blob: 39dc1af8dc468f6f9d6a6c12580094db6d28c11a [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
402 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700403};
404
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700405static const audio_usecase_t offload_usecases[] = {
406 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700407 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
408 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700415};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800416
Varun Balaraje49253e2017-07-06 19:48:56 +0530417static const audio_usecase_t interactive_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
426};
427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428#define STRING_TO_ENUM(string) { #string, string }
429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430struct string_to_enum {
431 const char *name;
432 uint32_t value;
433};
434
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700444 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
445 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
446 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
447 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455};
456
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457static const struct string_to_enum formats_name_to_enum_table[] = {
458 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
459 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
460 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700461 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
462 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
463 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700464 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800465 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
466 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800468};
469
470//list of all supported sample rates by HDMI specification.
471static const int out_hdmi_sample_rates[] = {
472 32000, 44100, 48000, 88200, 96000, 176400, 192000,
473};
474
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700475static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(32000),
477 STRING_TO_ENUM(44100),
478 STRING_TO_ENUM(48000),
479 STRING_TO_ENUM(88200),
480 STRING_TO_ENUM(96000),
481 STRING_TO_ENUM(176400),
482 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700483};
484
Carter Hsu2e429db2019-05-14 18:50:52 +0800485struct in_effect_list {
486 struct listnode list;
487 effect_handle_t handle;
488};
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
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700518static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
519 int flags __unused)
520{
521 int dir = 0;
522 switch (uc_id) {
523 case USECASE_AUDIO_RECORD_LOW_LATENCY:
524 dir = 1;
525 case USECASE_AUDIO_PLAYBACK_ULL:
526 break;
527 default:
528 return false;
529 }
530
531 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
532 PCM_PLAYBACK : PCM_CAPTURE);
533 if (adev->adm_is_noirq_avail)
534 return adev->adm_is_noirq_avail(adev->adm_data,
535 adev->snd_card, dev_id, dir);
536 return false;
537}
538
539static void register_out_stream(struct stream_out *out)
540{
541 struct audio_device *adev = out->dev;
542 if (is_offload_usecase(out->usecase) ||
543 !adev->adm_register_output_stream)
544 return;
545
546 // register stream first for backward compatibility
547 adev->adm_register_output_stream(adev->adm_data,
548 out->handle,
549 out->flags);
550
551 if (!adev->adm_set_config)
552 return;
553
554 if (out->realtime)
555 adev->adm_set_config(adev->adm_data,
556 out->handle,
557 out->pcm, &out->config);
558}
559
560static void register_in_stream(struct stream_in *in)
561{
562 struct audio_device *adev = in->dev;
563 if (!adev->adm_register_input_stream)
564 return;
565
566 adev->adm_register_input_stream(adev->adm_data,
567 in->capture_handle,
568 in->flags);
569
570 if (!adev->adm_set_config)
571 return;
572
573 if (in->realtime)
574 adev->adm_set_config(adev->adm_data,
575 in->capture_handle,
576 in->pcm,
577 &in->config);
578}
579
580static void request_out_focus(struct stream_out *out, long ns)
581{
582 struct audio_device *adev = out->dev;
583
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700584 if (adev->adm_request_focus_v2)
585 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
586 else if (adev->adm_request_focus)
587 adev->adm_request_focus(adev->adm_data, out->handle);
588}
589
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700590static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700591{
592 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700593 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700594
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700595 if (adev->adm_request_focus_v2_1)
596 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
597 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700598 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
599 else if (adev->adm_request_focus)
600 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700601
602 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700603}
604
605static void release_out_focus(struct stream_out *out)
606{
607 struct audio_device *adev = out->dev;
608
609 if (adev->adm_abandon_focus)
610 adev->adm_abandon_focus(adev->adm_data, out->handle);
611}
612
613static void release_in_focus(struct stream_in *in)
614{
615 struct audio_device *adev = in->dev;
616 if (adev->adm_abandon_focus)
617 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
618}
619
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530620static int parse_snd_card_status(struct str_parms *parms, int *card,
621 card_status_t *status)
622{
623 char value[32]={0};
624 char state[32]={0};
625
626 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
627 if (ret < 0)
628 return -1;
629
630 // sscanf should be okay as value is of max length 32.
631 // same as sizeof state.
632 if (sscanf(value, "%d,%s", card, state) < 2)
633 return -1;
634
635 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
636 CARD_STATUS_OFFLINE;
637 return 0;
638}
639
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700640static inline void adjust_frames_for_device_delay(struct stream_out *out,
641 uint32_t *dsp_frames) {
642 // Adjustment accounts for A2dp encoder latency with offload usecases
643 // Note: Encoder latency is returned in ms.
644 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
645 unsigned long offset =
646 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
647 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
648 }
649}
650
vivek mehtaa76401a2015-04-24 14:12:15 -0700651__attribute__ ((visibility ("default")))
652bool audio_hw_send_gain_dep_calibration(int level) {
653 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700654 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700655
656 pthread_mutex_lock(&adev_init_lock);
657
658 if (adev != NULL && adev->platform != NULL) {
659 pthread_mutex_lock(&adev->lock);
660 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700661
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530662 // cache level info for any of the use case which
663 // was not started.
664 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700665
vivek mehtaa76401a2015-04-24 14:12:15 -0700666 pthread_mutex_unlock(&adev->lock);
667 } else {
668 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
669 }
670
671 pthread_mutex_unlock(&adev_init_lock);
672
673 return ret_val;
674}
675
Ashish Jain5106d362016-05-11 19:23:33 +0530676static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
677{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800678 bool gapless_enabled = false;
679 const char *mixer_ctl_name = "Compress Gapless Playback";
680 struct mixer_ctl *ctl;
681
682 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700683 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530684
685 /*Disable gapless if its AV playback*/
686 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800687
688 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
689 if (!ctl) {
690 ALOGE("%s: Could not get ctl for mixer cmd - %s",
691 __func__, mixer_ctl_name);
692 return -EINVAL;
693 }
694
695 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
696 ALOGE("%s: Could not set gapless mode %d",
697 __func__, gapless_enabled);
698 return -EINVAL;
699 }
700 return 0;
701}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700702
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700703__attribute__ ((visibility ("default")))
704int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
705 int table_size) {
706 int ret_val = 0;
707 ALOGV("%s: enter ... ", __func__);
708
709 pthread_mutex_lock(&adev_init_lock);
710 if (adev == NULL) {
711 ALOGW("%s: adev is NULL .... ", __func__);
712 goto done;
713 }
714
715 pthread_mutex_lock(&adev->lock);
716 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
717 pthread_mutex_unlock(&adev->lock);
718done:
719 pthread_mutex_unlock(&adev_init_lock);
720 ALOGV("%s: exit ... ", __func__);
721 return ret_val;
722}
723
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800724bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800725{
726 bool ret = false;
727 ALOGV("%s: enter ...", __func__);
728
729 pthread_mutex_lock(&adev_init_lock);
730
731 if (adev != NULL && adev->platform != NULL) {
732 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800733 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800734 pthread_mutex_unlock(&adev->lock);
735 }
736
737 pthread_mutex_unlock(&adev_init_lock);
738
739 ALOGV("%s: exit with ret %d", __func__, ret);
740 return ret;
741}
Aalique Grahame22e49102018-12-18 14:23:57 -0800742
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700743static bool is_supported_format(audio_format_t format)
744{
Eric Laurent86e17132013-09-12 17:49:30 -0700745 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530746 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530747 format == AUDIO_FORMAT_AAC_LC ||
748 format == AUDIO_FORMAT_AAC_HE_V1 ||
749 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530750 format == AUDIO_FORMAT_AAC_ADTS_LC ||
751 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
752 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530753 format == AUDIO_FORMAT_AAC_LATM_LC ||
754 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
755 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530756 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
757 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530758 format == AUDIO_FORMAT_PCM_FLOAT ||
759 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700760 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530761 format == AUDIO_FORMAT_AC3 ||
762 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700763 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530764 format == AUDIO_FORMAT_DTS ||
765 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800766 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530767 format == AUDIO_FORMAT_ALAC ||
768 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530769 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530770 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800771 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530772 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700773 format == AUDIO_FORMAT_APTX ||
774 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800775 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700776
777 return false;
778}
779
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700780static inline bool is_mmap_usecase(audio_usecase_t uc_id)
781{
782 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
783 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
784}
785
Avinash Vaish71a8b972014-07-24 15:36:33 +0530786static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
787 struct audio_usecase *uc_info)
788{
789 struct listnode *node;
790 struct audio_usecase *usecase;
791
792 if (uc_info == NULL)
793 return -EINVAL;
794
795 /* Re-route all voice usecases on the shared backend other than the
796 specified usecase to new snd devices */
797 list_for_each(node, &adev->usecase_list) {
798 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800799 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530800 enable_audio_route(adev, usecase);
801 }
802 return 0;
803}
804
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530805static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530806{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530807 ALOGV("%s", __func__);
808 audio_route_apply_and_update_path(adev->audio_route,
809 "asrc-mode");
810 adev->asrc_mode_enabled = true;
811}
812
813static void disable_asrc_mode(struct audio_device *adev)
814{
815 ALOGV("%s", __func__);
816 audio_route_reset_and_update_path(adev->audio_route,
817 "asrc-mode");
818 adev->asrc_mode_enabled = false;
819}
820
821/*
822 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
823 * 44.1 or Native DSD backends are enabled for any of current use case.
824 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
825 * - Disable current mix path use case(Headphone backend) and re-enable it with
826 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
827 * e.g. Naitve DSD or Headphone 44.1 -> + 48
828 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530829static void check_and_set_asrc_mode(struct audio_device *adev,
830 struct audio_usecase *uc_info,
831 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530832{
833 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530834 int i, num_new_devices = 0;
835 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
836 /*
837 *Split snd device for new combo use case
838 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
839 */
840 if (platform_split_snd_device(adev->platform,
841 snd_device,
842 &num_new_devices,
843 split_new_snd_devices) == 0) {
844 for (i = 0; i < num_new_devices; i++)
845 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
846 } else {
847 int new_backend_idx = platform_get_backend_index(snd_device);
848 if (((new_backend_idx == HEADPHONE_BACKEND) ||
849 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
850 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
851 !adev->asrc_mode_enabled) {
852 struct listnode *node = NULL;
853 struct audio_usecase *uc = NULL;
854 struct stream_out *curr_out = NULL;
855 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
856 int i, num_devices, ret = 0;
857 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530858
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530859 list_for_each(node, &adev->usecase_list) {
860 uc = node_to_item(node, struct audio_usecase, list);
861 curr_out = (struct stream_out*) uc->stream.out;
862 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
863 /*
864 *Split snd device for existing combo use case
865 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
866 */
867 ret = platform_split_snd_device(adev->platform,
868 uc->out_snd_device,
869 &num_devices,
870 split_snd_devices);
871 if (ret < 0 || num_devices == 0) {
872 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
873 split_snd_devices[0] = uc->out_snd_device;
874 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800875 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530876 for (i = 0; i < num_devices; i++) {
877 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
878 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
879 if((new_backend_idx == HEADPHONE_BACKEND) &&
880 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
881 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
882 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
883 __func__);
884 enable_asrc_mode(adev);
885 break;
886 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
887 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
888 (usecase_backend_idx == HEADPHONE_BACKEND)) {
889 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
890 __func__);
891 disable_audio_route(adev, uc);
892 disable_snd_device(adev, uc->out_snd_device);
893 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
894 if (new_backend_idx == DSD_NATIVE_BACKEND)
895 audio_route_apply_and_update_path(adev->audio_route,
896 "hph-true-highquality-mode");
897 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
898 (curr_out->bit_width >= 24))
899 audio_route_apply_and_update_path(adev->audio_route,
900 "hph-highquality-mode");
901 enable_asrc_mode(adev);
902 enable_snd_device(adev, uc->out_snd_device);
903 enable_audio_route(adev, uc);
904 break;
905 }
906 }
907 // reset split devices count
908 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800909 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530910 if (adev->asrc_mode_enabled)
911 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530912 }
913 }
914 }
915}
916
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700917static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
918 struct audio_effect_config effect_config,
919 unsigned int param_value)
920{
921 char mixer_ctl_name[] = "Audio Effect";
922 struct mixer_ctl *ctl;
923 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800924 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700925
926 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
927 if (!ctl) {
928 ALOGE("%s: Could not get mixer ctl - %s",
929 __func__, mixer_ctl_name);
930 return -EINVAL;
931 }
932
933 set_values[0] = 1; //0:Rx 1:Tx
934 set_values[1] = in->app_type_cfg.app_type;
935 set_values[2] = (long)effect_config.module_id;
936 set_values[3] = (long)effect_config.instance_id;
937 set_values[4] = (long)effect_config.param_id;
938 set_values[5] = param_value;
939
940 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
941
942 return 0;
943
944}
945
946static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
947 int effect_type, unsigned int *param_value)
948{
949 int ret = 0;
950 struct audio_effect_config other_effect_config;
951 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800952 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700953
954 usecase = get_usecase_from_list(adev, in->usecase);
955 if (!usecase)
956 return -EINVAL;
957
958 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
959 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
960 if (ret < 0) {
961 ALOGE("%s Failed to get effect params %d", __func__, ret);
962 return ret;
963 }
964
965 if (module_id == other_effect_config.module_id) {
966 //Same module id for AEC/NS. Values need to be combined
967 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
968 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
969 *param_value |= other_effect_config.param_value;
970 }
971 }
972
973 return ret;
974}
975
976static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530977{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700978 struct audio_effect_config effect_config;
979 struct audio_usecase *usecase = NULL;
980 int ret = 0;
981 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -0800982 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700983
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800984 if(!voice_extn_is_dynamic_ecns_enabled())
985 return ENOSYS;
986
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700987 if (!in) {
988 ALOGE("%s: Invalid input stream", __func__);
989 return -EINVAL;
990 }
991
992 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
993
994 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800995 if (usecase == NULL) {
996 ALOGE("%s: Could not find the usecase (%d) in the list",
997 __func__, in->usecase);
998 return -EINVAL;
999 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001000
1001 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1002 if (ret < 0) {
1003 ALOGE("%s Failed to get module id %d", __func__, ret);
1004 return ret;
1005 }
1006 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1007 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1008
1009 if(enable)
1010 param_value = effect_config.param_value;
1011
1012 /*Special handling for AEC & NS effects Param values need to be
1013 updated if module ids are same*/
1014
1015 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1016 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1017 if (ret < 0)
1018 return ret;
1019 }
1020
1021 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1022
1023 return ret;
1024}
1025
1026static void check_and_enable_effect(struct audio_device *adev)
1027{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001028 if(!voice_extn_is_dynamic_ecns_enabled())
1029 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001030
Eric Laurent637e2d42018-11-15 12:24:31 -08001031 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032
Eric Laurent637e2d42018-11-15 12:24:31 -08001033 if (in != NULL && !in->standby) {
1034 if (in->enable_aec)
1035 enable_disable_effect(adev, EFFECT_AEC, true);
1036
1037 if (in->enable_ns &&
1038 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1039 enable_disable_effect(adev, EFFECT_NS, true);
1040 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041 }
1042}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001043
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001044int pcm_ioctl(struct pcm *pcm, int request, ...)
1045{
1046 va_list ap;
1047 void * arg;
1048 int pcm_fd = *(int*)pcm;
1049
1050 va_start(ap, request);
1051 arg = va_arg(ap, void *);
1052 va_end(ap);
1053
1054 return ioctl(pcm_fd, request, arg);
1055}
1056
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001057int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001058 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001061 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301062 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301063 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001064
1065 if (usecase == NULL)
1066 return -EINVAL;
1067
1068 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1069
Carter Hsu2e429db2019-05-14 18:50:52 +08001070 if (usecase->type == PCM_CAPTURE) {
1071 struct stream_in *in = usecase->stream.in;
1072 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001074
1075 if (in) {
1076 if (in->enable_aec || in->enable_ec_port) {
1077 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1078 struct listnode *node;
1079 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1080 USECASE_AUDIO_PLAYBACK_VOIP);
1081 if (voip_usecase) {
1082 out_device = voip_usecase->stream.out->devices;
1083 } else if (adev->primary_output &&
1084 !adev->primary_output->standby) {
1085 out_device = adev->primary_output->devices;
1086 } else {
1087 list_for_each(node, &adev->usecase_list) {
1088 uinfo = node_to_item(node, struct audio_usecase, list);
1089 if (uinfo->type != PCM_CAPTURE) {
1090 out_device = uinfo->stream.out->devices;
1091 break;
1092 }
1093 }
1094 }
1095 platform_set_echo_reference(adev, true, out_device);
1096 in->ec_opened = true;
1097 }
1098 }
1099 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1100 snd_device = usecase->in_snd_device;
1101 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001103 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001104
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001105#ifdef DS1_DOLBY_DAP_ENABLED
1106 audio_extn_dolby_set_dmid(adev);
1107 audio_extn_dolby_set_endpoint(adev);
1108#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001109 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001110 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301111 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001112 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001113 if (audio_extn_is_maxx_audio_enabled())
1114 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301115 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301116 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1117 out = usecase->stream.out;
1118 if (out && out->compr)
1119 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1120 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301121 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301122
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: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301129 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1130 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1131 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1132 if (parms) {
1133 audio_extn_fm_set_parameters(adev, parms);
1134 str_parms_destroy(parms);
1135 }
1136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001137 ALOGV("%s: exit", __func__);
1138 return 0;
1139}
1140
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001141int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001142 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001143{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001145 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001146
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301147 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001148 return -EINVAL;
1149
1150 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301151 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 snd_device = usecase->in_snd_device;
1153 else
1154 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001155 // we shouldn't truncate mixer_path
1156 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1157 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1158 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001159 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001160 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001161 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001162 if (usecase->type == PCM_CAPTURE) {
1163 struct stream_in *in = usecase->stream.in;
1164 if (in && in->ec_opened) {
1165 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1166 in->ec_opened = false;
1167 }
1168 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001169 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301170 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301171 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001172 if ((usecase->type == PCM_PLAYBACK) &&
1173 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301174 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175 ALOGV("%s: exit", __func__);
1176 return 0;
1177}
1178
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001179int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001180 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301182 int i, num_devices = 0;
1183 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001184 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1185
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001186 if (snd_device < SND_DEVICE_MIN ||
1187 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001188 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001189 return -EINVAL;
1190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001192 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001193 ALOGE("%s: Invalid sound device returned", __func__);
1194 return -EINVAL;
1195 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001196
1197 adev->snd_dev_ref_cnt[snd_device]++;
1198
1199 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1200 (platform_split_snd_device(adev->platform,
1201 snd_device,
1202 &num_devices,
1203 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001204 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001205 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001206 return 0;
1207 }
1208
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001209 if (audio_extn_spkr_prot_is_enabled())
1210 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001211
Aalique Grahame22e49102018-12-18 14:23:57 -08001212 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1213
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001214 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1215 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001216 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1217 goto err;
1218 }
1219 audio_extn_dev_arbi_acquire(snd_device);
1220 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001221 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001222 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001223 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001224 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001225 } else if (platform_split_snd_device(adev->platform,
1226 snd_device,
1227 &num_devices,
1228 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301229 for (i = 0; i < num_devices; i++) {
1230 enable_snd_device(adev, new_snd_devices[i]);
1231 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001232 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001233 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001234 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301235
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301236
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001237 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1238 (audio_extn_a2dp_start_playback() < 0)) {
1239 ALOGE(" fail to configure A2dp Source control path ");
1240 goto err;
1241 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001242
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001243 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1244 (audio_extn_a2dp_start_capture() < 0)) {
1245 ALOGE(" fail to configure A2dp Sink control path ");
1246 goto err;
1247 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301248
Zhou Song12c29502019-03-16 10:37:18 +08001249 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1250 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1251 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1252 (audio_extn_sco_start_configuration() < 0)) {
1253 ALOGE(" fail to configure sco control path ");
1254 goto err;
1255 }
1256
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001257 /* due to the possibility of calibration overwrite between listen
1258 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001259 audio_extn_sound_trigger_update_device_status(snd_device,
1260 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301261 audio_extn_listen_update_device_status(snd_device,
1262 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001263 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001264 audio_extn_sound_trigger_update_device_status(snd_device,
1265 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301266 audio_extn_listen_update_device_status(snd_device,
1267 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001268 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001269 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001270 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001271 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301272
1273 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1274 !adev->native_playback_enabled &&
1275 audio_is_true_native_stream_active(adev)) {
1276 ALOGD("%s: %d: napb: enabling native mode in hardware",
1277 __func__, __LINE__);
1278 audio_route_apply_and_update_path(adev->audio_route,
1279 "true-native-mode");
1280 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301281 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301282 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1283 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001284 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001285 ALOGD("%s: init ec ref loopback", __func__);
1286 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1287 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001290err:
1291 adev->snd_dev_ref_cnt[snd_device]--;
1292 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293}
1294
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001295int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001296 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301298 int i, num_devices = 0;
1299 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001300 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1301
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001302 if (snd_device < SND_DEVICE_MIN ||
1303 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001304 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001305 return -EINVAL;
1306 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001307
1308 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1309 ALOGE("%s: Invalid sound device returned", __func__);
1310 return -EINVAL;
1311 }
1312
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1314 ALOGE("%s: device ref cnt is already 0", __func__);
1315 return -EINVAL;
1316 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001317
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001318 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001319
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001320
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001321 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001322 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301323
Aalique Grahame22e49102018-12-18 14:23:57 -08001324 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1325
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001326 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1327 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001328 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001329
1330 // when speaker device is disabled, reset swap.
1331 // will be renabled on usecase start
1332 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001333 } else if (platform_split_snd_device(adev->platform,
1334 snd_device,
1335 &num_devices,
1336 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301337 for (i = 0; i < num_devices; i++) {
1338 disable_snd_device(adev, new_snd_devices[i]);
1339 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001340 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001341 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001342 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001343 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001344
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001345 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301346 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001347 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001348 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001349 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001350 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301351 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001352 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301353 adev->native_playback_enabled) {
1354 ALOGD("%s: %d: napb: disabling native mode in hardware",
1355 __func__, __LINE__);
1356 audio_route_reset_and_update_path(adev->audio_route,
1357 "true-native-mode");
1358 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001359 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301360 adev->asrc_mode_enabled) {
1361 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301362 disable_asrc_mode(adev);
1363 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001364 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301365 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001366 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001367 ALOGD("%s: deinit ec ref loopback", __func__);
1368 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1369 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001370
1371 audio_extn_utils_release_snd_device(snd_device);
1372 } else {
1373 if (platform_split_snd_device(adev->platform,
1374 snd_device,
1375 &num_devices,
1376 new_snd_devices) == 0) {
1377 for (i = 0; i < num_devices; i++) {
1378 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1379 }
1380 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001381 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383 return 0;
1384}
1385
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001386/*
1387 legend:
1388 uc - existing usecase
1389 new_uc - new usecase
1390 d1, d11, d2 - SND_DEVICE enums
1391 a1, a2 - corresponding ANDROID device enums
1392 B1, B2 - backend strings
1393
1394case 1
1395 uc->dev d1 (a1) B1
1396 new_uc->dev d1 (a1), d2 (a2) B1, B2
1397
1398 resolution: disable and enable uc->dev on d1
1399
1400case 2
1401 uc->dev d1 (a1) B1
1402 new_uc->dev d11 (a1) B1
1403
1404 resolution: need to switch uc since d1 and d11 are related
1405 (e.g. speaker and voice-speaker)
1406 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1407
1408case 3
1409 uc->dev d1 (a1) B1
1410 new_uc->dev d2 (a2) B2
1411
1412 resolution: no need to switch uc
1413
1414case 4
1415 uc->dev d1 (a1) B1
1416 new_uc->dev d2 (a2) B1
1417
1418 resolution: disable enable uc-dev on d2 since backends match
1419 we cannot enable two streams on two different devices if they
1420 share the same backend. e.g. if offload is on speaker device using
1421 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1422 using the same backend, offload must also be switched to voice-handset.
1423
1424case 5
1425 uc->dev d1 (a1) B1
1426 new_uc->dev d1 (a1), d2 (a2) B1
1427
1428 resolution: disable enable uc-dev on d2 since backends match
1429 we cannot enable two streams on two different devices if they
1430 share the same backend.
1431
1432case 6
1433 uc->dev d1 (a1) B1
1434 new_uc->dev d2 (a1) B2
1435
1436 resolution: no need to switch
1437
1438case 7
1439 uc->dev d1 (a1), d2 (a2) B1, B2
1440 new_uc->dev d1 (a1) B1
1441
1442 resolution: no need to switch
1443
Zhou Song4ba65882018-07-09 14:48:07 +08001444case 8
1445 uc->dev d1 (a1) B1
1446 new_uc->dev d11 (a1), d2 (a2) B1, B2
1447 resolution: compared to case 1, for this case, d1 and d11 are related
1448 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001449*/
1450static snd_device_t derive_playback_snd_device(void * platform,
1451 struct audio_usecase *uc,
1452 struct audio_usecase *new_uc,
1453 snd_device_t new_snd_device)
1454{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301455 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001456
1457 snd_device_t d1 = uc->out_snd_device;
1458 snd_device_t d2 = new_snd_device;
1459
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301460 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301461 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301462 a1 = uc->stream.inout->out_config.devices;
1463 a2 = new_uc->stream.inout->out_config.devices;
1464 break;
1465 default :
1466 a1 = uc->stream.out->devices;
1467 a2 = new_uc->stream.out->devices;
1468 break;
1469 }
1470
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001471 // Treat as a special case when a1 and a2 are not disjoint
1472 if ((a1 != a2) && (a1 & a2)) {
1473 snd_device_t d3[2];
1474 int num_devices = 0;
1475 int ret = platform_split_snd_device(platform,
1476 popcount(a1) > 1 ? d1 : d2,
1477 &num_devices,
1478 d3);
1479 if (ret < 0) {
1480 if (ret != -ENOSYS) {
1481 ALOGW("%s failed to split snd_device %d",
1482 __func__,
1483 popcount(a1) > 1 ? d1 : d2);
1484 }
1485 goto end;
1486 }
1487
1488 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1489 // But if it does happen, we need to give priority to d2 if
1490 // the combo devices active on the existing usecase share a backend.
1491 // This is because we cannot have a usecase active on a combo device
1492 // and a new usecase requests one device in this combo pair.
1493 if (platform_check_backends_match(d3[0], d3[1])) {
1494 return d2; // case 5
1495 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001496 // check if d1 is related to any of d3's
1497 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001498 return d1; // case 1
1499 else
1500 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001501 }
1502 } else {
1503 if (platform_check_backends_match(d1, d2)) {
1504 return d2; // case 2, 4
1505 } else {
1506 return d1; // case 6, 3
1507 }
1508 }
1509
1510end:
1511 return d2; // return whatever was calculated before.
1512}
1513
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001514static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301515 struct audio_usecase *uc_info,
1516 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517{
1518 struct listnode *node;
1519 struct audio_usecase *usecase;
1520 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301521 snd_device_t uc_derive_snd_device;
1522 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001523 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1524 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001525 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301526 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 /*
1528 * This function is to make sure that all the usecases that are active on
1529 * the hardware codec backend are always routed to any one device that is
1530 * handled by the hardware codec.
1531 * For example, if low-latency and deep-buffer usecases are currently active
1532 * on speaker and out_set_parameters(headset) is received on low-latency
1533 * output, then we have to make sure deep-buffer is also switched to headset,
1534 * because of the limitation that both the devices cannot be enabled
1535 * at the same time as they share the same backend.
1536 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001537 /*
1538 * This call is to check if we need to force routing for a particular stream
1539 * If there is a backend configuration change for the device when a
1540 * new stream starts, then ADM needs to be closed and re-opened with the new
1541 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001542 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001543 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001544 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1545 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301546 /* For a2dp device reconfigure all active sessions
1547 * with new AFE encoder format based on a2dp state
1548 */
1549 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1550 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1551 audio_extn_a2dp_is_force_device_switch()) {
1552 force_routing = true;
1553 force_restart_session = true;
1554 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301555 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001558 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001559 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1561 switch_device[i] = false;
1562
1563 list_for_each(node, &adev->usecase_list) {
1564 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001565
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301566 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1567 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301568 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301569 platform_get_snd_device_name(usecase->out_snd_device),
1570 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301571 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1572 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1573 usecase, uc_info, snd_device);
1574 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1575 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1576 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1577 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001578 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301579 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1580 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1581 ((force_restart_session) ||
1582 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301583 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1584 __func__, use_case_table[usecase->id],
1585 platform_get_snd_device_name(usecase->out_snd_device));
1586 disable_audio_route(adev, usecase);
1587 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301588 /* Enable existing usecase on derived playback device */
1589 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301590 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301591 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 }
1593 }
1594
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301595 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1596 num_uc_to_switch);
1597
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001598 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001599 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001600
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301601 /* Make sure the previous devices to be disabled first and then enable the
1602 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 list_for_each(node, &adev->usecase_list) {
1604 usecase = node_to_item(node, struct audio_usecase, list);
1605 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001606 /* Check if output sound device to be switched can be split and if any
1607 of the split devices match with derived sound device */
1608 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1609 &num_devices, split_snd_devices) == 0) {
1610 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1611 for (i = 0; i < num_devices; i++) {
1612 /* Disable devices that do not match with derived sound device */
1613 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1614 disable_snd_device(adev, split_snd_devices[i]);
1615 }
1616 } else {
1617 disable_snd_device(adev, usecase->out_snd_device);
1618 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 }
1620 }
1621
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001622 list_for_each(node, &adev->usecase_list) {
1623 usecase = node_to_item(node, struct audio_usecase, list);
1624 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001625 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1626 &num_devices, split_snd_devices) == 0) {
1627 /* Enable derived sound device only if it does not match with
1628 one of the split sound devices. This is because the matching
1629 sound device was not disabled */
1630 bool should_enable = true;
1631 for (i = 0; i < num_devices; i++) {
1632 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1633 should_enable = false;
1634 break;
1635 }
1636 }
1637 if (should_enable)
1638 enable_snd_device(adev, derive_snd_device[usecase->id]);
1639 } else {
1640 enable_snd_device(adev, derive_snd_device[usecase->id]);
1641 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001642 }
1643 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001645 /* Re-route all the usecases on the shared backend other than the
1646 specified usecase to new snd devices */
1647 list_for_each(node, &adev->usecase_list) {
1648 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301649 /* Update the out_snd_device only before enabling the audio route */
1650 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301651 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301652 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301653 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301654 use_case_table[usecase->id],
1655 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001656 /* Update voc calibration before enabling VoIP route */
1657 if (usecase->type == VOIP_CALL)
1658 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001659 usecase->out_snd_device,
1660 platform_get_input_snd_device(
1661 adev->platform, NULL,
1662 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301663 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301664 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001665 out_set_voip_volume(&usecase->stream.out->stream,
1666 usecase->stream.out->volume_l,
1667 usecase->stream.out->volume_r);
1668 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301669 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 }
1671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001672 }
1673}
1674
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301675static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001676 struct audio_usecase *uc_info,
1677 snd_device_t snd_device)
1678{
1679 struct listnode *node;
1680 struct audio_usecase *usecase;
1681 bool switch_device[AUDIO_USECASE_MAX];
1682 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301683 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001684 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001685
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301686 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1687 snd_device);
1688 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301689
1690 /*
1691 * Make sure out devices is checked against out codec backend device and
1692 * also in devices against in codec backend. Checking out device against in
1693 * codec backend or vice versa causes issues.
1694 */
1695 if (uc_info->type == PCM_CAPTURE)
1696 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001697 /*
1698 * This function is to make sure that all the active capture usecases
1699 * are always routed to the same input sound device.
1700 * For example, if audio-record and voice-call usecases are currently
1701 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1702 * is received for voice call then we have to make sure that audio-record
1703 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1704 * because of the limitation that two devices cannot be enabled
1705 * at the same time if they share the same backend.
1706 */
1707 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1708 switch_device[i] = false;
1709
1710 list_for_each(node, &adev->usecase_list) {
1711 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301712 /*
1713 * TODO: Enhance below condition to handle BT sco/USB multi recording
1714 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001715 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001716 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301717 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301718 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301719 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301720 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001721 ((uc_info->type == VOICE_CALL &&
1722 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1723 platform_check_backends_match(snd_device,\
1724 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001725 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001726 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1727 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001728 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001729 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001730 switch_device[usecase->id] = true;
1731 num_uc_to_switch++;
1732 }
1733 }
1734
1735 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001736 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001737
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301738 /* Make sure the previous devices to be disabled first and then enable the
1739 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001740 list_for_each(node, &adev->usecase_list) {
1741 usecase = node_to_item(node, struct audio_usecase, list);
1742 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001743 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001744 }
1745 }
1746
1747 list_for_each(node, &adev->usecase_list) {
1748 usecase = node_to_item(node, struct audio_usecase, list);
1749 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001750 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001751 }
1752 }
1753
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001754 /* Re-route all the usecases on the shared backend other than the
1755 specified usecase to new snd devices */
1756 list_for_each(node, &adev->usecase_list) {
1757 usecase = node_to_item(node, struct audio_usecase, list);
1758 /* Update the in_snd_device only before enabling the audio route */
1759 if (switch_device[usecase->id] ) {
1760 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001761 if (usecase->type != VOICE_CALL) {
1762 /* Update voc calibration before enabling VoIP route */
1763 if (usecase->type == VOIP_CALL)
1764 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001765 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001766 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301767 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001768 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001769 }
1770 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001771 }
1772}
1773
Mingming Yin3a941d42016-02-17 18:08:05 -08001774static void reset_hdmi_sink_caps(struct stream_out *out) {
1775 int i = 0;
1776
1777 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1778 out->supported_channel_masks[i] = 0;
1779 }
1780 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1781 out->supported_formats[i] = 0;
1782 }
1783 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1784 out->supported_sample_rates[i] = 0;
1785 }
1786}
1787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001789static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790{
Mingming Yin3a941d42016-02-17 18:08:05 -08001791 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001792 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793
Mingming Yin3a941d42016-02-17 18:08:05 -08001794 reset_hdmi_sink_caps(out);
1795
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001796 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001797 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001798 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001799 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001800 }
1801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001804 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001805 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001806 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1807 case 6:
1808 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1809 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1810 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1811 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1812 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1813 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 break;
1815 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001816 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001817 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 break;
1819 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001820
1821 // check channel format caps
1822 i = 0;
1823 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1824 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1825 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1826 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1827 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1828 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1829 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1830 }
1831
Ben Romberger1aaaf862017-04-06 17:49:46 -07001832 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1833 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1834 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1835 }
1836
Mingming Yin3a941d42016-02-17 18:08:05 -08001837 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1838 ALOGV(":%s HDMI supports DTS format", __func__);
1839 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1840 }
1841
1842 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1843 ALOGV(":%s HDMI supports DTS HD format", __func__);
1844 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1845 }
1846
Naresh Tanniru928f0862017-04-07 16:44:23 -07001847 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1848 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1849 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1850 }
1851
Mingming Yin3a941d42016-02-17 18:08:05 -08001852
1853 // check sample rate caps
1854 i = 0;
1855 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1856 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1857 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1858 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1859 }
1860 }
1861
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001862 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863}
1864
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001865static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1866 uint32_t *supported_sample_rates __unused,
1867 uint32_t max_rates __unused)
1868{
1869 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1870 supported_sample_rates,
1871 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301872 ssize_t i = 0;
1873
1874 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001875 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1876 supported_sample_rates[i]);
1877 }
1878 return count;
1879}
1880
1881static inline int read_usb_sup_channel_masks(bool is_playback,
1882 audio_channel_mask_t *supported_channel_masks,
1883 uint32_t max_masks)
1884{
1885 int channels = audio_extn_usb_get_max_channels(is_playback);
1886 int channel_count;
1887 uint32_t num_masks = 0;
1888 if (channels > MAX_HIFI_CHANNEL_COUNT)
1889 channels = MAX_HIFI_CHANNEL_COUNT;
1890
1891 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001892 // start from 2 channels as framework currently doesn't support mono.
1893 if (channels >= FCC_2) {
1894 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1895 }
1896 for (channel_count = FCC_2;
1897 channel_count <= channels && num_masks < max_masks;
1898 ++channel_count) {
1899 supported_channel_masks[num_masks++] =
1900 audio_channel_mask_for_index_assignment_from_count(channel_count);
1901 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001902 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001903 // For capture we report all supported channel masks from 1 channel up.
1904 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001905 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1906 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001907 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1908 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1909 if (channel_count <= FCC_2) {
1910 mask = audio_channel_in_mask_from_count(channel_count);
1911 supported_channel_masks[num_masks++] = mask;
1912 }
1913 const audio_channel_mask_t index_mask =
1914 audio_channel_mask_for_index_assignment_from_count(channel_count);
1915 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1916 supported_channel_masks[num_masks++] = index_mask;
1917 }
1918 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001919 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301920
vincenttewf51c94e2019-05-07 10:28:53 +08001921 for (size_t i = 0; i < num_masks; ++i) {
1922 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1923 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301924 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001925 return num_masks;
1926}
1927
1928static inline int read_usb_sup_formats(bool is_playback __unused,
1929 audio_format_t *supported_formats,
1930 uint32_t max_formats __unused)
1931{
1932 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1933 switch (bitwidth) {
1934 case 24:
1935 // XXX : usb.c returns 24 for s24 and s24_le?
1936 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1937 break;
1938 case 32:
1939 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1940 break;
1941 case 16:
1942 default :
1943 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1944 break;
1945 }
1946 ALOGV("%s: %s supported format %d", __func__,
1947 is_playback ? "P" : "C", bitwidth);
1948 return 1;
1949}
1950
1951static inline int read_usb_sup_params_and_compare(bool is_playback,
1952 audio_format_t *format,
1953 audio_format_t *supported_formats,
1954 uint32_t max_formats,
1955 audio_channel_mask_t *mask,
1956 audio_channel_mask_t *supported_channel_masks,
1957 uint32_t max_masks,
1958 uint32_t *rate,
1959 uint32_t *supported_sample_rates,
1960 uint32_t max_rates) {
1961 int ret = 0;
1962 int num_formats;
1963 int num_masks;
1964 int num_rates;
1965 int i;
1966
1967 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1968 max_formats);
1969 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1970 max_masks);
1971
1972 num_rates = read_usb_sup_sample_rates(is_playback,
1973 supported_sample_rates, max_rates);
1974
1975#define LUT(table, len, what, dflt) \
1976 for (i=0; i<len && (table[i] != what); i++); \
1977 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1978
1979 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1980 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1981 LUT(supported_sample_rates, num_rates, *rate, 0);
1982
1983#undef LUT
1984 return ret < 0 ? -EINVAL : 0; // HACK TBD
1985}
1986
Alexy Josephb1379942016-01-29 15:49:38 -08001987audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001988 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001989{
1990 struct audio_usecase *usecase;
1991 struct listnode *node;
1992
1993 list_for_each(node, &adev->usecase_list) {
1994 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001995 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001996 ALOGV("%s: usecase id %d", __func__, usecase->id);
1997 return usecase->id;
1998 }
1999 }
2000 return USECASE_INVALID;
2001}
2002
Alexy Josephb1379942016-01-29 15:49:38 -08002003struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002004 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002005{
2006 struct audio_usecase *usecase;
2007 struct listnode *node;
2008
2009 list_for_each(node, &adev->usecase_list) {
2010 usecase = node_to_item(node, struct audio_usecase, list);
2011 if (usecase->id == uc_id)
2012 return usecase;
2013 }
2014 return NULL;
2015}
2016
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302017/*
2018 * is a true native playback active
2019 */
2020bool audio_is_true_native_stream_active(struct audio_device *adev)
2021{
2022 bool active = false;
2023 int i = 0;
2024 struct listnode *node;
2025
2026 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2027 ALOGV("%s:napb: not in true mode or non hdphones device",
2028 __func__);
2029 active = false;
2030 goto exit;
2031 }
2032
2033 list_for_each(node, &adev->usecase_list) {
2034 struct audio_usecase *uc;
2035 uc = node_to_item(node, struct audio_usecase, list);
2036 struct stream_out *curr_out =
2037 (struct stream_out*) uc->stream.out;
2038
2039 if (curr_out && PCM_PLAYBACK == uc->type) {
2040 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2041 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2042 uc->id, curr_out->sample_rate,
2043 curr_out->bit_width,
2044 platform_get_snd_device_name(uc->out_snd_device));
2045
2046 if (is_offload_usecase(uc->id) &&
2047 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2048 active = true;
2049 ALOGD("%s:napb:native stream detected", __func__);
2050 }
2051 }
2052 }
2053exit:
2054 return active;
2055}
2056
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002057uint32_t adev_get_dsp_bit_width_enforce_mode()
2058{
2059 if (adev == NULL) {
2060 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2061 return 0;
2062 }
2063 return adev->dsp_bit_width_enforce_mode;
2064}
2065
2066static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2067{
2068 char value[PROPERTY_VALUE_MAX];
2069 int trial;
2070 uint32_t dsp_bit_width_enforce_mode = 0;
2071
2072 if (!mixer) {
2073 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2074 __func__);
2075 return 0;
2076 }
2077
2078 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2079 value, NULL) > 0) {
2080 trial = atoi(value);
2081 switch (trial) {
2082 case 16:
2083 dsp_bit_width_enforce_mode = 16;
2084 break;
2085 case 24:
2086 dsp_bit_width_enforce_mode = 24;
2087 break;
2088 case 32:
2089 dsp_bit_width_enforce_mode = 32;
2090 break;
2091 default:
2092 dsp_bit_width_enforce_mode = 0;
2093 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2094 break;
2095 }
2096 }
2097
2098 return dsp_bit_width_enforce_mode;
2099}
2100
2101static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2102 uint32_t enforce_mode,
2103 bool enable)
2104{
2105 struct mixer_ctl *ctl = NULL;
2106 const char *mixer_ctl_name = "ASM Bit Width";
2107 uint32_t asm_bit_width_mode = 0;
2108
2109 if (enforce_mode == 0) {
2110 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2111 return;
2112 }
2113
2114 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2115 if (!ctl) {
2116 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2117 __func__, mixer_ctl_name);
2118 return;
2119 }
2120
2121 if (enable)
2122 asm_bit_width_mode = enforce_mode;
2123 else
2124 asm_bit_width_mode = 0;
2125
2126 ALOGV("%s DSP bit width feature status is %d width=%d",
2127 __func__, enable, asm_bit_width_mode);
2128 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2129 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2130 asm_bit_width_mode);
2131
2132 return;
2133}
2134
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302135/*
2136 * if native DSD playback active
2137 */
2138bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2139{
2140 bool active = false;
2141 struct listnode *node = NULL;
2142 struct audio_usecase *uc = NULL;
2143 struct stream_out *curr_out = NULL;
2144
2145 list_for_each(node, &adev->usecase_list) {
2146 uc = node_to_item(node, struct audio_usecase, list);
2147 curr_out = (struct stream_out*) uc->stream.out;
2148
2149 if (curr_out && PCM_PLAYBACK == uc->type &&
2150 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2151 active = true;
2152 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302153 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302154 }
2155 }
2156 return active;
2157}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302158
2159static bool force_device_switch(struct audio_usecase *usecase)
2160{
2161 bool ret = false;
2162 bool is_it_true_mode = false;
2163
Zhou Song30f2c3e2018-02-08 14:02:15 +08002164 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302165 usecase->type == TRANSCODE_LOOPBACK_RX ||
2166 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002167 return false;
2168 }
2169
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002170 if(usecase->stream.out == NULL) {
2171 ALOGE("%s: stream.out is NULL", __func__);
2172 return false;
2173 }
2174
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302175 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002176 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2177 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2178 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302179 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2180 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2181 (!is_it_true_mode && adev->native_playback_enabled)){
2182 ret = true;
2183 ALOGD("napb: time to toggle native mode");
2184 }
2185 }
2186
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302187 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302188 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2189 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002190 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302191 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302192 ALOGD("Force a2dp device switch to update new encoder config");
2193 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002194 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302195
Florian Pfister1a84f312018-07-19 14:38:18 +02002196 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302197 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2198 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002199 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302200 return ret;
2201}
2202
Aalique Grahame22e49102018-12-18 14:23:57 -08002203static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2204{
2205 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2206}
2207
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302208bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2209{
2210 bool ret=false;
2211 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2212 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2213 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2214 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2215 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2216 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2217 ret = true;
2218
2219 return ret;
2220}
2221
2222bool is_a2dp_device(snd_device_t out_snd_device)
2223{
2224 bool ret=false;
2225 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2226 ret = true;
2227
2228 return ret;
2229}
2230
2231bool is_bt_soc_on(struct audio_device *adev)
2232{
2233 struct mixer_ctl *ctl;
2234 char *mixer_ctl_name = "BT SOC status";
2235 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2236 bool bt_soc_status = true;
2237 if (!ctl) {
2238 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2239 __func__, mixer_ctl_name);
2240 /*This is to ensure we dont break targets which dont have the kernel change*/
2241 return true;
2242 }
2243 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2244 ALOGD("BT SOC status: %d",bt_soc_status);
2245 return bt_soc_status;
2246}
2247
2248int out_standby_l(struct audio_stream *stream);
2249
Eric Laurent637e2d42018-11-15 12:24:31 -08002250struct stream_in *adev_get_active_input(const struct audio_device *adev)
2251{
2252 struct listnode *node;
2253 struct stream_in *last_active_in = NULL;
2254
2255 /* Get last added active input.
2256 * TODO: We may use a priority mechanism to pick highest priority active source */
2257 list_for_each(node, &adev->usecase_list)
2258 {
2259 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2260 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2261 last_active_in = usecase->stream.in;
2262 }
2263
2264 return last_active_in;
2265}
2266
2267struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2268{
2269 struct listnode *node;
2270
2271 /* First check active inputs with voice communication source and then
2272 * any input if audio mode is in communication */
2273 list_for_each(node, &adev->usecase_list)
2274 {
2275 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2276 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2277 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2278 return usecase->stream.in;
2279 }
2280 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2281 return adev_get_active_input(adev);
2282
2283 return NULL;
2284}
2285
Carter Hsu2e429db2019-05-14 18:50:52 +08002286/*
2287 * Aligned with policy.h
2288 */
2289static inline int source_priority(int inputSource)
2290{
2291 switch (inputSource) {
2292 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2293 return 9;
2294 case AUDIO_SOURCE_CAMCORDER:
2295 return 8;
2296 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2297 return 7;
2298 case AUDIO_SOURCE_UNPROCESSED:
2299 return 6;
2300 case AUDIO_SOURCE_MIC:
2301 return 5;
2302 case AUDIO_SOURCE_ECHO_REFERENCE:
2303 return 4;
2304 case AUDIO_SOURCE_FM_TUNER:
2305 return 3;
2306 case AUDIO_SOURCE_VOICE_RECOGNITION:
2307 return 2;
2308 case AUDIO_SOURCE_HOTWORD:
2309 return 1;
2310 default:
2311 break;
2312 }
2313 return 0;
2314}
2315
2316static struct stream_in *get_priority_input(struct audio_device *adev)
2317{
2318 struct listnode *node;
2319 struct audio_usecase *usecase;
2320 int last_priority = 0, priority;
2321 struct stream_in *priority_in = NULL;
2322 struct stream_in *in;
2323
2324 list_for_each(node, &adev->usecase_list) {
2325 usecase = node_to_item(node, struct audio_usecase, list);
2326 if (usecase->type == PCM_CAPTURE) {
2327 in = usecase->stream.in;
2328 if (!in)
2329 continue;
2330 priority = source_priority(in->source);
2331
2332 if (priority > last_priority) {
2333 last_priority = priority;
2334 priority_in = in;
2335 }
2336 }
2337 }
2338 return priority_in;
2339}
2340
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002341int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002343 snd_device_t out_snd_device = SND_DEVICE_NONE;
2344 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002345 struct audio_usecase *usecase = NULL;
2346 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002347 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002348 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302349 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002350 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002351 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302353 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2354
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002355 usecase = get_usecase_from_list(adev, uc_id);
2356 if (usecase == NULL) {
2357 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2358 return -EINVAL;
2359 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002361 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002362 (usecase->type == VOIP_CALL) ||
2363 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302364 if(usecase->stream.out == NULL) {
2365 ALOGE("%s: stream.out is NULL", __func__);
2366 return -EINVAL;
2367 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002368 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002369 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002370 in_snd_device = platform_get_input_snd_device(adev->platform,
2371 NULL,
2372 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002373 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302374 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302375 if (usecase->stream.inout == NULL) {
2376 ALOGE("%s: stream.inout is NULL", __func__);
2377 return -EINVAL;
2378 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302379 stream_out.devices = usecase->stream.inout->out_config.devices;
2380 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2381 stream_out.format = usecase->stream.inout->out_config.format;
2382 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2383 out_snd_device = platform_get_output_snd_device(adev->platform,
2384 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302385 usecase->devices = out_snd_device;
2386 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2387 if (usecase->stream.inout == NULL) {
2388 ALOGE("%s: stream.inout is NULL", __func__);
2389 return -EINVAL;
2390 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002391 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302392 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002393 } else {
2394 /*
2395 * If the voice call is active, use the sound devices of voice call usecase
2396 * so that it would not result any device switch. All the usecases will
2397 * be switched to new device when select_devices() is called for voice call
2398 * usecase. This is to avoid switching devices for voice call when
2399 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002400 * choose voice call device only if the use case device is
2401 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002402 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002403 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002404 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002405 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002406 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2407 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302408 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2409 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002410 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2411 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002412 in_snd_device = vc_usecase->in_snd_device;
2413 out_snd_device = vc_usecase->out_snd_device;
2414 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002415 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002416 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002417 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002418 if ((voip_usecase != NULL) &&
2419 (usecase->type == PCM_PLAYBACK) &&
2420 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002421 out_snd_device_backend_match = platform_check_backends_match(
2422 voip_usecase->out_snd_device,
2423 platform_get_output_snd_device(
2424 adev->platform,
2425 usecase->stream.out));
2426 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002427 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002428 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2429 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002430 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002431 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002432 in_snd_device = voip_usecase->in_snd_device;
2433 out_snd_device = voip_usecase->out_snd_device;
2434 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002435 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002436 hfp_ucid = audio_extn_hfp_get_usecase();
2437 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002438 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002439 in_snd_device = hfp_usecase->in_snd_device;
2440 out_snd_device = hfp_usecase->out_snd_device;
2441 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002442 }
2443 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302444 if (usecase->stream.out == NULL) {
2445 ALOGE("%s: stream.out is NULL", __func__);
2446 return -EINVAL;
2447 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002448 usecase->devices = usecase->stream.out->devices;
2449 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002450 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002451 struct stream_out *voip_out = adev->primary_output;
2452 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002453 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002454 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002455 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002456
Eric Laurent637e2d42018-11-15 12:24:31 -08002457 if (voip_usecase)
2458 voip_out = voip_usecase->stream.out;
2459
2460 if (usecase->stream.out == voip_out && voip_in != NULL)
2461 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002462 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002463 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302464 if (usecase->stream.in == NULL) {
2465 ALOGE("%s: stream.in is NULL", __func__);
2466 return -EINVAL;
2467 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002468 usecase->devices = usecase->stream.in->device;
2469 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002470 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002471 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002472 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002473 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002474
2475 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002476 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2477 USECASE_AUDIO_PLAYBACK_VOIP);
2478
Carter Hsu2e429db2019-05-14 18:50:52 +08002479 usecase->stream.in->enable_ec_port = false;
2480
Eric Laurent637e2d42018-11-15 12:24:31 -08002481 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2482 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2483 } else if (voip_usecase) {
2484 out_device = voip_usecase->stream.out->devices;
2485 } else if (adev->primary_output &&
2486 !adev->primary_output->standby) {
2487 out_device = adev->primary_output->devices;
2488 } else {
2489 /* forcing speaker o/p device to get matching i/p pair
2490 in case o/p is not routed from same primary HAL */
2491 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2492 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002493 priority_in = voip_in;
2494 } else {
2495 /* get the input with the highest priority source*/
2496 priority_in = get_priority_input(adev);
2497
2498 if (!priority_in)
2499 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002500 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002501
Eric Laurent637e2d42018-11-15 12:24:31 -08002502 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002503 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002504 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002505 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002506 }
2507 }
2508
2509 if (out_snd_device == usecase->out_snd_device &&
2510 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302511
2512 if (!force_device_switch(usecase))
2513 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 }
2515
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302516 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002517 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302518 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2519 return 0;
2520 }
2521
Aalique Grahame22e49102018-12-18 14:23:57 -08002522 if (out_snd_device != SND_DEVICE_NONE &&
2523 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2524 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2525 __func__,
2526 use_case_table[uc_id],
2527 adev->last_logged_snd_device[uc_id][0],
2528 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2529 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2530 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2531 -1,
2532 out_snd_device,
2533 platform_get_snd_device_name(out_snd_device),
2534 platform_get_snd_device_acdb_id(out_snd_device));
2535 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2536 }
2537 if (in_snd_device != SND_DEVICE_NONE &&
2538 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2539 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2540 __func__,
2541 use_case_table[uc_id],
2542 adev->last_logged_snd_device[uc_id][1],
2543 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2544 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2545 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2546 -1,
2547 in_snd_device,
2548 platform_get_snd_device_name(in_snd_device),
2549 platform_get_snd_device_acdb_id(in_snd_device));
2550 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2551 }
2552
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 /*
2555 * Limitation: While in call, to do a device switch we need to disable
2556 * and enable both RX and TX devices though one of them is same as current
2557 * device.
2558 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002559 if ((usecase->type == VOICE_CALL) &&
2560 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2561 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002562 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002563 }
2564
2565 if (((usecase->type == VOICE_CALL) ||
2566 (usecase->type == VOIP_CALL)) &&
2567 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2568 /* Disable sidetone only if voice/voip call already exists */
2569 if (voice_is_call_state_active(adev) ||
2570 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002571 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002572
2573 /* Disable aanc only if voice call exists */
2574 if (voice_is_call_state_active(adev))
2575 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002576 }
2577
Aalique Grahame22e49102018-12-18 14:23:57 -08002578 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2579 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002580 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302581 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002582 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2583 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2584 else
2585 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302586 }
2587
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002588 /* Disable current sound devices */
2589 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002590 disable_audio_route(adev, usecase);
2591 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 }
2593
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002594 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002595 disable_audio_route(adev, usecase);
2596 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 }
2598
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002599 /* Applicable only on the targets that has external modem.
2600 * New device information should be sent to modem before enabling
2601 * the devices to reduce in-call device switch time.
2602 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002603 if ((usecase->type == VOICE_CALL) &&
2604 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2605 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002606 status = platform_switch_voice_call_enable_device_config(adev->platform,
2607 out_snd_device,
2608 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002609 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002610
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002611 /* Enable new sound devices */
2612 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002613 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302614 if (platform_check_codec_asrc_support(adev->platform))
2615 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002616 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 }
2618
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002619 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302620 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002621 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002622 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002623
Avinash Vaish71a8b972014-07-24 15:36:33 +05302624 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002625 status = platform_switch_voice_call_device_post(adev->platform,
2626 out_snd_device,
2627 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302628 enable_audio_route_for_voice_usecases(adev, usecase);
2629 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002630
sangwoo170731f2013-06-08 15:36:36 +09002631 usecase->in_snd_device = in_snd_device;
2632 usecase->out_snd_device = out_snd_device;
2633
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302634 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2635 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302636 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002637 if ((24 == usecase->stream.out->bit_width) &&
2638 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2639 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2640 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2641 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2642 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2643 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2644 /*
2645 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2646 * configured device sample rate, if not update the COPP rate to be equal to the
2647 * device sample rate, else open COPP at stream sample rate
2648 */
2649 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2650 usecase->stream.out->sample_rate,
2651 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302652 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2653 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002654 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2655 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2656 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2657 }
2658
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002659 /* Notify device change info to effect clients registered */
2660 audio_extn_gef_notify_device_config(
2661 usecase->stream.out->devices,
2662 usecase->stream.out->channel_mask,
2663 usecase->stream.out->app_type_cfg.sample_rate,
2664 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302665 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002666 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002667
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002668 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002669
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002670 /* If input stream is already running then effect needs to be
2671 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002672 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002673 check_and_enable_effect(adev);
2674
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002675 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002676 /* Enable aanc only if voice call exists */
2677 if (voice_is_call_state_active(adev))
2678 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2679
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002680 /* Enable sidetone only if other voice/voip call already exists */
2681 if (voice_is_call_state_active(adev) ||
2682 voice_extn_compress_voip_is_started(adev))
2683 voice_set_sidetone(adev, out_snd_device, true);
2684 }
2685
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002686 /* Applicable only on the targets that has external modem.
2687 * Enable device command should be sent to modem only after
2688 * enabling voice call mixer controls
2689 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002690 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002691 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2692 out_snd_device,
2693 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302694
2695 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002696 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302697 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002698 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302699 if (is_bt_soc_on(adev) == false){
2700 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002701 if (in->pcm != NULL)
2702 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302703 }
2704 }
2705 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2706 && usecase->stream.out->started) {
2707 if (is_bt_soc_on(adev) == false) {
2708 ALOGD("BT SCO/A2DP disconnected while in connection");
2709 out_standby_l(&usecase->stream.out->stream.common);
2710 }
2711 }
2712 } else if ((usecase->stream.out != NULL) &&
2713 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302714 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2715 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302716 usecase->stream.out->started) {
2717 if (is_bt_soc_on(adev) == false) {
2718 ALOGD("BT SCO/A2dp disconnected while in connection");
2719 out_standby_l(&usecase->stream.out->stream.common);
2720 }
2721 }
2722 }
2723
Yung Ti Su70cb8242018-06-22 17:38:47 +08002724 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002725 struct stream_out *voip_out = voip_usecase->stream.out;
2726 audio_extn_utils_send_app_type_gain(adev,
2727 voip_out->app_type_cfg.app_type,
2728 &voip_out->app_type_cfg.gain[0]);
2729 }
2730
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302731 ALOGD("%s: done",__func__);
2732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 return status;
2734}
2735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736static int stop_input_stream(struct stream_in *in)
2737{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302738 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302740
2741 if (in == NULL) {
2742 ALOGE("%s: stream_in ptr is NULL", __func__);
2743 return -EINVAL;
2744 }
2745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002747 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002750 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 uc_info = get_usecase_from_list(adev, in->usecase);
2752 if (uc_info == NULL) {
2753 ALOGE("%s: Could not find the usecase (%d) in the list",
2754 __func__, in->usecase);
2755 return -EINVAL;
2756 }
2757
Carter Hsu2e429db2019-05-14 18:50:52 +08002758 priority_in = get_priority_input(adev);
2759
Derek Chenea197282019-01-07 17:35:01 -08002760 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2761 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002762
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002763 /* Close in-call recording streams */
2764 voice_check_and_stop_incall_rec_usecase(adev, in);
2765
Eric Laurent150dbfe2013-02-27 14:31:02 -08002766 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002767 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002768
2769 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002770 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002772 list_remove(&uc_info->list);
2773 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774
Carter Hsu2e429db2019-05-14 18:50:52 +08002775 if (priority_in == in) {
2776 priority_in = get_priority_input(adev);
2777 if (priority_in)
2778 select_devices(adev, priority_in->usecase);
2779 }
2780
Vatsal Buchac09ae062018-11-14 13:25:08 +05302781 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002782 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 return ret;
2784}
2785
2786int start_input_stream(struct stream_in *in)
2787{
2788 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002789 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302791
2792 if (in == NULL) {
2793 ALOGE("%s: stream_in ptr is NULL", __func__);
2794 return -EINVAL;
2795 }
2796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002798 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002799 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800
Mingming Yin2664a5b2015-09-03 10:53:11 -07002801 if (get_usecase_from_list(adev, usecase) == NULL)
2802 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302803 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2804 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002805
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302806 if (CARD_STATUS_OFFLINE == in->card_status||
2807 CARD_STATUS_OFFLINE == adev->card_status) {
2808 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302809 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302810 goto error_config;
2811 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302812
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302813 if (audio_is_bluetooth_sco_device(in->device)) {
2814 if (!adev->bt_sco_on) {
2815 ALOGE("%s: SCO profile is not ready, return error", __func__);
2816 ret = -EIO;
2817 goto error_config;
2818 }
2819 }
2820
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002821 /* Check if source matches incall recording usecase criteria */
2822 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2823 if (ret)
2824 goto error_config;
2825 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002826 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2827
2828 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2829 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2830 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002831 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002832 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002833
Eric Laurentb23d5282013-05-14 15:27:20 -07002834 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 if (in->pcm_device_id < 0) {
2836 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2837 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002838 ret = -EINVAL;
2839 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002843
2844 if (!uc_info) {
2845 ret = -ENOMEM;
2846 goto error_config;
2847 }
2848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 uc_info->id = in->usecase;
2850 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002851 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 uc_info->devices = in->device;
2853 uc_info->in_snd_device = SND_DEVICE_NONE;
2854 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002856 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002857 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302858 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2859 adev->perf_lock_opts,
2860 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002861 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862
Derek Chenea197282019-01-07 17:35:01 -08002863 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2864 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002865
Haynes Mathew George16081042017-05-31 17:16:49 -07002866 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302867 ret = audio_extn_cin_start_input_stream(in);
2868 if (ret)
2869 goto error_open;
2870 else
2871 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002872 }
2873
Haynes Mathew George16081042017-05-31 17:16:49 -07002874 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002875 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002876 ALOGE("%s: pcm stream not ready", __func__);
2877 goto error_open;
2878 }
2879 ret = pcm_start(in->pcm);
2880 if (ret < 0) {
2881 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2882 goto error_open;
2883 }
2884 } else {
2885 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2886 unsigned int pcm_open_retry_count = 0;
2887
2888 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2889 flags |= PCM_MMAP | PCM_NOIRQ;
2890 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2891 } else if (in->realtime) {
2892 flags |= PCM_MMAP | PCM_NOIRQ;
2893 }
2894
Garmond Leunge2433c32017-09-28 21:51:22 -07002895 if (audio_extn_ffv_get_stream() == in) {
2896 ALOGD("%s: ffv stream, update pcm config", __func__);
2897 audio_extn_ffv_update_pcm_config(&config);
2898 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002899 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2900 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2901
2902 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002903 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002904 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002905 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002906 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302907 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302908 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2909 adev->card_status = CARD_STATUS_OFFLINE;
2910 in->card_status = CARD_STATUS_OFFLINE;
2911 ret = -EIO;
2912 goto error_open;
2913 }
2914
Haynes Mathew George16081042017-05-31 17:16:49 -07002915 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2916 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2917 if (in->pcm != NULL) {
2918 pcm_close(in->pcm);
2919 in->pcm = NULL;
2920 }
2921 if (pcm_open_retry_count-- == 0) {
2922 ret = -EIO;
2923 goto error_open;
2924 }
2925 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2926 continue;
2927 }
2928 break;
2929 }
2930
2931 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002932 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002933 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002934 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002935 if (ret < 0) {
2936 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2937 pcm_close(in->pcm);
2938 in->pcm = NULL;
2939 goto error_open;
2940 }
2941 register_in_stream(in);
2942 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002943 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002944 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002945 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002946 if (ret < 0) {
2947 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002948 pcm_close(in->pcm);
2949 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002950 goto error_open;
2951 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002952 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002953 }
2954
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002955 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002956 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2957 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002958
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302959done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002960 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302961 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002962 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302963 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002964 return ret;
2965
2966error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002967 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302968 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002970
Eric Laurentc8400632013-02-14 19:04:54 -08002971error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302972 /*
2973 * sleep 50ms to allow sufficient time for kernel
2974 * drivers to recover incases like SSR.
2975 */
2976 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002977 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302978 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002979 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980}
2981
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002982void lock_input_stream(struct stream_in *in)
2983{
2984 pthread_mutex_lock(&in->pre_lock);
2985 pthread_mutex_lock(&in->lock);
2986 pthread_mutex_unlock(&in->pre_lock);
2987}
2988
2989void lock_output_stream(struct stream_out *out)
2990{
2991 pthread_mutex_lock(&out->pre_lock);
2992 pthread_mutex_lock(&out->lock);
2993 pthread_mutex_unlock(&out->pre_lock);
2994}
2995
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996/* must be called with out->lock locked */
2997static int send_offload_cmd_l(struct stream_out* out, int command)
2998{
2999 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3000
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003001 if (!cmd) {
3002 ALOGE("failed to allocate mem for command 0x%x", command);
3003 return -ENOMEM;
3004 }
3005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 ALOGVV("%s %d", __func__, command);
3007
3008 cmd->cmd = command;
3009 list_add_tail(&out->offload_cmd_list, &cmd->node);
3010 pthread_cond_signal(&out->offload_cond);
3011 return 0;
3012}
3013
3014/* must be called iwth out->lock locked */
3015static void stop_compressed_output_l(struct stream_out *out)
3016{
3017 out->offload_state = OFFLOAD_STATE_IDLE;
3018 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003019 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 if (out->compr != NULL) {
3021 compress_stop(out->compr);
3022 while (out->offload_thread_blocked) {
3023 pthread_cond_wait(&out->cond, &out->lock);
3024 }
3025 }
3026}
3027
Varun Balaraje49253e2017-07-06 19:48:56 +05303028bool is_interactive_usecase(audio_usecase_t uc_id)
3029{
3030 unsigned int i;
3031 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3032 if (uc_id == interactive_usecases[i])
3033 return true;
3034 }
3035 return false;
3036}
3037
3038static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3039{
3040 audio_usecase_t ret_uc = USECASE_INVALID;
3041 unsigned int intract_uc_index;
3042 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3043
3044 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3045 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3046 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3047 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3048 ret_uc = interactive_usecases[intract_uc_index];
3049 break;
3050 }
3051 }
3052
3053 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3054 return ret_uc;
3055}
3056
3057static void free_interactive_usecase(struct audio_device *adev,
3058 audio_usecase_t uc_id)
3059{
3060 unsigned int interact_uc_index;
3061 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3062
3063 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3064 if (interactive_usecases[interact_uc_index] == uc_id) {
3065 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3066 break;
3067 }
3068 }
3069 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3070}
3071
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003072bool is_offload_usecase(audio_usecase_t uc_id)
3073{
3074 unsigned int i;
3075 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3076 if (uc_id == offload_usecases[i])
3077 return true;
3078 }
3079 return false;
3080}
3081
Dhananjay Kumarac341582017-02-23 23:42:25 +05303082static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003083{
vivek mehta446c3962015-09-14 10:57:35 -07003084 audio_usecase_t ret_uc = USECASE_INVALID;
3085 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003086 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003087 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303088 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003089 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3090 else
3091 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003092
vivek mehta446c3962015-09-14 10:57:35 -07003093 pthread_mutex_lock(&adev->lock);
3094 if (get_usecase_from_list(adev, ret_uc) != NULL)
3095 ret_uc = USECASE_INVALID;
3096 pthread_mutex_unlock(&adev->lock);
3097
3098 return ret_uc;
3099 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003100
3101 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003102 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3103 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3104 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3105 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003106 break;
3107 }
3108 }
vivek mehta446c3962015-09-14 10:57:35 -07003109
3110 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3111 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003112}
3113
3114static void free_offload_usecase(struct audio_device *adev,
3115 audio_usecase_t uc_id)
3116{
vivek mehta446c3962015-09-14 10:57:35 -07003117 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003118 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003119
3120 if (!adev->multi_offload_enable)
3121 return;
3122
3123 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3124 if (offload_usecases[offload_uc_index] == uc_id) {
3125 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003126 break;
3127 }
3128 }
3129 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3130}
3131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003132static void *offload_thread_loop(void *context)
3133{
3134 struct stream_out *out = (struct stream_out *) context;
3135 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003136 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003138 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003139 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3141
3142 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003143 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003144 out->offload_state = OFFLOAD_STATE_IDLE;
3145 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 for (;;) {
3147 struct offload_cmd *cmd = NULL;
3148 stream_callback_event_t event;
3149 bool send_callback = false;
3150
3151 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3152 __func__, list_empty(&out->offload_cmd_list),
3153 out->offload_state);
3154 if (list_empty(&out->offload_cmd_list)) {
3155 ALOGV("%s SLEEPING", __func__);
3156 pthread_cond_wait(&out->offload_cond, &out->lock);
3157 ALOGV("%s RUNNING", __func__);
3158 continue;
3159 }
3160
3161 item = list_head(&out->offload_cmd_list);
3162 cmd = node_to_item(item, struct offload_cmd, node);
3163 list_remove(item);
3164
3165 ALOGVV("%s STATE %d CMD %d out->compr %p",
3166 __func__, out->offload_state, cmd->cmd, out->compr);
3167
3168 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3169 free(cmd);
3170 break;
3171 }
3172
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003173 // allow OFFLOAD_CMD_ERROR reporting during standby
3174 // this is needed to handle failures during compress_open
3175 // Note however that on a pause timeout, the stream is closed
3176 // and no offload usecase will be active. Therefore this
3177 // special case is needed for compress_open failures alone
3178 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3179 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003181 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182 pthread_cond_signal(&out->cond);
3183 continue;
3184 }
3185 out->offload_thread_blocked = true;
3186 pthread_mutex_unlock(&out->lock);
3187 send_callback = false;
3188 switch(cmd->cmd) {
3189 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003190 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003192 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 send_callback = true;
3194 event = STREAM_CBK_EVENT_WRITE_READY;
3195 break;
3196 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003197 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303198 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003199 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303200 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003201 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303202 if (ret < 0)
3203 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303204 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303205 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003206 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003207 else
3208 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003209 if (-ENETRESET != ret && !(-EINTR == ret &&
3210 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303211 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303212 pthread_mutex_lock(&out->lock);
3213 out->send_new_metadata = 1;
3214 out->send_next_track_params = true;
3215 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303216 event = STREAM_CBK_EVENT_DRAIN_READY;
3217 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3218 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303219 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003220 break;
3221 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003222 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003223 ret = compress_drain(out->compr);
3224 ALOGD("copl(%p):out of compress_drain", out);
3225 // EINTR check avoids drain interruption due to SSR
3226 if (-ENETRESET != ret && !(-EINTR == ret &&
3227 CARD_STATUS_OFFLINE == out->card_status)) {
3228 send_callback = true;
3229 event = STREAM_CBK_EVENT_DRAIN_READY;
3230 } else
3231 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003232 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303233 case OFFLOAD_CMD_ERROR:
3234 ALOGD("copl(%p): sending error callback to AF", out);
3235 send_callback = true;
3236 event = STREAM_CBK_EVENT_ERROR;
3237 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003238 default:
3239 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3240 break;
3241 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003242 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003243 out->offload_thread_blocked = false;
3244 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003245 if (send_callback && out->client_callback) {
3246 ALOGVV("%s: sending client_callback event %d", __func__, event);
3247 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003248 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003249 free(cmd);
3250 }
3251
3252 pthread_cond_signal(&out->cond);
3253 while (!list_empty(&out->offload_cmd_list)) {
3254 item = list_head(&out->offload_cmd_list);
3255 list_remove(item);
3256 free(node_to_item(item, struct offload_cmd, node));
3257 }
3258 pthread_mutex_unlock(&out->lock);
3259
3260 return NULL;
3261}
3262
3263static int create_offload_callback_thread(struct stream_out *out)
3264{
3265 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3266 list_init(&out->offload_cmd_list);
3267 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3268 offload_thread_loop, out);
3269 return 0;
3270}
3271
3272static int destroy_offload_callback_thread(struct stream_out *out)
3273{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003274 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275 stop_compressed_output_l(out);
3276 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3277
3278 pthread_mutex_unlock(&out->lock);
3279 pthread_join(out->offload_thread, (void **) NULL);
3280 pthread_cond_destroy(&out->offload_cond);
3281
3282 return 0;
3283}
3284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285static int stop_output_stream(struct stream_out *out)
3286{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303287 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 struct audio_usecase *uc_info;
3289 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003290 bool has_voip_usecase =
3291 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292
Eric Laurent994a6932013-07-17 11:51:42 -07003293 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003294 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 uc_info = get_usecase_from_list(adev, out->usecase);
3296 if (uc_info == NULL) {
3297 ALOGE("%s: Could not find the usecase (%d) in the list",
3298 __func__, out->usecase);
3299 return -EINVAL;
3300 }
3301
Derek Chenea197282019-01-07 17:35:01 -08003302 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3303 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003304
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003305 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303306 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003307 if (adev->visualizer_stop_output != NULL)
3308 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003309
3310 audio_extn_dts_remove_state_notifier_node(out->usecase);
3311
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003312 if (adev->offload_effects_stop_output != NULL)
3313 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003314 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3315 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3316 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003317 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003318
Arun Mirpurief53ce52018-09-11 18:00:09 -07003319 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3320 voice_set_device_mute_flag(adev, false);
3321
Eric Laurent150dbfe2013-02-27 14:31:02 -08003322 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003323 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003324
3325 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003326 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327
Aalique Grahame22e49102018-12-18 14:23:57 -08003328 audio_extn_extspk_update(adev->extspk);
3329
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003330 if (is_offload_usecase(out->usecase)) {
3331 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3332 adev->dsp_bit_width_enforce_mode,
3333 false);
3334 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003335 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3336 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3337 false);
3338
3339 if (ret != 0)
3340 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3341 /* default service interval was successfully updated,
3342 reopen USB backend with new service interval */
3343 ret = 0;
3344 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003345
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003346 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303347 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003348 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303349 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003350 ALOGV("Disable passthrough , reset mixer to pcm");
3351 /* NO_PASSTHROUGH */
3352 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003353 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003354 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3355 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003356
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303357 /* Must be called after removing the usecase from list */
3358 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303359 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303360
Manish Dewangan21a850a2017-08-14 12:03:55 +05303361 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003362 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3363 if (ret < 0)
3364 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3365 }
3366
juyuchen2d415992018-11-16 14:15:16 +08003367 /* 1) media + voip output routing to handset must route media back to
3368 speaker when voip stops.
3369 2) trigger voip input to reroute when voip output changes to
3370 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003371 if (has_voip_usecase ||
3372 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3373 struct listnode *node;
3374 struct audio_usecase *usecase;
3375 list_for_each(node, &adev->usecase_list) {
3376 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003377 if ((usecase->type == PCM_CAPTURE &&
3378 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3379 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003380 continue;
3381
3382 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3383 __func__, usecase->id, use_case_table[usecase->id],
3384 out->usecase, use_case_table[out->usecase]);
3385 select_devices(adev, usecase->id);
3386 }
3387 }
3388
Garmond Leung5fd0b552018-04-17 11:56:12 -07003389 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003390 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 return ret;
3392}
3393
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003394struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3395 unsigned int flags, unsigned int pcm_open_retry_count,
3396 struct pcm_config *config)
3397{
3398 struct pcm* pcm = NULL;
3399
3400 while (1) {
3401 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3402 if (pcm == NULL || !pcm_is_ready(pcm)) {
3403 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3404 if (pcm != NULL) {
3405 pcm_close(pcm);
3406 pcm = NULL;
3407 }
3408 if (pcm_open_retry_count-- == 0)
3409 return NULL;
3410
3411 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3412 continue;
3413 }
3414 break;
3415 }
3416
3417 if (pcm_is_ready(pcm)) {
3418 int ret = pcm_prepare(pcm);
3419 if (ret < 0) {
3420 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3421 pcm_close(pcm);
3422 pcm = NULL;
3423 }
3424 }
3425
3426 return pcm;
3427}
3428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429int start_output_stream(struct stream_out *out)
3430{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 struct audio_usecase *uc_info;
3433 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003434 char mixer_ctl_name[128];
3435 struct mixer_ctl *ctl = NULL;
3436 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303437 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003438 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439
Haynes Mathew George380745d2017-10-04 15:27:45 -07003440 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003441 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3442 ret = -EINVAL;
3443 goto error_config;
3444 }
3445
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003446 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303447 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003448 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303449
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303450 if (CARD_STATUS_OFFLINE == out->card_status ||
3451 CARD_STATUS_OFFLINE == adev->card_status) {
3452 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303453 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303454 goto error_config;
3455 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303456
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303457 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003458 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003459 if (out->devices &
3460 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303461 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303462 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303463 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3464 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3465 ret = -EAGAIN;
3466 goto error_config;
3467 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303468 }
3469 }
3470 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303471 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3472 if (!adev->bt_sco_on) {
3473 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3474 //combo usecase just by pass a2dp
3475 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3476 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3477 } else {
3478 ALOGE("%s: SCO profile is not ready, return error", __func__);
3479 ret = -EAGAIN;
3480 goto error_config;
3481 }
3482 }
3483 }
3484
Eric Laurentb23d5282013-05-14 15:27:20 -07003485 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 if (out->pcm_device_id < 0) {
3487 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3488 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003489 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003490 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 }
3492
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003493 if (is_haptic_usecase) {
3494 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3495 if (adev->haptic_pcm_device_id < 0) {
3496 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3497 __func__, adev->haptic_pcm_device_id, out->usecase);
3498 ret = -EINVAL;
3499 goto error_config;
3500 }
3501 }
3502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003504
3505 if (!uc_info) {
3506 ret = -ENOMEM;
3507 goto error_config;
3508 }
3509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 uc_info->id = out->usecase;
3511 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003512 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003513 uc_info->devices = out->devices;
3514 uc_info->in_snd_device = SND_DEVICE_NONE;
3515 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003516
3517 /* This must be called before adding this usecase to the list */
3518 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3519 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3520 /* USB backend is not reopened immediately.
3521 This is eventually done as part of select_devices */
3522 }
3523
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003524 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Wei Wangf7ca6c92017-11-21 14:51:20 -08003526 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303527 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3528 adev->perf_lock_opts,
3529 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303530
3531 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303532 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303533 if (audio_extn_passthru_is_enabled() &&
3534 audio_extn_passthru_is_passthrough_stream(out)) {
3535 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303536 }
3537 }
3538
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303539 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003540 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303541 if (!a2dp_combo) {
3542 check_a2dp_restore_l(adev, out, false);
3543 } else {
3544 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003545 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3546 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3547 else
3548 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303549 select_devices(adev, out->usecase);
3550 out->devices = dev;
3551 }
3552 } else {
3553 select_devices(adev, out->usecase);
3554 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003555
Arun Mirpurief53ce52018-09-11 18:00:09 -07003556 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3557 voice_set_device_mute_flag(adev, true);
3558
Derek Chenea197282019-01-07 17:35:01 -08003559 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3560 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003561
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003562 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3563 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003564
3565 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003566 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003567 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3568 ALOGE("%s: pcm stream not ready", __func__);
3569 goto error_open;
3570 }
3571 ret = pcm_start(out->pcm);
3572 if (ret < 0) {
3573 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3574 goto error_open;
3575 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003576 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003577 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003578 unsigned int flags = PCM_OUT;
3579 unsigned int pcm_open_retry_count = 0;
3580 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3581 flags |= PCM_MMAP | PCM_NOIRQ;
3582 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003583 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003584 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003585 } else
3586 flags |= PCM_MONOTONIC;
3587
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003588 if ((adev->vr_audio_mode_enabled) &&
3589 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3590 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3591 "PCM_Dev %d Topology", out->pcm_device_id);
3592 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3593 if (!ctl) {
3594 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3595 __func__, mixer_ctl_name);
3596 } else {
3597 //if success use ULLPP
3598 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3599 __func__, mixer_ctl_name, out->pcm_device_id);
3600 //There is a still a possibility that some sessions
3601 // that request for FAST|RAW when 3D audio is active
3602 //can go through ULLPP. Ideally we expects apps to
3603 //listen to audio focus and stop concurrent playback
3604 //Also, we will look for mode flag (voice_in_communication)
3605 //before enabling the realtime flag.
3606 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3607 }
3608 }
3609
Surendar Karka91fa3682018-07-02 18:12:12 +05303610 if (out->realtime)
3611 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3612 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3613
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003614 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3615 flags, pcm_open_retry_count,
3616 &(out->config));
3617 if (out->pcm == NULL) {
3618 ret = -EIO;
3619 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003620 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003621
3622 if (is_haptic_usecase) {
3623 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3624 adev->haptic_pcm_device_id,
3625 flags, pcm_open_retry_count,
3626 &(adev->haptics_config));
3627 // failure to open haptics pcm shouldnt stop audio,
3628 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003629
3630 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3631 ALOGD("%s: enable haptic audio synchronization", __func__);
3632 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3633 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003634 }
3635
Surendar Karka91fa3682018-07-02 18:12:12 +05303636 if (!out->realtime)
3637 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303638 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003639
Zhou Song2b8f28f2017-09-11 10:51:38 +08003640 // apply volume for voip playback after path is set up
3641 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3642 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303643 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3644 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303645 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3646 out->apply_volume = false;
3647 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003649 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303650 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003651 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3652 adev->dsp_bit_width_enforce_mode,
3653 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003655 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003656 out->compr = compress_open(adev->snd_card,
3657 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003659 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303660 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303661 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3662 adev->card_status = CARD_STATUS_OFFLINE;
3663 out->card_status = CARD_STATUS_OFFLINE;
3664 ret = -EIO;
3665 goto error_open;
3666 }
3667
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003668 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003669 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003670 compress_close(out->compr);
3671 out->compr = NULL;
3672 ret = -EIO;
3673 goto error_open;
3674 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303675 /* compress_open sends params of the track, so reset the flag here */
3676 out->is_compr_metadata_avail = false;
3677
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003678 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003680
Fred Oh3f43e742015-03-04 18:42:34 -08003681 /* Since small bufs uses blocking writes, a write will be blocked
3682 for the default max poll time (20s) in the event of an SSR.
3683 Reduce the poll time to observe and deal with SSR faster.
3684 */
Ashish Jain5106d362016-05-11 19:23:33 +05303685 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003686 compress_set_max_poll_wait(out->compr, 1000);
3687 }
3688
Manish Dewangan69426c82017-01-30 17:35:36 +05303689 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303690 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303691
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003692 audio_extn_dts_create_state_notifier_node(out->usecase);
3693 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3694 popcount(out->channel_mask),
3695 out->playback_started);
3696
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003697#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303698 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003699 audio_extn_dolby_send_ddp_endp_params(adev);
3700#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303701 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3702 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003703 if (adev->visualizer_start_output != NULL)
3704 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3705 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303706 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003707 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003710
3711 if (ret == 0) {
3712 register_out_stream(out);
3713 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003714 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3715 ALOGE("%s: pcm stream not ready", __func__);
3716 goto error_open;
3717 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003718 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003719 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003720 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003721 if (ret < 0)
3722 goto error_open;
3723 }
3724 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003725 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303726 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003727 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003728
vivek mehtad15d2bf2019-05-17 13:35:10 -07003729 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3730 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3731 audio_low_latency_hint_start();
3732 }
3733
Manish Dewangan21a850a2017-08-14 12:03:55 +05303734 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003735 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003736 if (ret < 0)
3737 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3738 }
3739
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003740 // consider a scenario where on pause lower layers are tear down.
3741 // so on resume, swap mixer control need to be sent only when
3742 // backend is active, hence rather than sending from enable device
3743 // sending it from start of streamtream
3744
3745 platform_set_swap_channels(adev, true);
3746
Haynes Mathew George380745d2017-10-04 15:27:45 -07003747 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303748 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003749 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003750error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003751 if (adev->haptic_pcm) {
3752 pcm_close(adev->haptic_pcm);
3753 adev->haptic_pcm = NULL;
3754 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003755 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303756 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003758error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303759 /*
3760 * sleep 50ms to allow sufficient time for kernel
3761 * drivers to recover incases like SSR.
3762 */
3763 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003764 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303765 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003766 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767}
3768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769static int check_input_parameters(uint32_t sample_rate,
3770 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003771 int channel_count,
3772 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003774 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303776 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3777 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3778 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003779 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003780 !audio_extn_compr_cap_format_supported(format) &&
3781 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003782 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003783
Aalique Grahame22e49102018-12-18 14:23:57 -08003784 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3785 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3786 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3787 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3788 return -EINVAL;
3789 }
3790
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003791 switch (channel_count) {
3792 case 1:
3793 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303794 case 3:
3795 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003796 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003797 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003798 break;
3799 default:
3800 ret = -EINVAL;
3801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
3803 switch (sample_rate) {
3804 case 8000:
3805 case 11025:
3806 case 12000:
3807 case 16000:
3808 case 22050:
3809 case 24000:
3810 case 32000:
3811 case 44100:
3812 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003813 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303814 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003815 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303816 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 break;
3818 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003819 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 }
3821
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003822 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823}
3824
Naresh Tanniru04f71882018-06-26 17:46:22 +05303825
3826/** Add a value in a list if not already present.
3827 * @return true if value was successfully inserted or already present,
3828 * false if the list is full and does not contain the value.
3829 */
3830static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3831 for (size_t i = 0; i < list_length; i++) {
3832 if (list[i] == value) return true; // value is already present
3833 if (list[i] == 0) { // no values in this slot
3834 list[i] = value;
3835 return true; // value inserted
3836 }
3837 }
3838 return false; // could not insert value
3839}
3840
3841/** Add channel_mask in supported_channel_masks if not already present.
3842 * @return true if channel_mask was successfully inserted or already present,
3843 * false if supported_channel_masks is full and does not contain channel_mask.
3844 */
3845static void register_channel_mask(audio_channel_mask_t channel_mask,
3846 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3847 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3848 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3849}
3850
3851/** Add format in supported_formats if not already present.
3852 * @return true if format was successfully inserted or already present,
3853 * false if supported_formats is full and does not contain format.
3854 */
3855static void register_format(audio_format_t format,
3856 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3857 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3858 "%s: stream can not declare supporting its format %x", __func__, format);
3859}
3860/** Add sample_rate in supported_sample_rates if not already present.
3861 * @return true if sample_rate was successfully inserted or already present,
3862 * false if supported_sample_rates is full and does not contain sample_rate.
3863 */
3864static void register_sample_rate(uint32_t sample_rate,
3865 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3866 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3867 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3868}
3869
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003870static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3871{
3872 uint32_t high = num1, low = num2, temp = 0;
3873
3874 if (!num1 || !num2)
3875 return 0;
3876
3877 if (num1 < num2) {
3878 high = num2;
3879 low = num1;
3880 }
3881
3882 while (low != 0) {
3883 temp = low;
3884 low = high % low;
3885 high = temp;
3886 }
3887 return (num1 * num2)/high;
3888}
3889
3890static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3891{
3892 uint32_t remainder = 0;
3893
3894 if (!multiplier)
3895 return num;
3896
3897 remainder = num % multiplier;
3898 if (remainder)
3899 num += (multiplier - remainder);
3900
3901 return num;
3902}
3903
Aalique Grahame22e49102018-12-18 14:23:57 -08003904static size_t get_stream_buffer_size(size_t duration_ms,
3905 uint32_t sample_rate,
3906 audio_format_t format,
3907 int channel_count,
3908 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909{
3910 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003911 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912
Aalique Grahame22e49102018-12-18 14:23:57 -08003913 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003914 if (is_low_latency)
3915 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303916
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003917 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003918 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919
Ralf Herzbd08d632018-09-28 15:50:49 +02003920 /* make sure the size is multiple of 32 bytes and additionally multiple of
3921 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003922 * At 48 kHz mono 16-bit PCM:
3923 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3924 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003925 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003926 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003927 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003928
3929 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930}
3931
Aalique Grahame22e49102018-12-18 14:23:57 -08003932static size_t get_input_buffer_size(uint32_t sample_rate,
3933 audio_format_t format,
3934 int channel_count,
3935 bool is_low_latency)
3936{
3937 /* Don't know if USB HIFI in this context so use true to be conservative */
3938 if (check_input_parameters(sample_rate, format, channel_count,
3939 true /*is_usb_hifi */) != 0)
3940 return 0;
3941
3942 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3943 sample_rate,
3944 format,
3945 channel_count,
3946 is_low_latency);
3947}
3948
Ashish Jain058165c2016-09-28 23:18:48 +05303949static size_t get_output_period_size(uint32_t sample_rate,
3950 audio_format_t format,
3951 int channel_count,
3952 int duration /*in millisecs*/)
3953{
3954 size_t size = 0;
3955 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3956
3957 if ((duration == 0) || (sample_rate == 0) ||
3958 (bytes_per_sample == 0) || (channel_count == 0)) {
3959 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3960 bytes_per_sample, channel_count);
3961 return -EINVAL;
3962 }
3963
3964 size = (sample_rate *
3965 duration *
3966 bytes_per_sample *
3967 channel_count) / 1000;
3968 /*
3969 * To have same PCM samples for all channels, the buffer size requires to
3970 * be multiple of (number of channels * bytes per sample)
3971 * For writes to succeed, the buffer must be written at address which is multiple of 32
3972 */
3973 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3974
3975 return (size/(channel_count * bytes_per_sample));
3976}
3977
Zhou Song48453a02018-01-10 17:50:59 +08003978static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303979{
3980 uint64_t actual_frames_rendered = 0;
3981 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3982
3983 /* This adjustment accounts for buffering after app processor.
3984 * It is based on estimated DSP latency per use case, rather than exact.
3985 */
3986 int64_t platform_latency = platform_render_latency(out->usecase) *
3987 out->sample_rate / 1000000LL;
3988
Zhou Song48453a02018-01-10 17:50:59 +08003989 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303990 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3991 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3992 * hence only estimate.
3993 */
3994 int64_t signed_frames = out->written - kernel_buffer_size;
3995
3996 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3997
Zhou Song48453a02018-01-10 17:50:59 +08003998 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303999 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004000 if (timestamp != NULL )
4001 *timestamp = out->writeAt;
4002 } else if (timestamp != NULL) {
4003 clock_gettime(CLOCK_MONOTONIC, timestamp);
4004 }
4005 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304006
4007 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4008 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4009 (long long int)out->written, (int)kernel_buffer_size,
4010 audio_bytes_per_sample(out->compr_config.codec->format),
4011 popcount(out->channel_mask));
4012
4013 return actual_frames_rendered;
4014}
4015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4017{
4018 struct stream_out *out = (struct stream_out *)stream;
4019
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004020 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004021}
4022
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004023static int out_set_sample_rate(struct audio_stream *stream __unused,
4024 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025{
4026 return -ENOSYS;
4027}
4028
4029static size_t out_get_buffer_size(const struct audio_stream *stream)
4030{
4031 struct stream_out *out = (struct stream_out *)stream;
4032
Varun Balaraje49253e2017-07-06 19:48:56 +05304033 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304034 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304035 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304036 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4037 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4038 else
4039 return out->compr_config.fragment_size;
4040 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004041 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004042 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4043 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 +05304044 else if (is_offload_usecase(out->usecase) &&
4045 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304046 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004048 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004049 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050}
4051
4052static uint32_t out_get_channels(const struct audio_stream *stream)
4053{
4054 struct stream_out *out = (struct stream_out *)stream;
4055
4056 return out->channel_mask;
4057}
4058
4059static audio_format_t out_get_format(const struct audio_stream *stream)
4060{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 struct stream_out *out = (struct stream_out *)stream;
4062
4063 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064}
4065
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004066static int out_set_format(struct audio_stream *stream __unused,
4067 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068{
4069 return -ENOSYS;
4070}
4071
4072static int out_standby(struct audio_stream *stream)
4073{
4074 struct stream_out *out = (struct stream_out *)stream;
4075 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004076 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304078 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4079 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004081 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004083 if (adev->adm_deregister_stream)
4084 adev->adm_deregister_stream(adev->adm_data, out->handle);
4085
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004086 if (is_offload_usecase(out->usecase))
4087 stop_compressed_output_l(out);
4088
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004089 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004091 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4092 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304093 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004094 pthread_mutex_unlock(&adev->lock);
4095 pthread_mutex_unlock(&out->lock);
4096 ALOGD("VOIP output entered standby");
4097 return 0;
4098 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004099 if (out->pcm) {
4100 pcm_close(out->pcm);
4101 out->pcm = NULL;
4102 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004103 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4104 do_stop = out->playback_started;
4105 out->playback_started = false;
4106 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004107 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004108 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304109 out->send_next_track_params = false;
4110 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004111 out->gapless_mdata.encoder_delay = 0;
4112 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004113 if (out->compr != NULL) {
4114 compress_close(out->compr);
4115 out->compr = NULL;
4116 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004117 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004118 if (do_stop) {
4119 stop_output_stream(out);
4120 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004121 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122 }
4123 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304124 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 return 0;
4126}
4127
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304128static int out_on_error(struct audio_stream *stream)
4129{
4130 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004131 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304132
4133 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004134 // always send CMD_ERROR for offload streams, this
4135 // is needed e.g. when SSR happens within compress_open
4136 // since the stream is active, offload_callback_thread is also active.
4137 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4138 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004139 }
4140 pthread_mutex_unlock(&out->lock);
4141
4142 status = out_standby(&out->stream.common);
4143
4144 lock_output_stream(out);
4145 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004146 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304147 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304148
4149 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4150 ALOGD("Setting previous card status if offline");
4151 out->prev_card_status_offline = true;
4152 }
4153
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304154 pthread_mutex_unlock(&out->lock);
4155
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004156 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304157}
4158
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304159/*
4160 *standby implementation without locks, assumes that the callee already
4161 *has taken adev and out lock.
4162 */
4163int out_standby_l(struct audio_stream *stream)
4164{
4165 struct stream_out *out = (struct stream_out *)stream;
4166 struct audio_device *adev = out->dev;
4167
4168 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4169 stream, out->usecase, use_case_table[out->usecase]);
4170
4171 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004172 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304173 if (adev->adm_deregister_stream)
4174 adev->adm_deregister_stream(adev->adm_data, out->handle);
4175
4176 if (is_offload_usecase(out->usecase))
4177 stop_compressed_output_l(out);
4178
4179 out->standby = true;
4180 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4181 voice_extn_compress_voip_close_output_stream(stream);
4182 out->started = 0;
4183 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004184 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304185 return 0;
4186 } else if (!is_offload_usecase(out->usecase)) {
4187 if (out->pcm) {
4188 pcm_close(out->pcm);
4189 out->pcm = NULL;
4190 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004191 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4192 if (adev->haptic_pcm) {
4193 pcm_close(adev->haptic_pcm);
4194 adev->haptic_pcm = NULL;
4195 }
4196
4197 if (adev->haptic_buffer != NULL) {
4198 free(adev->haptic_buffer);
4199 adev->haptic_buffer = NULL;
4200 adev->haptic_buffer_size = 0;
4201 }
4202 adev->haptic_pcm_device_id = 0;
4203 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304204 } else {
4205 ALOGD("copl(%p):standby", out);
4206 out->send_next_track_params = false;
4207 out->is_compr_metadata_avail = false;
4208 out->gapless_mdata.encoder_delay = 0;
4209 out->gapless_mdata.encoder_padding = 0;
4210 if (out->compr != NULL) {
4211 compress_close(out->compr);
4212 out->compr = NULL;
4213 }
4214 }
4215 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004216 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304217 }
4218 ALOGD("%s: exit", __func__);
4219 return 0;
4220}
4221
Aalique Grahame22e49102018-12-18 14:23:57 -08004222static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223{
Aalique Grahame22e49102018-12-18 14:23:57 -08004224 struct stream_out *out = (struct stream_out *)stream;
4225
4226 // We try to get the lock for consistency,
4227 // but it isn't necessary for these variables.
4228 // If we're not in standby, we may be blocked on a write.
4229 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4230 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4231 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4232
4233 if (locked) {
4234 pthread_mutex_unlock(&out->lock);
4235 }
4236
4237 // dump error info
4238 (void)error_log_dump(
4239 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241 return 0;
4242}
4243
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004244static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4245{
4246 int ret = 0;
4247 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004248
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004249 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004250 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004251 return -EINVAL;
4252 }
4253
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304254 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004255
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004256 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4257 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304258 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004259 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004260 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4261 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304262 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004263 }
4264
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004265 ALOGV("%s new encoder delay %u and padding %u", __func__,
4266 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4267
4268 return 0;
4269}
4270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004271static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4272{
4273 return out == adev->primary_output || out == adev->voice_tx_output;
4274}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004275
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304276// note: this call is safe only if the stream_cb is
4277// removed first in close_output_stream (as is done now).
4278static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4279{
4280 if (!stream || !parms)
4281 return;
4282
4283 struct stream_out *out = (struct stream_out *)stream;
4284 struct audio_device *adev = out->dev;
4285
4286 card_status_t status;
4287 int card;
4288 if (parse_snd_card_status(parms, &card, &status) < 0)
4289 return;
4290
4291 pthread_mutex_lock(&adev->lock);
4292 bool valid_cb = (card == adev->snd_card);
4293 pthread_mutex_unlock(&adev->lock);
4294
4295 if (!valid_cb)
4296 return;
4297
4298 lock_output_stream(out);
4299 if (out->card_status != status)
4300 out->card_status = status;
4301 pthread_mutex_unlock(&out->lock);
4302
4303 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4304 use_case_table[out->usecase],
4305 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4306
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304307 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304308 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304309 if (voice_is_call_state_active(adev) &&
4310 out == adev->primary_output) {
4311 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4312 pthread_mutex_lock(&adev->lock);
4313 voice_stop_call(adev);
4314 adev->mode = AUDIO_MODE_NORMAL;
4315 pthread_mutex_unlock(&adev->lock);
4316 }
4317 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304318 return;
4319}
4320
Kevin Rocardfce19002017-08-07 19:21:36 -07004321static int get_alive_usb_card(struct str_parms* parms) {
4322 int card;
4323 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4324 !audio_extn_usb_alive(card)) {
4325 return card;
4326 }
4327 return -ENODEV;
4328}
4329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4331{
4332 struct stream_out *out = (struct stream_out *)stream;
4333 struct audio_device *adev = out->dev;
4334 struct str_parms *parms;
4335 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004336 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304337 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004338 bool reconfig = false;
4339 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340
sangwoobc677242013-08-08 16:53:43 +09004341 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004342 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304344 if (!parms)
4345 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004346 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4347 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004349 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004350 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004352 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004353 * When HDMI cable is unplugged the music playback is paused and
4354 * the policy manager sends routing=0. But the audioflinger continues
4355 * to write data until standby time (3sec). As the HDMI core is
4356 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004357 * Avoid this by routing audio to speaker until standby.
4358 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004359 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4360 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304361 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004362 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4363 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004364 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304365 /*
4366 * When A2DP is disconnected the
4367 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004368 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304369 * (3sec). As BT is turned off, the write gets blocked.
4370 * Avoid this by routing audio to speaker until standby.
4371 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004372 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004373 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004374 !audio_extn_a2dp_source_is_ready() &&
4375 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304376 val = AUDIO_DEVICE_OUT_SPEAKER;
4377 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304378 /*
4379 * When USB headset is disconnected the music platback paused
4380 * and the policy manager send routing=0. But if the USB is connected
4381 * back before the standby time, AFE is not closed and opened
4382 * when USB is connected back. So routing to speker will guarantee
4383 * AFE reconfiguration and AFE will be opend once USB is connected again
4384 */
4385 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4386 (val == AUDIO_DEVICE_NONE) &&
4387 !audio_extn_usb_connected(parms)) {
4388 val = AUDIO_DEVICE_OUT_SPEAKER;
4389 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304390 /* To avoid a2dp to sco overlapping / BT device improper state
4391 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304392 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304393 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004394 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004395 if (val &
4396 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304397 //combo usecase just by pass a2dp
4398 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304399 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304400 } else {
4401 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4402 /* update device to a2dp and don't route as BT returned error
4403 * However it is still possible a2dp routing called because
4404 * of current active device disconnection (like wired headset)
4405 */
4406 out->devices = val;
4407 pthread_mutex_unlock(&out->lock);
4408 pthread_mutex_unlock(&adev->lock);
4409 goto error;
4410 }
4411 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304412 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004413
4414 audio_devices_t new_dev = val;
4415
4416 // Workaround: If routing to an non existing usb device, fail gracefully
4417 // The routing request will otherwise block during 10 second
4418 int card;
4419 if (audio_is_usb_out_device(new_dev) &&
4420 (card = get_alive_usb_card(parms)) >= 0) {
4421
4422 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4423 pthread_mutex_unlock(&adev->lock);
4424 pthread_mutex_unlock(&out->lock);
4425 ret = -ENOSYS;
4426 goto routing_fail;
4427 }
4428
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004429 /*
4430 * select_devices() call below switches all the usecases on the same
4431 * backend to the new device. Refer to check_usecases_codec_backend() in
4432 * the select_devices(). But how do we undo this?
4433 *
4434 * For example, music playback is active on headset (deep-buffer usecase)
4435 * and if we go to ringtones and select a ringtone, low-latency usecase
4436 * will be started on headset+speaker. As we can't enable headset+speaker
4437 * and headset devices at the same time, select_devices() switches the music
4438 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4439 * So when the ringtone playback is completed, how do we undo the same?
4440 *
4441 * We are relying on the out_set_parameters() call on deep-buffer output,
4442 * once the ringtone playback is ended.
4443 * NOTE: We should not check if the current devices are same as new devices.
4444 * Because select_devices() must be called to switch back the music
4445 * playback to headset.
4446 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004447 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004448 audio_devices_t new_dev = val;
4449 bool same_dev = out->devices == new_dev;
4450 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004451
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004452 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004453 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004454 if (adev->mode == AUDIO_MODE_IN_CALL) {
4455 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004456 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4457 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4458 audio_extn_usb_set_service_interval(true /*playback*/,
4459 service_interval,
4460 &reconfig);
4461 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4462 }
4463 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004464 }
4465 } else {
4466 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004467 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004468 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004469 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004470
4471 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004472 if (!same_dev) {
4473 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304474 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4475 adev->perf_lock_opts,
4476 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004477 if (adev->adm_on_routing_change)
4478 adev->adm_on_routing_change(adev->adm_data,
4479 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004480 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304481 if (!bypass_a2dp) {
4482 select_devices(adev, out->usecase);
4483 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004484 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4485 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4486 else
4487 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304488 select_devices(adev, out->usecase);
4489 out->devices = new_dev;
4490 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004491
4492 if (!same_dev) {
4493 // on device switch force swap, lower functions will make sure
4494 // to check if swap is allowed or not.
4495 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304496 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004497 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304498 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4499 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004500 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304501 pthread_mutex_lock(&out->compr_mute_lock);
4502 out->a2dp_compress_mute = false;
4503 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4504 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004505 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4506 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304507 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004508 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004509 }
4510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004512 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004513
4514 /*handles device and call state changes*/
4515 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004517 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004518
4519 if (out == adev->primary_output) {
4520 pthread_mutex_lock(&adev->lock);
4521 audio_extn_set_parameters(adev, parms);
4522 pthread_mutex_unlock(&adev->lock);
4523 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004524 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004525 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004526 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004527
4528 audio_extn_dts_create_state_notifier_node(out->usecase);
4529 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4530 popcount(out->channel_mask),
4531 out->playback_started);
4532
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004533 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004534 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004535
Surendar Karkaf51b5842018-04-26 11:28:38 +05304536 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4537 sizeof(value));
4538 if (err >= 0) {
4539 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4540 audio_extn_send_dual_mono_mixing_coefficients(out);
4541 }
4542
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304543 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4544 if (err >= 0) {
4545 strlcpy(out->profile, value, sizeof(out->profile));
4546 ALOGV("updating stream profile with value '%s'", out->profile);
4547 lock_output_stream(out);
4548 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4549 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004550 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304551 out->sample_rate, out->bit_width,
4552 out->channel_mask, out->profile,
4553 &out->app_type_cfg);
4554 pthread_mutex_unlock(&out->lock);
4555 }
4556
Alexy Joseph98988832017-01-13 14:56:59 -08004557 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004558 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4559 // and vendor.audio.hal.output.suspend.supported is set to true
4560 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004561 //check suspend parameter only for low latency and if the property
4562 //is enabled
4563 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4564 ALOGI("%s: got suspend_playback %s", __func__, value);
4565 lock_output_stream(out);
4566 if (!strncmp(value, "false", 5)) {
4567 //suspend_playback=false is supposed to set QOS value back to 75%
4568 //the mixer control sent with value Enable will achieve that
4569 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4570 } else if (!strncmp (value, "true", 4)) {
4571 //suspend_playback=true is supposed to remove QOS value
4572 //resetting the mixer control will set the default value
4573 //for the mixer control which is Disable and this removes the QOS vote
4574 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4575 } else {
4576 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4577 " got %s", __func__, value);
4578 ret = -1;
4579 }
4580
4581 if (ret != 0) {
4582 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4583 __func__, out->pm_qos_mixer_path, ret);
4584 }
4585
4586 pthread_mutex_unlock(&out->lock);
4587 }
4588 }
4589 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304591error:
Eric Laurent994a6932013-07-17 11:51:42 -07004592 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 return ret;
4594}
4595
Paul McLeana50b7332018-12-17 08:24:21 -07004596static int in_set_microphone_direction(const struct audio_stream_in *stream,
4597 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004598 struct stream_in *in = (struct stream_in *)stream;
4599
4600 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4601
4602 in->direction = dir;
4603
4604 if (in->standby)
4605 return 0;
4606
4607 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004608}
4609
4610static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004611 struct stream_in *in = (struct stream_in *)stream;
4612
4613 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4614
4615 if (zoom > 1.0 || zoom < -1.0)
4616 return -EINVAL;
4617
4618 in->zoom = zoom;
4619
4620 if (in->standby)
4621 return 0;
4622
4623 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004624}
4625
4626
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004627static bool stream_get_parameter_channels(struct str_parms *query,
4628 struct str_parms *reply,
4629 audio_channel_mask_t *supported_channel_masks) {
4630 int ret = -1;
4631 char value[512];
4632 bool first = true;
4633 size_t i, j;
4634
4635 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4636 ret = 0;
4637 value[0] = '\0';
4638 i = 0;
4639 while (supported_channel_masks[i] != 0) {
4640 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4641 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4642 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304643 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004644
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304645 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004646 first = false;
4647 break;
4648 }
4649 }
4650 i++;
4651 }
4652 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4653 }
4654 return ret == 0;
4655}
4656
4657static bool stream_get_parameter_formats(struct str_parms *query,
4658 struct str_parms *reply,
4659 audio_format_t *supported_formats) {
4660 int ret = -1;
4661 char value[256];
4662 size_t i, j;
4663 bool first = true;
4664
4665 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4666 ret = 0;
4667 value[0] = '\0';
4668 i = 0;
4669 while (supported_formats[i] != 0) {
4670 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4671 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4672 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304673 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004674 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304675 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004676 first = false;
4677 break;
4678 }
4679 }
4680 i++;
4681 }
4682 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4683 }
4684 return ret == 0;
4685}
4686
4687static bool stream_get_parameter_rates(struct str_parms *query,
4688 struct str_parms *reply,
4689 uint32_t *supported_sample_rates) {
4690
4691 int i;
4692 char value[256];
4693 int ret = -1;
4694 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4695 ret = 0;
4696 value[0] = '\0';
4697 i=0;
4698 int cursor = 0;
4699 while (supported_sample_rates[i]) {
4700 int avail = sizeof(value) - cursor;
4701 ret = snprintf(value + cursor, avail, "%s%d",
4702 cursor > 0 ? "|" : "",
4703 supported_sample_rates[i]);
4704 if (ret < 0 || ret >= avail) {
4705 // if cursor is at the last element of the array
4706 // overwrite with \0 is duplicate work as
4707 // snprintf already put a \0 in place.
4708 // else
4709 // we had space to write the '|' at value[cursor]
4710 // (which will be overwritten) or no space to fill
4711 // the first element (=> cursor == 0)
4712 value[cursor] = '\0';
4713 break;
4714 }
4715 cursor += ret;
4716 ++i;
4717 }
4718 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4719 value);
4720 }
4721 return ret >= 0;
4722}
4723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4725{
4726 struct stream_out *out = (struct stream_out *)stream;
4727 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004728 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004729 char value[256];
4730 struct str_parms *reply = str_parms_create();
4731 size_t i, j;
4732 int ret;
4733 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004734
4735 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004736 if (reply) {
4737 str_parms_destroy(reply);
4738 }
4739 if (query) {
4740 str_parms_destroy(query);
4741 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004742 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4743 return NULL;
4744 }
4745
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004746 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4748 if (ret >= 0) {
4749 value[0] = '\0';
4750 i = 0;
4751 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004752 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4753 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004754 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004755 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004757 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 first = false;
4759 break;
4760 }
4761 }
4762 i++;
4763 }
4764 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4765 str = str_parms_to_str(reply);
4766 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004767 voice_extn_out_get_parameters(out, query, reply);
4768 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004770
Alexy Joseph62142aa2015-11-16 15:10:34 -08004771
4772 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4773 if (ret >= 0) {
4774 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304775 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4776 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004777 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304778 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004779 } else {
4780 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304781 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004782 }
4783 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004784 if (str)
4785 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004786 str = str_parms_to_str(reply);
4787 }
4788
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004789 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4790 if (ret >= 0) {
4791 value[0] = '\0';
4792 i = 0;
4793 first = true;
4794 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004795 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4796 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004797 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004798 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004799 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004800 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004801 first = false;
4802 break;
4803 }
4804 }
4805 i++;
4806 }
4807 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004808 if (str)
4809 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004810 str = str_parms_to_str(reply);
4811 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004812
4813 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4814 if (ret >= 0) {
4815 value[0] = '\0';
4816 i = 0;
4817 first = true;
4818 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004819 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4820 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004821 if (!first) {
4822 strlcat(value, "|", sizeof(value));
4823 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004824 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004825 first = false;
4826 break;
4827 }
4828 }
4829 i++;
4830 }
4831 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4832 if (str)
4833 free(str);
4834 str = str_parms_to_str(reply);
4835 }
4836
Alexy Joseph98988832017-01-13 14:56:59 -08004837 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4838 //only low latency track supports suspend_resume
4839 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004840 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004841 if (str)
4842 free(str);
4843 str = str_parms_to_str(reply);
4844 }
4845
4846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847 str_parms_destroy(query);
4848 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004849 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850 return str;
4851}
4852
4853static uint32_t out_get_latency(const struct audio_stream_out *stream)
4854{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004855 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004857 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858
Alexy Josephaa54c872014-12-03 02:46:47 -08004859 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304860 lock_output_stream(out);
4861 latency = audio_extn_utils_compress_get_dsp_latency(out);
4862 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004863 } else if ((out->realtime) ||
4864 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004865 // since the buffer won't be filled up faster than realtime,
4866 // return a smaller number
4867 if (out->config.rate)
4868 period_ms = (out->af_period_multiplier * out->config.period_size *
4869 1000) / (out->config.rate);
4870 else
4871 period_ms = 0;
4872 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004873 } else {
4874 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004875 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004876 }
4877
yidongh0515e042017-07-06 15:00:34 +08004878 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004879 latency += audio_extn_a2dp_get_encoder_latency();
4880
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304881 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004882 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883}
4884
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304885static float AmpToDb(float amplification)
4886{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304887 float db = DSD_VOLUME_MIN_DB;
4888 if (amplification > 0) {
4889 db = 20 * log10(amplification);
4890 if(db < DSD_VOLUME_MIN_DB)
4891 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304892 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304893 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304894}
4895
Arun Mirpuri5d170872019-03-26 13:21:31 -07004896static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4897 float right)
4898{
4899 struct stream_out *out = (struct stream_out *)stream;
4900 long volume = 0;
4901 char mixer_ctl_name[128] = "";
4902 struct audio_device *adev = out->dev;
4903 struct mixer_ctl *ctl = NULL;
4904 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4905 PCM_PLAYBACK);
4906
4907 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4908 "Playback %d Volume", pcm_device_id);
4909 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4910 if (!ctl) {
4911 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4912 __func__, mixer_ctl_name);
4913 return -EINVAL;
4914 }
4915 if (left != right)
4916 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4917 __func__, left, right);
4918 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4919 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4920 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4921 __func__, mixer_ctl_name, volume);
4922 return -EINVAL;
4923 }
4924 return 0;
4925}
4926
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304927static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4928 float right)
4929{
4930 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304931 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304932 char mixer_ctl_name[128];
4933 struct audio_device *adev = out->dev;
4934 struct mixer_ctl *ctl;
4935 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4936 PCM_PLAYBACK);
4937
4938 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4939 "Compress Playback %d Volume", pcm_device_id);
4940 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4941 if (!ctl) {
4942 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4943 __func__, mixer_ctl_name);
4944 return -EINVAL;
4945 }
4946 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4947 __func__, mixer_ctl_name, left, right);
4948 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4949 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4950 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4951
4952 return 0;
4953}
4954
Zhou Song2b8f28f2017-09-11 10:51:38 +08004955static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4956 float right)
4957{
4958 struct stream_out *out = (struct stream_out *)stream;
4959 char mixer_ctl_name[] = "App Type Gain";
4960 struct audio_device *adev = out->dev;
4961 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304962 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004963
4964 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4965 if (!ctl) {
4966 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4967 __func__, mixer_ctl_name);
4968 return -EINVAL;
4969 }
4970
4971 set_values[0] = 0; //0: Rx Session 1:Tx Session
4972 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304973 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4974 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004975
4976 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4977 return 0;
4978}
4979
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304980static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4981 float right)
4982{
4983 struct stream_out *out = (struct stream_out *)stream;
4984 /* Volume control for pcm playback */
4985 if (left != right) {
4986 return -EINVAL;
4987 } else {
4988 char mixer_ctl_name[128];
4989 struct audio_device *adev = out->dev;
4990 struct mixer_ctl *ctl;
4991 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4992 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4993 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4994 if (!ctl) {
4995 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4996 return -EINVAL;
4997 }
4998
4999 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5000 int ret = mixer_ctl_set_value(ctl, 0, volume);
5001 if (ret < 0) {
5002 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5003 return -EINVAL;
5004 }
5005
5006 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5007
5008 return 0;
5009 }
5010}
5011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012static int out_set_volume(struct audio_stream_out *stream, float left,
5013 float right)
5014{
Eric Laurenta9024de2013-04-04 09:19:12 -07005015 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005016 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305017 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005018
Arun Mirpuri5d170872019-03-26 13:21:31 -07005019 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005020 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5021 /* only take left channel into account: the API is for stereo anyway */
5022 out->muted = (left == 0.0f);
5023 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005024 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305025 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005026 /*
5027 * Set mute or umute on HDMI passthrough stream.
5028 * Only take left channel into account.
5029 * Mute is 0 and unmute 1
5030 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305031 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305032 } else if (out->format == AUDIO_FORMAT_DSD){
5033 char mixer_ctl_name[128] = "DSD Volume";
5034 struct audio_device *adev = out->dev;
5035 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5036
5037 if (!ctl) {
5038 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5039 __func__, mixer_ctl_name);
5040 return -EINVAL;
5041 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305042 volume[0] = (long)(AmpToDb(left));
5043 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305044 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5045 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005046 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305047 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005048 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305049 if (!out->a2dp_compress_mute)
5050 ret = out_set_compr_volume(stream, left, right);
5051 out->volume_l = left;
5052 out->volume_r = right;
5053 pthread_mutex_unlock(&out->compr_mute_lock);
5054 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005055 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005056 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005057 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5058 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5059 if (!out->standby) {
5060 audio_extn_utils_send_app_type_gain(out->dev,
5061 out->app_type_cfg.app_type,
5062 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005063 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005064 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005065 out->volume_l = left;
5066 out->volume_r = right;
5067 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005068 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5069 ALOGV("%s: MMAP set volume called", __func__);
5070 if (!out->standby)
5071 ret = out_set_mmap_volume(stream, left, right);
5072 out->volume_l = left;
5073 out->volume_r = right;
5074 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305075 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305076 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5077 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305078 /* Volume control for pcm playback */
5079 if (!out->standby)
5080 ret = out_set_pcm_volume(stream, left, right);
5081 else
5082 out->apply_volume = true;
5083
5084 out->volume_l = left;
5085 out->volume_r = right;
5086 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005087 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005089 return -ENOSYS;
5090}
5091
Zhou Songc9672822017-08-16 16:01:39 +08005092static void update_frames_written(struct stream_out *out, size_t bytes)
5093{
5094 size_t bpf = 0;
5095
5096 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5097 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5098 bpf = 1;
5099 else if (!is_offload_usecase(out->usecase))
5100 bpf = audio_bytes_per_sample(out->format) *
5101 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005102
5103 pthread_mutex_lock(&out->position_query_lock);
5104 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005105 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005106 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5107 }
5108 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005109}
5110
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005111int split_and_write_audio_haptic_data(struct stream_out *out,
5112 const void *buffer, size_t bytes_to_write)
5113{
5114 struct audio_device *adev = out->dev;
5115
5116 int ret = 0;
5117 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5118 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5119 size_t frame_size = channel_count * bytes_per_sample;
5120 size_t frame_count = bytes_to_write / frame_size;
5121
5122 bool force_haptic_path =
5123 property_get_bool("vendor.audio.test_haptic", false);
5124
5125 // extract Haptics data from Audio buffer
5126 bool alloc_haptic_buffer = false;
5127 int haptic_channel_count = adev->haptics_config.channels;
5128 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5129 size_t audio_frame_size = frame_size - haptic_frame_size;
5130 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5131
5132 if (adev->haptic_buffer == NULL) {
5133 alloc_haptic_buffer = true;
5134 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5135 free(adev->haptic_buffer);
5136 adev->haptic_buffer_size = 0;
5137 alloc_haptic_buffer = true;
5138 }
5139
5140 if (alloc_haptic_buffer) {
5141 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005142 if(adev->haptic_buffer == NULL) {
5143 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5144 return -ENOMEM;
5145 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005146 adev->haptic_buffer_size = total_haptic_buffer_size;
5147 }
5148
5149 size_t src_index = 0, aud_index = 0, hap_index = 0;
5150 uint8_t *audio_buffer = (uint8_t *)buffer;
5151 uint8_t *haptic_buffer = adev->haptic_buffer;
5152
5153 // This is required for testing only. This works for stereo data only.
5154 // One channel is fed to audio stream and other to haptic stream for testing.
5155 if (force_haptic_path)
5156 audio_frame_size = haptic_frame_size = bytes_per_sample;
5157
5158 for (size_t i = 0; i < frame_count; i++) {
5159 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5160 audio_frame_size);
5161 aud_index += audio_frame_size;
5162 src_index += audio_frame_size;
5163
5164 if (adev->haptic_pcm)
5165 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5166 haptic_frame_size);
5167 hap_index += haptic_frame_size;
5168 src_index += haptic_frame_size;
5169
5170 // This is required for testing only.
5171 // Discard haptic channel data.
5172 if (force_haptic_path)
5173 src_index += haptic_frame_size;
5174 }
5175
5176 // write to audio pipeline
5177 ret = pcm_write(out->pcm, (void *)audio_buffer,
5178 frame_count * audio_frame_size);
5179
5180 // write to haptics pipeline
5181 if (adev->haptic_pcm)
5182 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5183 frame_count * haptic_frame_size);
5184
5185 return ret;
5186}
5187
Aalique Grahame22e49102018-12-18 14:23:57 -08005188#ifdef NO_AUDIO_OUT
5189static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5190 const void *buffer __unused, size_t bytes)
5191{
5192 struct stream_out *out = (struct stream_out *)stream;
5193
5194 /* No Output device supported other than BT for playback.
5195 * Sleep for the amount of buffer duration
5196 */
5197 lock_output_stream(out);
5198 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5199 (const struct audio_stream_out *)&out->stream) /
5200 out_get_sample_rate(&out->stream.common));
5201 pthread_mutex_unlock(&out->lock);
5202 return bytes;
5203}
5204#endif
5205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005206static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5207 size_t bytes)
5208{
5209 struct stream_out *out = (struct stream_out *)stream;
5210 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005211 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305212 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005213 const size_t frame_size = audio_stream_out_frame_size(stream);
5214 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305215 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216
Haynes Mathew George380745d2017-10-04 15:27:45 -07005217 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005218 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305219
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305220 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005221
Dhananjay Kumarac341582017-02-23 23:42:25 +05305222 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305223 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305224 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5225 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005226 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305227 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305228 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305229 ALOGD(" %s: sound card is not active/SSR state", __func__);
5230 ret= -EIO;
5231 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305232 }
5233 }
5234
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305235 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305236 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305237 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305238 goto exit;
5239 }
5240
Haynes Mathew George16081042017-05-31 17:16:49 -07005241 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5242 ret = -EINVAL;
5243 goto exit;
5244 }
5245
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305246 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5247 !out->is_iec61937_info_available) {
5248
5249 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5250 out->is_iec61937_info_available = true;
5251 } else if (audio_extn_passthru_is_enabled()) {
5252 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305253 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305254
5255 if((out->format == AUDIO_FORMAT_DTS) ||
5256 (out->format == AUDIO_FORMAT_DTS_HD)) {
5257 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5258 buffer, bytes);
5259 if (ret) {
5260 if (ret != -ENOSYS) {
5261 out->is_iec61937_info_available = false;
5262 ALOGD("iec61937 transmission info not yet updated retry");
5263 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305264 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305265 /* if stream has started and after that there is
5266 * stream config change (iec transmission config)
5267 * then trigger select_device to update backend configuration.
5268 */
5269 out->stream_config_changed = true;
5270 pthread_mutex_lock(&adev->lock);
5271 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305272 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005273 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305274 ret = -EINVAL;
5275 goto exit;
5276 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305277 pthread_mutex_unlock(&adev->lock);
5278 out->stream_config_changed = false;
5279 out->is_iec61937_info_available = true;
5280 }
5281 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305282
Garmond Leung317cbf12017-09-13 16:20:50 -07005283 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305284 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5285 (out->is_iec61937_info_available == true)) {
5286 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5287 ret = -EINVAL;
5288 goto exit;
5289 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305290 }
5291 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305292
5293 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005294 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005295 if (!(out->devices &
5296 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305297 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305298 ret = -EIO;
5299 goto exit;
5300 }
5301 }
5302 }
5303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005305 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005306 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005307 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5308 ret = voice_extn_compress_voip_start_output_stream(out);
5309 else
5310 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005311 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005312 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005313 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005314 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315 goto exit;
5316 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305317 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005318 if (last_known_cal_step != -1) {
5319 ALOGD("%s: retry previous failed cal level set", __func__);
5320 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305321 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005322 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305323
5324 if ((out->is_iec61937_info_available == true) &&
5325 (audio_extn_passthru_is_passthrough_stream(out))&&
5326 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5327 ret = -EINVAL;
5328 goto exit;
5329 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305330 if (out->set_dual_mono)
5331 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005333
Ashish Jain81eb2a82015-05-13 10:52:34 +05305334 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005335 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305336 adev->is_channel_status_set = true;
5337 }
5338
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305339 if ((adev->use_old_pspd_mix_ctrl == true) &&
5340 (out->pspd_coeff_sent == false)) {
5341 /*
5342 * Need to resend pspd coefficients after stream started for
5343 * older kernel version as it does not save the coefficients
5344 * and also stream has to be started for coeff to apply.
5345 */
5346 usecase = get_usecase_from_list(adev, out->usecase);
5347 if (usecase != NULL) {
5348 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5349 out->pspd_coeff_sent = true;
5350 }
5351 }
5352
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005353 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005354 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005355 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005356 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005357 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5358 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305359 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5360 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005361 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305362 out->send_next_track_params = false;
5363 out->is_compr_metadata_avail = false;
5364 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005365 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305366 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305367 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005368
Ashish Jain83a6cc22016-06-28 14:34:17 +05305369 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305370 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305371 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305372 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005373 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305374 return -EINVAL;
5375 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305376 audio_format_t dst_format = out->hal_op_format;
5377 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305378
Dieter Luecking5d57def2018-09-07 14:23:37 +02005379 /* prevent division-by-zero */
5380 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5381 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5382 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5383 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305384 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005385 ATRACE_END();
5386 return -EINVAL;
5387 }
5388
Ashish Jainf1eaa582016-05-23 20:54:24 +05305389 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5390 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5391
Ashish Jain83a6cc22016-06-28 14:34:17 +05305392 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305393 dst_format,
5394 buffer,
5395 src_format,
5396 frames);
5397
Ashish Jain83a6cc22016-06-28 14:34:17 +05305398 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305399 bytes_to_write);
5400
5401 /*Convert written bytes in audio flinger format*/
5402 if (ret > 0)
5403 ret = ((ret * format_to_bitwidth_table[out->format]) /
5404 format_to_bitwidth_table[dst_format]);
5405 }
5406 } else
5407 ret = compress_write(out->compr, buffer, bytes);
5408
Zhou Songc9672822017-08-16 16:01:39 +08005409 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5410 update_frames_written(out, bytes);
5411
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305412 if (ret < 0)
5413 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005414 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305415 /*msg to cb thread only if non blocking write is enabled*/
5416 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305417 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005418 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305419 } else if (-ENETRESET == ret) {
5420 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305421 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305422 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305423 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005424 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305425 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005426 }
Ashish Jain5106d362016-05-11 19:23:33 +05305427
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305428 /* Call compr start only when non-zero bytes of data is there to be rendered */
5429 if (!out->playback_started && ret > 0) {
5430 int status = compress_start(out->compr);
5431 if (status < 0) {
5432 ret = status;
5433 ALOGE("%s: compr start failed with err %d", __func__, errno);
5434 goto exit;
5435 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005436 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005437 out->playback_started = 1;
5438 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005439
5440 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5441 popcount(out->channel_mask),
5442 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005443 }
5444 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005445 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005446 return ret;
5447 } else {
5448 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005449 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005450 if (out->muted)
5451 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005452 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5453 __func__, frames, frame_size, bytes_to_write);
5454
Aalique Grahame22e49102018-12-18 14:23:57 -08005455 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005456 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5457 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5458 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005459 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5460 int16_t *src = (int16_t *)buffer;
5461 int16_t *dst = (int16_t *)buffer;
5462
5463 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5464 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005465 "out_write called for %s use case with wrong properties",
5466 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005467
5468 /*
5469 * FIXME: this can be removed once audio flinger mixer supports
5470 * mono output
5471 */
5472
5473 /*
5474 * Code below goes over each frame in the buffer and adds both
5475 * L and R samples and then divides by 2 to convert to mono
5476 */
5477 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5478 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5479 }
5480 bytes_to_write /= 2;
5481 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005482
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305483 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005484
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005485 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005486
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005487 if (out->config.rate)
5488 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5489 out->config.rate;
5490
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005491 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005492 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5493
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005494 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005495 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005496 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305497 out->convert_buffer != NULL) {
5498
5499 memcpy_by_audio_format(out->convert_buffer,
5500 out->hal_op_format,
5501 buffer,
5502 out->hal_ip_format,
5503 out->config.period_size * out->config.channels);
5504
5505 ret = pcm_write(out->pcm, out->convert_buffer,
5506 (out->config.period_size *
5507 out->config.channels *
5508 format_to_bitwidth_table[out->hal_op_format]));
5509 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305510 /*
5511 * To avoid underrun in DSP when the application is not pumping
5512 * data at required rate, check for the no. of bytes and ignore
5513 * pcm_write if it is less than actual buffer size.
5514 * It is a work around to a change in compress VOIP driver.
5515 */
5516 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5517 bytes < (out->config.period_size * out->config.channels *
5518 audio_bytes_per_sample(out->format))) {
5519 size_t voip_buf_size =
5520 out->config.period_size * out->config.channels *
5521 audio_bytes_per_sample(out->format);
5522 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5523 __func__, bytes, voip_buf_size);
5524 usleep(((uint64_t)voip_buf_size - bytes) *
5525 1000000 / audio_stream_out_frame_size(stream) /
5526 out_get_sample_rate(&out->stream.common));
5527 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005528 } else {
5529 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5530 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5531 else
5532 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5533 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305534 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005535
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005536 release_out_focus(out);
5537
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305538 if (ret < 0)
5539 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005540 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305541 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005542 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005543 }
5544
5545exit:
Zhou Songc9672822017-08-16 16:01:39 +08005546 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305547 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305548 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005550 pthread_mutex_unlock(&out->lock);
5551
5552 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005553 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005554 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305555 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305556 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305557 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305558 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305559 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305560 out->standby = true;
5561 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305562 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005563 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5564 /* prevent division-by-zero */
5565 uint32_t stream_size = audio_stream_out_frame_size(stream);
5566 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005567
Dieter Luecking5d57def2018-09-07 14:23:37 +02005568 if ((stream_size == 0) || (srate == 0)) {
5569 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5570 ATRACE_END();
5571 return -EINVAL;
5572 }
5573 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5574 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005575 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305576 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005577 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005578 return ret;
5579 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005580 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005581 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005582 return bytes;
5583}
5584
5585static int out_get_render_position(const struct audio_stream_out *stream,
5586 uint32_t *dsp_frames)
5587{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005588 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005589
5590 if (dsp_frames == NULL)
5591 return -EINVAL;
5592
5593 *dsp_frames = 0;
5594 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005595 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305596
5597 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5598 * this operation and adev_close_output_stream(where out gets reset).
5599 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305600 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005601 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305602 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005603 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305604 return 0;
5605 }
5606
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005607 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305608 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305609 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305611 if (ret < 0)
5612 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005613 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305614 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005615 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305616 if (-ENETRESET == ret) {
5617 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305618 out->card_status = CARD_STATUS_OFFLINE;
5619 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305620 } else if(ret < 0) {
5621 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305622 ret = -EINVAL;
5623 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305624 /*
5625 * Handle corner case where compress session is closed during SSR
5626 * and timestamp is queried
5627 */
5628 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305629 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305630 } else if (out->prev_card_status_offline) {
5631 ALOGE("ERROR: previously sound card was offline,return error");
5632 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305633 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305634 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005635 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305636 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305637 pthread_mutex_unlock(&out->lock);
5638 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005639 } else if (audio_is_linear_pcm(out->format)) {
5640 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005641 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005642 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005643 } else
5644 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005645}
5646
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005647static int out_add_audio_effect(const struct audio_stream *stream __unused,
5648 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005649{
5650 return 0;
5651}
5652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005653static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5654 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005655{
5656 return 0;
5657}
5658
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005659static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5660 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305662 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005663}
5664
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005665static int out_get_presentation_position(const struct audio_stream_out *stream,
5666 uint64_t *frames, struct timespec *timestamp)
5667{
5668 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305669 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005670 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005671
Ashish Jain5106d362016-05-11 19:23:33 +05305672 /* below piece of code is not guarded against any lock because audioFliner serializes
5673 * this operation and adev_close_output_stream( where out gets reset).
5674 */
5675 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305676 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005677 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305678 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5679 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5680 return 0;
5681 }
5682
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005683 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005684
Ashish Jain5106d362016-05-11 19:23:33 +05305685 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5686 ret = compress_get_tstamp(out->compr, &dsp_frames,
5687 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005688 // Adjustment accounts for A2dp encoder latency with offload usecases
5689 // Note: Encoder latency is returned in ms.
5690 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5691 unsigned long offset =
5692 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5693 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5694 }
Ashish Jain5106d362016-05-11 19:23:33 +05305695 ALOGVV("%s rendered frames %ld sample_rate %d",
5696 __func__, dsp_frames, out->sample_rate);
5697 *frames = dsp_frames;
5698 if (ret < 0)
5699 ret = -errno;
5700 if (-ENETRESET == ret) {
5701 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305702 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305703 ret = -EINVAL;
5704 } else
5705 ret = 0;
5706 /* this is the best we can do */
5707 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005708 } else {
5709 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005710 unsigned int avail;
5711 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5712 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5713 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5714 // This adjustment accounts for buffering after app processor.
5715 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005716 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005717 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005718
Weiyin Jiangd4633762018-03-16 12:05:03 +08005719 // Adjustment accounts for A2dp encoder latency with non offload usecases
5720 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5721 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5722 signed_frames -=
5723 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5724 }
5725
5726 // It would be unusual for this value to be negative, but check just in case ...
5727 if (signed_frames >= 0) {
5728 *frames = signed_frames;
5729 ret = 0;
5730 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005731 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305732 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305733 *frames = out->written;
5734 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305735 if (is_offload_usecase(out->usecase))
5736 ret = -EINVAL;
5737 else
5738 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005739 }
5740 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005741 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005742 return ret;
5743}
5744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005745static int out_set_callback(struct audio_stream_out *stream,
5746 stream_callback_t callback, void *cookie)
5747{
5748 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005749 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005750
5751 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005752 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005753 out->client_callback = callback;
5754 out->client_cookie = cookie;
5755 if (out->adsp_hdlr_stream_handle) {
5756 ret = audio_extn_adsp_hdlr_stream_set_callback(
5757 out->adsp_hdlr_stream_handle,
5758 callback,
5759 cookie);
5760 if (ret)
5761 ALOGW("%s:adsp hdlr callback registration failed %d",
5762 __func__, ret);
5763 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005764 pthread_mutex_unlock(&out->lock);
5765 return 0;
5766}
5767
5768static int out_pause(struct audio_stream_out* stream)
5769{
5770 struct stream_out *out = (struct stream_out *)stream;
5771 int status = -ENOSYS;
5772 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005773 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005774 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005775 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005776 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305777 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305778 status = compress_pause(out->compr);
5779
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005780 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005781
Mingming Yin21854652016-04-13 11:54:02 -07005782 if (audio_extn_passthru_is_active()) {
5783 ALOGV("offload use case, pause passthru");
5784 audio_extn_passthru_on_pause(out);
5785 }
5786
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305787 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005788 audio_extn_dts_notify_playback_state(out->usecase, 0,
5789 out->sample_rate, popcount(out->channel_mask),
5790 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005791 }
5792 pthread_mutex_unlock(&out->lock);
5793 }
5794 return status;
5795}
5796
5797static int out_resume(struct audio_stream_out* stream)
5798{
5799 struct stream_out *out = (struct stream_out *)stream;
5800 int status = -ENOSYS;
5801 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005802 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005803 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005804 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005805 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005806 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305807 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305808 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005809 }
5810 if (!status) {
5811 out->offload_state = OFFLOAD_STATE_PLAYING;
5812 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305813 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005814 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5815 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005816 }
5817 pthread_mutex_unlock(&out->lock);
5818 }
5819 return status;
5820}
5821
5822static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5823{
5824 struct stream_out *out = (struct stream_out *)stream;
5825 int status = -ENOSYS;
5826 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005827 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005828 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005829 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5830 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5831 else
5832 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5833 pthread_mutex_unlock(&out->lock);
5834 }
5835 return status;
5836}
5837
5838static int out_flush(struct audio_stream_out* stream)
5839{
5840 struct stream_out *out = (struct stream_out *)stream;
5841 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005842 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005843 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005844 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005845 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5846 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005847 } else {
5848 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5849 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005850 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005851 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005852 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005853 return 0;
5854 }
5855 return -ENOSYS;
5856}
5857
Haynes Mathew George16081042017-05-31 17:16:49 -07005858static int out_stop(const struct audio_stream_out* stream)
5859{
5860 struct stream_out *out = (struct stream_out *)stream;
5861 struct audio_device *adev = out->dev;
5862 int ret = -ENOSYS;
5863
5864 ALOGV("%s", __func__);
5865 pthread_mutex_lock(&adev->lock);
5866 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5867 out->playback_started && out->pcm != NULL) {
5868 pcm_stop(out->pcm);
5869 ret = stop_output_stream(out);
5870 out->playback_started = false;
5871 }
5872 pthread_mutex_unlock(&adev->lock);
5873 return ret;
5874}
5875
5876static int out_start(const struct audio_stream_out* stream)
5877{
5878 struct stream_out *out = (struct stream_out *)stream;
5879 struct audio_device *adev = out->dev;
5880 int ret = -ENOSYS;
5881
5882 ALOGV("%s", __func__);
5883 pthread_mutex_lock(&adev->lock);
5884 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5885 !out->playback_started && out->pcm != NULL) {
5886 ret = start_output_stream(out);
5887 if (ret == 0) {
5888 out->playback_started = true;
5889 }
5890 }
5891 pthread_mutex_unlock(&adev->lock);
5892 return ret;
5893}
5894
5895/*
5896 * Modify config->period_count based on min_size_frames
5897 */
5898static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5899{
5900 int periodCountRequested = (min_size_frames + config->period_size - 1)
5901 / config->period_size;
5902 int periodCount = MMAP_PERIOD_COUNT_MIN;
5903
5904 ALOGV("%s original config.period_size = %d config.period_count = %d",
5905 __func__, config->period_size, config->period_count);
5906
5907 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5908 periodCount *= 2;
5909 }
5910 config->period_count = periodCount;
5911
5912 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5913}
5914
Phil Burkfe17efd2019-03-25 10:23:35 -07005915// Read offset for the positional timestamp from a persistent vendor property.
5916// This is to workaround apparent inaccuracies in the timing information that
5917// is used by the AAudio timing model. The inaccuracies can cause glitches.
5918static int64_t get_mmap_out_time_offset() {
5919 const int32_t kDefaultOffsetMicros = 0;
5920 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08005921 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07005922 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
5923 return mmap_time_offset_micros * (int64_t)1000;
5924}
5925
Haynes Mathew George16081042017-05-31 17:16:49 -07005926static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5927 int32_t min_size_frames,
5928 struct audio_mmap_buffer_info *info)
5929{
5930 struct stream_out *out = (struct stream_out *)stream;
5931 struct audio_device *adev = out->dev;
5932 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005933 unsigned int offset1 = 0;
5934 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005935 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005936 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005937 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005938
Arun Mirpuri5d170872019-03-26 13:21:31 -07005939 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305940 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005941 pthread_mutex_lock(&adev->lock);
5942
Sharad Sanglec6f32552018-05-04 16:15:38 +05305943 if (CARD_STATUS_OFFLINE == out->card_status ||
5944 CARD_STATUS_OFFLINE == adev->card_status) {
5945 ALOGW("out->card_status or adev->card_status offline, try again");
5946 ret = -EIO;
5947 goto exit;
5948 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005949 if (info == NULL || min_size_frames == 0) {
5950 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5951 ret = -EINVAL;
5952 goto exit;
5953 }
5954 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5955 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5956 ret = -ENOSYS;
5957 goto exit;
5958 }
5959 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5960 if (out->pcm_device_id < 0) {
5961 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5962 __func__, out->pcm_device_id, out->usecase);
5963 ret = -EINVAL;
5964 goto exit;
5965 }
5966
5967 adjust_mmap_period_count(&out->config, min_size_frames);
5968
Arun Mirpuri5d170872019-03-26 13:21:31 -07005969 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005970 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5971 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5972 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305973 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305974 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5975 out->card_status = CARD_STATUS_OFFLINE;
5976 adev->card_status = CARD_STATUS_OFFLINE;
5977 ret = -EIO;
5978 goto exit;
5979 }
5980
Haynes Mathew George16081042017-05-31 17:16:49 -07005981 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5982 step = "open";
5983 ret = -ENODEV;
5984 goto exit;
5985 }
5986 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5987 if (ret < 0) {
5988 step = "begin";
5989 goto exit;
5990 }
5991 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005992 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005993 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005994 ret = platform_get_mmap_data_fd(adev->platform,
5995 out->pcm_device_id, 0 /*playback*/,
5996 &info->shared_memory_fd,
5997 &mmap_size);
5998 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005999 // Fall back to non exclusive mode
6000 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6001 } else {
6002 if (mmap_size < buffer_size) {
6003 step = "mmap";
6004 goto exit;
6005 }
6006 // FIXME: indicate exclusive mode support by returning a negative buffer size
6007 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006008 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006009 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006010 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006011
6012 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6013 if (ret < 0) {
6014 step = "commit";
6015 goto exit;
6016 }
6017
Phil Burkfe17efd2019-03-25 10:23:35 -07006018 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6019
Haynes Mathew George16081042017-05-31 17:16:49 -07006020 out->standby = false;
6021 ret = 0;
6022
Arun Mirpuri5d170872019-03-26 13:21:31 -07006023 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006024 __func__, info->shared_memory_address, info->buffer_size_frames);
6025
6026exit:
6027 if (ret != 0) {
6028 if (out->pcm == NULL) {
6029 ALOGE("%s: %s - %d", __func__, step, ret);
6030 } else {
6031 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6032 pcm_close(out->pcm);
6033 out->pcm = NULL;
6034 }
6035 }
6036 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306037 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006038 return ret;
6039}
6040
6041static int out_get_mmap_position(const struct audio_stream_out *stream,
6042 struct audio_mmap_position *position)
6043{
6044 struct stream_out *out = (struct stream_out *)stream;
6045 ALOGVV("%s", __func__);
6046 if (position == NULL) {
6047 return -EINVAL;
6048 }
6049 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006050 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006051 return -ENOSYS;
6052 }
6053 if (out->pcm == NULL) {
6054 return -ENOSYS;
6055 }
6056
6057 struct timespec ts = { 0, 0 };
6058 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6059 if (ret < 0) {
6060 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6061 return ret;
6062 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006063 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6064 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006065 return 0;
6066}
6067
6068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006069/** audio_stream_in implementation **/
6070static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6071{
6072 struct stream_in *in = (struct stream_in *)stream;
6073
6074 return in->config.rate;
6075}
6076
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006077static int in_set_sample_rate(struct audio_stream *stream __unused,
6078 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006079{
6080 return -ENOSYS;
6081}
6082
6083static size_t in_get_buffer_size(const struct audio_stream *stream)
6084{
6085 struct stream_in *in = (struct stream_in *)stream;
6086
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006087 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6088 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006089 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
6090 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 -07006091 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6092 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306093 else if(audio_extn_cin_attached_usecase(in->usecase))
6094 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006095
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006096 return in->config.period_size * in->af_period_multiplier *
6097 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006098}
6099
6100static uint32_t in_get_channels(const struct audio_stream *stream)
6101{
6102 struct stream_in *in = (struct stream_in *)stream;
6103
6104 return in->channel_mask;
6105}
6106
6107static audio_format_t in_get_format(const struct audio_stream *stream)
6108{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006109 struct stream_in *in = (struct stream_in *)stream;
6110
6111 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006112}
6113
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006114static int in_set_format(struct audio_stream *stream __unused,
6115 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006116{
6117 return -ENOSYS;
6118}
6119
6120static int in_standby(struct audio_stream *stream)
6121{
6122 struct stream_in *in = (struct stream_in *)stream;
6123 struct audio_device *adev = in->dev;
6124 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306125 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6126 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006127 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306128
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006129 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006130 if (!in->standby && in->is_st_session) {
6131 ALOGD("%s: sound trigger pcm stop lab", __func__);
6132 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006133 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006134 in->standby = 1;
6135 }
6136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006137 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006138 if (adev->adm_deregister_stream)
6139 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6140
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006141 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006142 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006143 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006144 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006145 voice_extn_compress_voip_close_input_stream(stream);
6146 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006147 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6148 do_stop = in->capture_started;
6149 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006150 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306151 if (audio_extn_cin_attached_usecase(in->usecase))
6152 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006153 }
6154
Arun Mirpuri5d170872019-03-26 13:21:31 -07006155 if (in->pcm) {
6156 ATRACE_BEGIN("pcm_in_close");
6157 pcm_close(in->pcm);
6158 ATRACE_END();
6159 in->pcm = NULL;
6160 }
6161
Carter Hsu2e429db2019-05-14 18:50:52 +08006162 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006163 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006164
6165 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006166 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006167
6168 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6169 adev->num_va_sessions--;
6170
Eric Laurent150dbfe2013-02-27 14:31:02 -08006171 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006172 }
6173 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006174 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006175 return status;
6176}
6177
Aalique Grahame22e49102018-12-18 14:23:57 -08006178static int in_dump(const struct audio_stream *stream,
6179 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006180{
Aalique Grahame22e49102018-12-18 14:23:57 -08006181 struct stream_in *in = (struct stream_in *)stream;
6182
6183 // We try to get the lock for consistency,
6184 // but it isn't necessary for these variables.
6185 // If we're not in standby, we may be blocked on a read.
6186 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6187 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6188 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6189 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6190
6191 if (locked) {
6192 pthread_mutex_unlock(&in->lock);
6193 }
6194
6195 // dump error info
6196 (void)error_log_dump(
6197 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006199 return 0;
6200}
6201
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306202static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6203{
6204 if (!stream || !parms)
6205 return;
6206
6207 struct stream_in *in = (struct stream_in *)stream;
6208 struct audio_device *adev = in->dev;
6209
6210 card_status_t status;
6211 int card;
6212 if (parse_snd_card_status(parms, &card, &status) < 0)
6213 return;
6214
6215 pthread_mutex_lock(&adev->lock);
6216 bool valid_cb = (card == adev->snd_card);
6217 pthread_mutex_unlock(&adev->lock);
6218
6219 if (!valid_cb)
6220 return;
6221
6222 lock_input_stream(in);
6223 if (in->card_status != status)
6224 in->card_status = status;
6225 pthread_mutex_unlock(&in->lock);
6226
6227 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6228 use_case_table[in->usecase],
6229 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6230
6231 // a better solution would be to report error back to AF and let
6232 // it put the stream to standby
6233 if (status == CARD_STATUS_OFFLINE)
6234 in_standby(&in->stream.common);
6235
6236 return;
6237}
6238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006239static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6240{
6241 struct stream_in *in = (struct stream_in *)stream;
6242 struct audio_device *adev = in->dev;
6243 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006244 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006245 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006246
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306247 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006248 parms = str_parms_create_str(kvpairs);
6249
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306250 if (!parms)
6251 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006252 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006253 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006254
6255 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6256 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257 val = atoi(value);
6258 /* no audio source uses val == 0 */
6259 if ((in->source != val) && (val != 0)) {
6260 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006261 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6262 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6263 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006264 (in->config.rate == 8000 || in->config.rate == 16000 ||
6265 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006266 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006267 err = voice_extn_compress_voip_open_input_stream(in);
6268 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006269 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006270 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006271 }
6272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273 }
6274 }
6275
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006276 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6277 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006278 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006279 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6280
6281 // Workaround: If routing to an non existing usb device, fail gracefully
6282 // The routing request will otherwise block during 10 second
6283 int card;
6284 if (audio_is_usb_in_device(val) &&
6285 (card = get_alive_usb_card(parms)) >= 0) {
6286
6287 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6288 ret = -ENOSYS;
6289 } else {
6290
6291 in->device = val;
6292 /* If recording is in progress, change the tx device to new device */
6293 if (!in->standby && !in->is_st_session) {
6294 ALOGV("update input routing change");
6295 // inform adm before actual routing to prevent glitches.
6296 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006297 adev->adm_on_routing_change(adev->adm_data,
6298 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006299 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006300 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6301 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006302 }
6303 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006304 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006305 }
6306 }
6307
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306308 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6309 if (err >= 0) {
6310 strlcpy(in->profile, value, sizeof(in->profile));
6311 ALOGV("updating stream profile with value '%s'", in->profile);
6312 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6313 &adev->streams_input_cfg_list,
6314 in->device, in->flags, in->format,
6315 in->sample_rate, in->bit_width,
6316 in->profile, &in->app_type_cfg);
6317 }
6318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006319 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006320 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006321
6322 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306323error:
Eric Laurent994a6932013-07-17 11:51:42 -07006324 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006325 return ret;
6326}
6327
6328static char* in_get_parameters(const struct audio_stream *stream,
6329 const char *keys)
6330{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006331 struct stream_in *in = (struct stream_in *)stream;
6332 struct str_parms *query = str_parms_create_str(keys);
6333 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006334 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006335
6336 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006337 if (reply) {
6338 str_parms_destroy(reply);
6339 }
6340 if (query) {
6341 str_parms_destroy(query);
6342 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006343 ALOGE("in_get_parameters: failed to create query or reply");
6344 return NULL;
6345 }
6346
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006347 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006348
6349 voice_extn_in_get_parameters(in, query, reply);
6350
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006351 stream_get_parameter_channels(query, reply,
6352 &in->supported_channel_masks[0]);
6353 stream_get_parameter_formats(query, reply,
6354 &in->supported_formats[0]);
6355 stream_get_parameter_rates(query, reply,
6356 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006357 str = str_parms_to_str(reply);
6358 str_parms_destroy(query);
6359 str_parms_destroy(reply);
6360
6361 ALOGV("%s: exit: returns - %s", __func__, str);
6362 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006363}
6364
Aalique Grahame22e49102018-12-18 14:23:57 -08006365static int in_set_gain(struct audio_stream_in *stream,
6366 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006367{
Aalique Grahame22e49102018-12-18 14:23:57 -08006368 struct stream_in *in = (struct stream_in *)stream;
6369 char mixer_ctl_name[128];
6370 struct mixer_ctl *ctl;
6371 int ctl_value;
6372
6373 ALOGV("%s: gain %f", __func__, gain);
6374
6375 if (stream == NULL)
6376 return -EINVAL;
6377
6378 /* in_set_gain() only used to silence MMAP capture for now */
6379 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6380 return -ENOSYS;
6381
6382 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6383
6384 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6385 if (!ctl) {
6386 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6387 __func__, mixer_ctl_name);
6388 return -ENOSYS;
6389 }
6390
6391 if (gain < RECORD_GAIN_MIN)
6392 gain = RECORD_GAIN_MIN;
6393 else if (gain > RECORD_GAIN_MAX)
6394 gain = RECORD_GAIN_MAX;
6395 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6396
6397 mixer_ctl_set_value(ctl, 0, ctl_value);
6398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006399 return 0;
6400}
6401
6402static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6403 size_t bytes)
6404{
6405 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306406
6407 if (in == NULL) {
6408 ALOGE("%s: stream_in ptr is NULL", __func__);
6409 return -EINVAL;
6410 }
6411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006412 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306413 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306414 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006416 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306417
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006418 if (in->is_st_session) {
6419 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6420 /* Read from sound trigger HAL */
6421 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006422 if (in->standby) {
6423 adev->num_va_sessions++;
6424 in->standby = 0;
6425 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006426 pthread_mutex_unlock(&in->lock);
6427 return bytes;
6428 }
6429
Haynes Mathew George16081042017-05-31 17:16:49 -07006430 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6431 ret = -ENOSYS;
6432 goto exit;
6433 }
6434
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006435 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6436 !in->standby && adev->adm_routing_changed) {
6437 ret = -ENOSYS;
6438 goto exit;
6439 }
6440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006441 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006442 pthread_mutex_lock(&adev->lock);
6443 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6444 ret = voice_extn_compress_voip_start_input_stream(in);
6445 else
6446 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006447 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6448 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006449 pthread_mutex_unlock(&adev->lock);
6450 if (ret != 0) {
6451 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452 }
6453 in->standby = 0;
6454 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006455
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006456 // what's the duration requested by the client?
6457 long ns = 0;
6458
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306459 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006460 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6461 in->config.rate;
6462
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006463 ret = request_in_focus(in, ns);
6464 if (ret != 0)
6465 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006466 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006467
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306468 if (audio_extn_cin_attached_usecase(in->usecase)) {
6469 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6470 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306471 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006472 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306473 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006474 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006475 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006476 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006477 } else if (audio_extn_ffv_get_stream() == in) {
6478 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306479 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006480 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306481 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6482 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6483 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6484 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306485 ret = -EINVAL;
6486 goto exit;
6487 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306488 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306489 ret = -errno;
6490 }
6491 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306492 /* bytes read is always set to bytes for non compress usecases */
6493 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006494 }
6495
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006496 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006498 /*
Quinn Malef6050362019-01-30 15:55:40 -08006499 * Instead of writing zeroes here, we could trust the hardware to always
6500 * provide zeroes when muted. This is also muted with voice recognition
6501 * usecases so that other clients do not have access to voice recognition
6502 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006503 */
Quinn Malef6050362019-01-30 15:55:40 -08006504 if ((ret == 0 && voice_get_mic_mute(adev) &&
6505 !voice_is_in_call_rec_stream(in) &&
6506 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6507 (adev->num_va_sessions &&
6508 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6509 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6510 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006511 memset(buffer, 0, bytes);
6512
6513exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306514 frame_size = audio_stream_in_frame_size(stream);
6515 if (frame_size > 0)
6516 in->frames_read += bytes_read/frame_size;
6517
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006518 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306519 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006520 pthread_mutex_unlock(&in->lock);
6521
6522 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306523 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306524 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306525 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306526 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306527 in->standby = true;
6528 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306529 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6530 bytes_read = bytes;
6531 memset(buffer, 0, bytes);
6532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006533 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006534 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6535 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006536 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306537 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306538 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006539 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306540 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006541}
6542
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006543static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006544{
6545 return 0;
6546}
6547
Aalique Grahame22e49102018-12-18 14:23:57 -08006548static int in_get_capture_position(const struct audio_stream_in *stream,
6549 int64_t *frames, int64_t *time)
6550{
6551 if (stream == NULL || frames == NULL || time == NULL) {
6552 return -EINVAL;
6553 }
6554 struct stream_in *in = (struct stream_in *)stream;
6555 int ret = -ENOSYS;
6556
6557 lock_input_stream(in);
6558 // note: ST sessions do not close the alsa pcm driver synchronously
6559 // on standby. Therefore, we may return an error even though the
6560 // pcm stream is still opened.
6561 if (in->standby) {
6562 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6563 "%s stream in standby but pcm not NULL for non ST session", __func__);
6564 goto exit;
6565 }
6566 if (in->pcm) {
6567 struct timespec timestamp;
6568 unsigned int avail;
6569 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6570 *frames = in->frames_read + avail;
6571 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6572 ret = 0;
6573 }
6574 }
6575exit:
6576 pthread_mutex_unlock(&in->lock);
6577 return ret;
6578}
6579
Carter Hsu2e429db2019-05-14 18:50:52 +08006580static int in_update_effect_list(bool add, effect_handle_t effect,
6581 struct listnode *head)
6582{
6583 struct listnode *node;
6584 struct in_effect_list *elist = NULL;
6585 struct in_effect_list *target = NULL;
6586 int ret = 0;
6587
6588 if (!head)
6589 return ret;
6590
6591 list_for_each(node, head) {
6592 elist = node_to_item(node, struct in_effect_list, list);
6593 if (elist->handle == effect) {
6594 target = elist;
6595 break;
6596 }
6597 }
6598
6599 if (add) {
6600 if (target) {
6601 ALOGD("effect %p already exist", effect);
6602 return ret;
6603 }
6604
6605 target = (struct in_effect_list *)
6606 calloc(1, sizeof(struct in_effect_list));
6607
6608 if (!target) {
6609 ALOGE("%s:fail to allocate memory", __func__);
6610 return -ENOMEM;
6611 }
6612
6613 target->handle = effect;
6614 list_add_tail(head, &target->list);
6615 } else {
6616 if (target) {
6617 list_remove(&target->list);
6618 free(target);
6619 }
6620 }
6621
6622 return ret;
6623}
6624
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006625static int add_remove_audio_effect(const struct audio_stream *stream,
6626 effect_handle_t effect,
6627 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006628{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006629 struct stream_in *in = (struct stream_in *)stream;
6630 int status = 0;
6631 effect_descriptor_t desc;
6632
6633 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006634 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6635
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006636 if (status != 0)
6637 return status;
6638
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006639 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006640 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006641 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006642 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6643 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006644 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006645
6646 in_update_effect_list(enable, effect, &in->aec_list);
6647 enable = !list_empty(&in->aec_list);
6648 if (enable == in->enable_aec)
6649 goto exit;
6650
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006651 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006652 ALOGD("AEC enable %d", enable);
6653
Aalique Grahame22e49102018-12-18 14:23:57 -08006654 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6655 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6656 in->dev->enable_voicerx = enable;
6657 struct audio_usecase *usecase;
6658 struct listnode *node;
6659 list_for_each(node, &in->dev->usecase_list) {
6660 usecase = node_to_item(node, struct audio_usecase, list);
6661 if (usecase->type == PCM_PLAYBACK)
6662 select_devices(in->dev, usecase->id);
6663 }
6664 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006665 if (!in->standby) {
6666 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6667 select_devices(in->dev, in->usecase);
6668 }
6669
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006670 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006671 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6672
6673 in_update_effect_list(enable, effect, &in->ns_list);
6674 enable = !list_empty(&in->ns_list);
6675 if (enable == in->enable_ns)
6676 goto exit;
6677
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006678 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006679 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006680 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006681 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6682 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006683 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6684 select_devices(in->dev, in->usecase);
6685 } else
6686 select_devices(in->dev, in->usecase);
6687 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006688 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006689exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006690 pthread_mutex_unlock(&in->dev->lock);
6691 pthread_mutex_unlock(&in->lock);
6692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006693 return 0;
6694}
6695
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006696static int in_add_audio_effect(const struct audio_stream *stream,
6697 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698{
Eric Laurent994a6932013-07-17 11:51:42 -07006699 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006700 return add_remove_audio_effect(stream, effect, true);
6701}
6702
6703static int in_remove_audio_effect(const struct audio_stream *stream,
6704 effect_handle_t effect)
6705{
Eric Laurent994a6932013-07-17 11:51:42 -07006706 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006707 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006708}
6709
Derek Chenf939fb72018-11-13 13:34:41 -08006710streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6711 audio_io_handle_t input)
6712{
6713 struct listnode *node;
6714
6715 list_for_each(node, &dev->active_inputs_list) {
6716 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6717 streams_input_ctxt_t,
6718 list);
6719 if (in_ctxt->input->capture_handle == input) {
6720 return in_ctxt;
6721 }
6722 }
6723 return NULL;
6724}
6725
6726streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6727 audio_io_handle_t output)
6728{
6729 struct listnode *node;
6730
6731 list_for_each(node, &dev->active_outputs_list) {
6732 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6733 streams_output_ctxt_t,
6734 list);
6735 if (out_ctxt->output->handle == output) {
6736 return out_ctxt;
6737 }
6738 }
6739 return NULL;
6740}
6741
Haynes Mathew George16081042017-05-31 17:16:49 -07006742static int in_stop(const struct audio_stream_in* stream)
6743{
6744 struct stream_in *in = (struct stream_in *)stream;
6745 struct audio_device *adev = in->dev;
6746
6747 int ret = -ENOSYS;
6748 ALOGV("%s", __func__);
6749 pthread_mutex_lock(&adev->lock);
6750 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6751 in->capture_started && in->pcm != NULL) {
6752 pcm_stop(in->pcm);
6753 ret = stop_input_stream(in);
6754 in->capture_started = false;
6755 }
6756 pthread_mutex_unlock(&adev->lock);
6757 return ret;
6758}
6759
6760static int in_start(const struct audio_stream_in* stream)
6761{
6762 struct stream_in *in = (struct stream_in *)stream;
6763 struct audio_device *adev = in->dev;
6764 int ret = -ENOSYS;
6765
6766 ALOGV("%s in %p", __func__, in);
6767 pthread_mutex_lock(&adev->lock);
6768 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6769 !in->capture_started && in->pcm != NULL) {
6770 if (!in->capture_started) {
6771 ret = start_input_stream(in);
6772 if (ret == 0) {
6773 in->capture_started = true;
6774 }
6775 }
6776 }
6777 pthread_mutex_unlock(&adev->lock);
6778 return ret;
6779}
6780
Phil Burke0a86d12019-02-16 22:28:11 -08006781// Read offset for the positional timestamp from a persistent vendor property.
6782// This is to workaround apparent inaccuracies in the timing information that
6783// is used by the AAudio timing model. The inaccuracies can cause glitches.
6784static int64_t in_get_mmap_time_offset() {
6785 const int32_t kDefaultOffsetMicros = 0;
6786 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006787 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006788 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6789 return mmap_time_offset_micros * (int64_t)1000;
6790}
6791
Haynes Mathew George16081042017-05-31 17:16:49 -07006792static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6793 int32_t min_size_frames,
6794 struct audio_mmap_buffer_info *info)
6795{
6796 struct stream_in *in = (struct stream_in *)stream;
6797 struct audio_device *adev = in->dev;
6798 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006799 unsigned int offset1 = 0;
6800 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006801 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006802 uint32_t mmap_size = 0;
6803 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006804
6805 pthread_mutex_lock(&adev->lock);
6806 ALOGV("%s in %p", __func__, in);
6807
Sharad Sanglec6f32552018-05-04 16:15:38 +05306808 if (CARD_STATUS_OFFLINE == in->card_status||
6809 CARD_STATUS_OFFLINE == adev->card_status) {
6810 ALOGW("in->card_status or adev->card_status offline, try again");
6811 ret = -EIO;
6812 goto exit;
6813 }
6814
Haynes Mathew George16081042017-05-31 17:16:49 -07006815 if (info == NULL || min_size_frames == 0) {
6816 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6817 ret = -EINVAL;
6818 goto exit;
6819 }
6820 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6821 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6822 ALOGV("%s in %p", __func__, in);
6823 ret = -ENOSYS;
6824 goto exit;
6825 }
6826 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6827 if (in->pcm_device_id < 0) {
6828 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6829 __func__, in->pcm_device_id, in->usecase);
6830 ret = -EINVAL;
6831 goto exit;
6832 }
6833
6834 adjust_mmap_period_count(&in->config, min_size_frames);
6835
6836 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6837 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6838 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6839 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306840 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306841 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6842 in->card_status = CARD_STATUS_OFFLINE;
6843 adev->card_status = CARD_STATUS_OFFLINE;
6844 ret = -EIO;
6845 goto exit;
6846 }
6847
Haynes Mathew George16081042017-05-31 17:16:49 -07006848 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6849 step = "open";
6850 ret = -ENODEV;
6851 goto exit;
6852 }
6853
6854 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6855 if (ret < 0) {
6856 step = "begin";
6857 goto exit;
6858 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006859
Arun Mirpuri5d170872019-03-26 13:21:31 -07006860 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6861 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6862 info->burst_size_frames = in->config.period_size;
6863 ret = platform_get_mmap_data_fd(adev->platform,
6864 in->pcm_device_id, 1 /*capture*/,
6865 &info->shared_memory_fd,
6866 &mmap_size);
6867 if (ret < 0) {
6868 // Fall back to non exclusive mode
6869 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6870 } else {
6871 if (mmap_size < buffer_size) {
6872 step = "mmap";
6873 goto exit;
6874 }
6875 // FIXME: indicate exclusive mode support by returning a negative buffer size
6876 info->buffer_size_frames *= -1;
6877 }
6878
6879 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006880
6881 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6882 if (ret < 0) {
6883 step = "commit";
6884 goto exit;
6885 }
6886
Phil Burke0a86d12019-02-16 22:28:11 -08006887 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
6888
Haynes Mathew George16081042017-05-31 17:16:49 -07006889 in->standby = false;
6890 ret = 0;
6891
6892 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6893 __func__, info->shared_memory_address, info->buffer_size_frames);
6894
6895exit:
6896 if (ret != 0) {
6897 if (in->pcm == NULL) {
6898 ALOGE("%s: %s - %d", __func__, step, ret);
6899 } else {
6900 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6901 pcm_close(in->pcm);
6902 in->pcm = NULL;
6903 }
6904 }
6905 pthread_mutex_unlock(&adev->lock);
6906 return ret;
6907}
6908
6909static int in_get_mmap_position(const struct audio_stream_in *stream,
6910 struct audio_mmap_position *position)
6911{
6912 struct stream_in *in = (struct stream_in *)stream;
6913 ALOGVV("%s", __func__);
6914 if (position == NULL) {
6915 return -EINVAL;
6916 }
6917 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6918 return -ENOSYS;
6919 }
6920 if (in->pcm == NULL) {
6921 return -ENOSYS;
6922 }
6923 struct timespec ts = { 0, 0 };
6924 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6925 if (ret < 0) {
6926 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6927 return ret;
6928 }
Phil Burke0a86d12019-02-16 22:28:11 -08006929 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6930 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006931 return 0;
6932}
6933
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306934static int in_get_active_microphones(const struct audio_stream_in *stream,
6935 struct audio_microphone_characteristic_t *mic_array,
6936 size_t *mic_count) {
6937 struct stream_in *in = (struct stream_in *)stream;
6938 struct audio_device *adev = in->dev;
6939 ALOGVV("%s", __func__);
6940
6941 lock_input_stream(in);
6942 pthread_mutex_lock(&adev->lock);
6943 int ret = platform_get_active_microphones(adev->platform,
6944 audio_channel_count_from_in_mask(in->channel_mask),
6945 in->usecase, mic_array, mic_count);
6946 pthread_mutex_unlock(&adev->lock);
6947 pthread_mutex_unlock(&in->lock);
6948
6949 return ret;
6950}
6951
6952static int adev_get_microphones(const struct audio_hw_device *dev,
6953 struct audio_microphone_characteristic_t *mic_array,
6954 size_t *mic_count) {
6955 struct audio_device *adev = (struct audio_device *)dev;
6956 ALOGVV("%s", __func__);
6957
6958 pthread_mutex_lock(&adev->lock);
6959 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6960 pthread_mutex_unlock(&adev->lock);
6961
6962 return ret;
6963}
juyuchendb308c22019-01-21 11:57:17 -07006964
6965static void in_update_sink_metadata(struct audio_stream_in *stream,
6966 const struct sink_metadata *sink_metadata) {
6967
6968 if (stream == NULL
6969 || sink_metadata == NULL
6970 || sink_metadata->tracks == NULL) {
6971 return;
6972 }
6973
6974 int error = 0;
6975 struct stream_in *in = (struct stream_in *)stream;
6976 struct audio_device *adev = in->dev;
6977 audio_devices_t device = AUDIO_DEVICE_NONE;
6978
6979 if (sink_metadata->track_count != 0)
6980 device = sink_metadata->tracks->dest_device;
6981
6982 lock_input_stream(in);
6983 pthread_mutex_lock(&adev->lock);
6984 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6985
6986 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6987 && device != AUDIO_DEVICE_NONE
6988 && adev->voice_tx_output != NULL) {
6989 /* Use the rx device from afe-proxy record to route voice call because
6990 there is no routing if tx device is on primary hal and rx device
6991 is on other hal during voice call. */
6992 adev->voice_tx_output->devices = device;
6993
6994 if (!voice_is_call_state_active(adev)) {
6995 if (adev->mode == AUDIO_MODE_IN_CALL) {
6996 adev->current_call_output = adev->voice_tx_output;
6997 error = voice_start_call(adev);
6998 if (error != 0)
6999 ALOGE("%s: start voice call failed %d", __func__, error);
7000 }
7001 } else {
7002 adev->current_call_output = adev->voice_tx_output;
7003 voice_update_devices_for_all_voice_usecases(adev);
7004 }
7005 }
7006
7007 pthread_mutex_unlock(&adev->lock);
7008 pthread_mutex_unlock(&in->lock);
7009}
7010
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307011int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007012 audio_io_handle_t handle,
7013 audio_devices_t devices,
7014 audio_output_flags_t flags,
7015 struct audio_config *config,
7016 struct audio_stream_out **stream_out,
7017 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007018{
7019 struct audio_device *adev = (struct audio_device *)dev;
7020 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307021 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007022 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007023 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307024 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007025 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7026 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7027 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7028 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007029 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007030 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7031 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007032 bool force_haptic_path =
7033 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007034 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007035
kunleizdff872d2018-08-20 14:40:33 +08007036 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007037 is_usb_dev = false;
7038 devices = AUDIO_DEVICE_OUT_SPEAKER;
7039 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7040 __func__, devices);
7041 }
7042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007043 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007045 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7046
Mingming Yin3a941d42016-02-17 18:08:05 -08007047 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
7048 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307049 devices, flags, &out->stream);
7050
7051
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007052 if (!out) {
7053 return -ENOMEM;
7054 }
7055
Haynes Mathew George204045b2015-02-25 20:32:03 -08007056 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007057 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307058 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007059 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007060 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 if (devices == AUDIO_DEVICE_NONE)
7063 devices = AUDIO_DEVICE_OUT_SPEAKER;
7064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007065 out->flags = flags;
7066 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007067 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007068 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007069 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307070 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307071 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7072 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7073 else
7074 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007075 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007076 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007077 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307078 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307079 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307080 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007081 out->hal_output_suspend_supported = 0;
7082 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307083 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307084 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307085 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007086
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307087 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307088 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007089 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7090
Aalique Grahame22e49102018-12-18 14:23:57 -08007091 if (direct_dev &&
7092 (audio_is_linear_pcm(out->format) ||
7093 config->format == AUDIO_FORMAT_DEFAULT) &&
7094 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7095 audio_format_t req_format = config->format;
7096 audio_channel_mask_t req_channel_mask = config->channel_mask;
7097 uint32_t req_sample_rate = config->sample_rate;
7098
7099 pthread_mutex_lock(&adev->lock);
7100 if (is_hdmi) {
7101 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7102 ret = read_hdmi_sink_caps(out);
7103 if (config->sample_rate == 0)
7104 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7105 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7106 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7107 if (config->format == AUDIO_FORMAT_DEFAULT)
7108 config->format = AUDIO_FORMAT_PCM_16_BIT;
7109 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007110 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7111 &config->format,
7112 &out->supported_formats[0],
7113 MAX_SUPPORTED_FORMATS,
7114 &config->channel_mask,
7115 &out->supported_channel_masks[0],
7116 MAX_SUPPORTED_CHANNEL_MASKS,
7117 &config->sample_rate,
7118 &out->supported_sample_rates[0],
7119 MAX_SUPPORTED_SAMPLE_RATES);
7120 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007121 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007122
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007123 pthread_mutex_unlock(&adev->lock);
7124 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007125 if (ret == -ENOSYS) {
7126 /* ignore and go with default */
7127 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007128 }
7129 // For MMAP NO IRQ, allow conversions in ADSP
7130 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7131 goto error_open;
7132 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007133 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007134 goto error_open;
7135 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007136
7137 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7138 config->sample_rate = req_sample_rate;
7139 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7140 config->channel_mask = req_channel_mask;
7141 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7142 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007143 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007144
7145 out->sample_rate = config->sample_rate;
7146 out->channel_mask = config->channel_mask;
7147 out->format = config->format;
7148 if (is_hdmi) {
7149 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7150 out->config = pcm_config_hdmi_multi;
7151 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7152 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7153 out->config = pcm_config_mmap_playback;
7154 out->stream.start = out_start;
7155 out->stream.stop = out_stop;
7156 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7157 out->stream.get_mmap_position = out_get_mmap_position;
7158 } else {
7159 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7160 out->config = pcm_config_hifi;
7161 }
7162
7163 out->config.rate = out->sample_rate;
7164 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7165 if (is_hdmi) {
7166 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7167 audio_bytes_per_sample(out->format));
7168 }
7169 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007170 }
7171
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007172 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007173 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007174 if (!voice_extn_is_compress_voip_supported()) {
7175 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7176 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007177 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7178 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007179 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7180 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007181
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007182 out->config = default_pcm_config_voip_copp;
7183 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7184 out->config.rate = out->sample_rate;
7185 }
7186 } else {
7187 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7188 voice_extn_compress_voip_is_active(out->dev)) &&
7189 (voice_extn_compress_voip_is_config_supported(config))) {
7190 ret = voice_extn_compress_voip_open_output_stream(out);
7191 if (ret != 0) {
7192 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7193 __func__, ret);
7194 goto error_open;
7195 }
7196 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007197 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007198 } else if (audio_is_linear_pcm(out->format) &&
7199 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7200 out->channel_mask = config->channel_mask;
7201 out->sample_rate = config->sample_rate;
7202 out->format = config->format;
7203 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7204 // does this change?
7205 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7206 out->config.rate = config->sample_rate;
7207 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7208 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7209 audio_bytes_per_sample(config->format));
7210 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007211 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307212 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307213 pthread_mutex_lock(&adev->lock);
7214 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7215 pthread_mutex_unlock(&adev->lock);
7216
7217 // reject offload during card offline to allow
7218 // fallback to s/w paths
7219 if (offline) {
7220 ret = -ENODEV;
7221 goto error_open;
7222 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007224 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7225 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7226 ALOGE("%s: Unsupported Offload information", __func__);
7227 ret = -EINVAL;
7228 goto error_open;
7229 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007230
Atul Khare3fa6e542017-08-09 00:56:17 +05307231 if (config->offload_info.format == 0)
7232 config->offload_info.format = config->format;
7233 if (config->offload_info.sample_rate == 0)
7234 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007235
Mingming Yin90310102013-11-13 16:57:00 -08007236 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307237 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007238 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007239 ret = -EINVAL;
7240 goto error_open;
7241 }
7242
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007243 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7244 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7245 (audio_extn_passthru_is_passthrough_stream(out)) &&
7246 !((config->sample_rate == 48000) ||
7247 (config->sample_rate == 96000) ||
7248 (config->sample_rate == 192000))) {
7249 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7250 __func__, config->sample_rate, config->offload_info.format);
7251 ret = -EINVAL;
7252 goto error_open;
7253 }
7254
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007255 out->compr_config.codec = (struct snd_codec *)
7256 calloc(1, sizeof(struct snd_codec));
7257
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007258 if (!out->compr_config.codec) {
7259 ret = -ENOMEM;
7260 goto error_open;
7261 }
7262
Dhananjay Kumarac341582017-02-23 23:42:25 +05307263 out->stream.pause = out_pause;
7264 out->stream.resume = out_resume;
7265 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307266 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307267 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007268 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307269 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007270 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307271 } else {
7272 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7273 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007274 }
vivek mehta446c3962015-09-14 10:57:35 -07007275
7276 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007277 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7278 config->format == 0 && config->sample_rate == 0 &&
7279 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007280 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007281 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7282 } else {
7283 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7284 ret = -EEXIST;
7285 goto error_open;
7286 }
vivek mehta446c3962015-09-14 10:57:35 -07007287 }
7288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007289 if (config->offload_info.channel_mask)
7290 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007291 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007292 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007293 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007294 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307295 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007296 ret = -EINVAL;
7297 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007298 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007299
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007300 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007301 out->sample_rate = config->offload_info.sample_rate;
7302
Mingming Yin3ee55c62014-08-04 14:23:35 -07007303 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007304
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307305 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307306 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307307 audio_extn_dolby_send_ddp_endp_params(adev);
7308 audio_extn_dolby_set_dmid(adev);
7309 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007310
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007311 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007312 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007313 out->compr_config.codec->bit_rate =
7314 config->offload_info.bit_rate;
7315 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307316 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007317 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307318 /* Update bit width only for non passthrough usecases.
7319 * For passthrough usecases, the output will always be opened @16 bit
7320 */
7321 if (!audio_extn_passthru_is_passthrough_stream(out))
7322 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307323
7324 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7325 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7326 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7327
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007328 /*TODO: Do we need to change it for passthrough */
7329 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007330
Manish Dewangana6fc5442015-08-24 20:30:31 +05307331 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7332 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307333 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307334 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307335 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7336 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307337
7338 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7339 AUDIO_FORMAT_PCM) {
7340
7341 /*Based on platform support, configure appropriate alsa format for corresponding
7342 *hal input format.
7343 */
7344 out->compr_config.codec->format = hal_format_to_alsa(
7345 config->offload_info.format);
7346
Ashish Jain83a6cc22016-06-28 14:34:17 +05307347 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307348 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307349 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307350
Dhananjay Kumarac341582017-02-23 23:42:25 +05307351 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307352 *hal input format and alsa format might differ based on platform support.
7353 */
7354 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307355 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307356
7357 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7358
7359 /* Check if alsa session is configured with the same format as HAL input format,
7360 * if not then derive correct fragment size needed to accomodate the
7361 * conversion of HAL input format to alsa format.
7362 */
7363 audio_extn_utils_update_direct_pcm_fragment_size(out);
7364
7365 /*if hal input and output fragment size is different this indicates HAL input format is
7366 *not same as the alsa format
7367 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307368 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307369 /*Allocate a buffer to convert input data to the alsa configured format.
7370 *size of convert buffer is equal to the size required to hold one fragment size
7371 *worth of pcm data, this is because flinger does not write more than fragment_size
7372 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307373 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7374 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307375 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7376 ret = -ENOMEM;
7377 goto error_open;
7378 }
7379 }
7380 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7381 out->compr_config.fragment_size =
7382 audio_extn_passthru_get_buffer_size(&config->offload_info);
7383 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7384 } else {
7385 out->compr_config.fragment_size =
7386 platform_get_compress_offload_buffer_size(&config->offload_info);
7387 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7388 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007389
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307390 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7391 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7392 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007393 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307394 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007395
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307396 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7397 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7398 }
7399
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007400 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7401 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007402
Manish Dewangan69426c82017-01-30 17:35:36 +05307403 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7404 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7405 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7406 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7407 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7408 } else {
7409 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7410 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007411
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307412 memset(&out->channel_map_param, 0,
7413 sizeof(struct audio_out_channel_map_param));
7414
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007415 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307416 out->send_next_track_params = false;
7417 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007418 out->offload_state = OFFLOAD_STATE_IDLE;
7419 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007420 out->writeAt.tv_sec = 0;
7421 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007422
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007423 audio_extn_dts_create_state_notifier_node(out->usecase);
7424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007425 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7426 __func__, config->offload_info.version,
7427 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307428
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307429 /* Check if DSD audio format is supported in codec
7430 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307431 */
7432
7433 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307434 (!platform_check_codec_dsd_support(adev->platform) ||
7435 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307436 ret = -EINVAL;
7437 goto error_open;
7438 }
7439
Ashish Jain5106d362016-05-11 19:23:33 +05307440 /* Disable gapless if any of the following is true
7441 * passthrough playback
7442 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307443 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307444 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307445 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307446 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007447 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307448 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307449 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307450 check_and_set_gapless_mode(adev, false);
7451 } else
7452 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007453
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307454 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007455 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7456 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307457 if (config->format == AUDIO_FORMAT_DSD) {
7458 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7459 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7460 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007461
7462 create_offload_callback_thread(out);
7463
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007464 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007465 switch (config->sample_rate) {
7466 case 0:
7467 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7468 break;
7469 case 8000:
7470 case 16000:
7471 case 48000:
7472 out->sample_rate = config->sample_rate;
7473 break;
7474 default:
7475 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7476 config->sample_rate);
7477 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7478 ret = -EINVAL;
7479 goto error_open;
7480 }
7481 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7482 switch (config->channel_mask) {
7483 case AUDIO_CHANNEL_NONE:
7484 case AUDIO_CHANNEL_OUT_STEREO:
7485 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7486 break;
7487 default:
7488 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7489 config->channel_mask);
7490 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7491 ret = -EINVAL;
7492 goto error_open;
7493 }
7494 switch (config->format) {
7495 case AUDIO_FORMAT_DEFAULT:
7496 case AUDIO_FORMAT_PCM_16_BIT:
7497 out->format = AUDIO_FORMAT_PCM_16_BIT;
7498 break;
7499 default:
7500 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7501 config->format);
7502 config->format = AUDIO_FORMAT_PCM_16_BIT;
7503 ret = -EINVAL;
7504 goto error_open;
7505 }
7506
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307507 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007508 if (ret != 0) {
7509 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007510 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007511 goto error_open;
7512 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007513 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007514 switch (config->sample_rate) {
7515 case 0:
7516 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7517 break;
7518 case 8000:
7519 case 16000:
7520 case 48000:
7521 out->sample_rate = config->sample_rate;
7522 break;
7523 default:
7524 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7525 config->sample_rate);
7526 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7527 ret = -EINVAL;
7528 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007529 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007530 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7531 switch (config->channel_mask) {
7532 case AUDIO_CHANNEL_NONE:
7533 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7534 break;
7535 case AUDIO_CHANNEL_OUT_STEREO:
7536 out->channel_mask = config->channel_mask;
7537 break;
7538 default:
7539 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7540 config->channel_mask);
7541 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7542 ret = -EINVAL;
7543 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007544 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007545 switch (config->format) {
7546 case AUDIO_FORMAT_DEFAULT:
7547 out->format = AUDIO_FORMAT_PCM_16_BIT;
7548 break;
7549 case AUDIO_FORMAT_PCM_16_BIT:
7550 out->format = config->format;
7551 break;
7552 default:
7553 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7554 config->format);
7555 config->format = AUDIO_FORMAT_PCM_16_BIT;
7556 ret = -EINVAL;
7557 break;
7558 }
7559 if (ret != 0)
7560 goto error_open;
7561
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007562 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7563 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007564 out->config.rate = out->sample_rate;
7565 out->config.channels =
7566 audio_channel_count_from_out_mask(out->channel_mask);
7567 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007568 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007569 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307570 unsigned int channels = 0;
7571 /*Update config params to default if not set by the caller*/
7572 if (config->sample_rate == 0)
7573 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7574 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7575 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7576 if (config->format == AUDIO_FORMAT_DEFAULT)
7577 config->format = AUDIO_FORMAT_PCM_16_BIT;
7578
7579 channels = audio_channel_count_from_out_mask(out->channel_mask);
7580
Varun Balaraje49253e2017-07-06 19:48:56 +05307581 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7582 out->usecase = get_interactive_usecase(adev);
7583 out->config = pcm_config_low_latency;
7584 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307585 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007586 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7587 out->flags);
7588 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007589 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7590 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7591 out->config = pcm_config_mmap_playback;
7592 out->stream.start = out_start;
7593 out->stream.stop = out_stop;
7594 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7595 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307596 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7597 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007598 out->hal_output_suspend_supported =
7599 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7600 out->dynamic_pm_qos_config_supported =
7601 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7602 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007603 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7604 } else {
7605 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7606 //the mixer path will be a string similar to "low-latency-playback resume"
7607 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7608 strlcat(out->pm_qos_mixer_path,
7609 " resume", MAX_MIXER_PATH_LEN);
7610 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7611 out->pm_qos_mixer_path);
7612 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307613 out->config = pcm_config_low_latency;
7614 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7615 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7616 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307617 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7618 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7619 if (out->config.period_size <= 0) {
7620 ALOGE("Invalid configuration period size is not valid");
7621 ret = -EINVAL;
7622 goto error_open;
7623 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007624 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7625 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7626 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007627 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7628 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7629 out->config = pcm_config_haptics_audio;
7630 if (force_haptic_path)
7631 adev->haptics_config = pcm_config_haptics_audio;
7632 else
7633 adev->haptics_config = pcm_config_haptics;
7634
7635 out->config.channels =
7636 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7637
7638 if (force_haptic_path) {
7639 out->config.channels = 1;
7640 adev->haptics_config.channels = 1;
7641 } else
7642 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307643 } else {
7644 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007645 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7646 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307647 }
7648 out->hal_ip_format = format = out->format;
7649 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7650 out->hal_op_format = pcm_format_to_hal(out->config.format);
7651 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7652 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007653 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307654 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307655 if (out->hal_ip_format != out->hal_op_format) {
7656 uint32_t buffer_size = out->config.period_size *
7657 format_to_bitwidth_table[out->hal_op_format] *
7658 out->config.channels;
7659 out->convert_buffer = calloc(1, buffer_size);
7660 if (out->convert_buffer == NULL){
7661 ALOGE("Allocation failed for convert buffer for size %d",
7662 out->compr_config.fragment_size);
7663 ret = -ENOMEM;
7664 goto error_open;
7665 }
7666 ALOGD("Convert buffer allocated of size %d", buffer_size);
7667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007668 }
7669
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007670 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7671 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307672
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007673 /* TODO remove this hardcoding and check why width is zero*/
7674 if (out->bit_width == 0)
7675 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307676 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007677 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007678 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307679 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307680 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007681 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007682 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7683 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007684 if(adev->primary_output == NULL)
7685 adev->primary_output = out;
7686 else {
7687 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007688 ret = -EEXIST;
7689 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007690 }
7691 }
7692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007693 /* Check if this usecase is already existing */
7694 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007695 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7696 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007697 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007698 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007699 ret = -EEXIST;
7700 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007701 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007703 pthread_mutex_unlock(&adev->lock);
7704
7705 out->stream.common.get_sample_rate = out_get_sample_rate;
7706 out->stream.common.set_sample_rate = out_set_sample_rate;
7707 out->stream.common.get_buffer_size = out_get_buffer_size;
7708 out->stream.common.get_channels = out_get_channels;
7709 out->stream.common.get_format = out_get_format;
7710 out->stream.common.set_format = out_set_format;
7711 out->stream.common.standby = out_standby;
7712 out->stream.common.dump = out_dump;
7713 out->stream.common.set_parameters = out_set_parameters;
7714 out->stream.common.get_parameters = out_get_parameters;
7715 out->stream.common.add_audio_effect = out_add_audio_effect;
7716 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7717 out->stream.get_latency = out_get_latency;
7718 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007719#ifdef NO_AUDIO_OUT
7720 out->stream.write = out_write_for_no_output;
7721#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007722 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007723#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007724 out->stream.get_render_position = out_get_render_position;
7725 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007726 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007727
Haynes Mathew George16081042017-05-31 17:16:49 -07007728 if (out->realtime)
7729 out->af_period_multiplier = af_period_multiplier;
7730 else
7731 out->af_period_multiplier = 1;
7732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007733 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007734 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007735 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007736
7737 config->format = out->stream.common.get_format(&out->stream.common);
7738 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7739 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307740 register_format(out->format, out->supported_formats);
7741 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7742 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007743
Aalique Grahame22e49102018-12-18 14:23:57 -08007744 out->error_log = error_log_create(
7745 ERROR_LOG_ENTRIES,
7746 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7747
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307748 /*
7749 By locking output stream before registering, we allow the callback
7750 to update stream's state only after stream's initial state is set to
7751 adev state.
7752 */
7753 lock_output_stream(out);
7754 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7755 pthread_mutex_lock(&adev->lock);
7756 out->card_status = adev->card_status;
7757 pthread_mutex_unlock(&adev->lock);
7758 pthread_mutex_unlock(&out->lock);
7759
Aalique Grahame22e49102018-12-18 14:23:57 -08007760 stream_app_type_cfg_init(&out->app_type_cfg);
7761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007762 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307763 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007764 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007765
7766 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7767 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7768 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007769 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307770 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007771 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007772 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307773 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7774 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007775 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7776 out->usecase, PCM_PLAYBACK);
7777 hdlr_stream_cfg.flags = out->flags;
7778 hdlr_stream_cfg.type = PCM_PLAYBACK;
7779 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7780 &hdlr_stream_cfg);
7781 if (ret) {
7782 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7783 out->adsp_hdlr_stream_handle = NULL;
7784 }
7785 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307786 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7787 is_direct_passthough, false);
7788 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7789 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007790 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007791 if (ret < 0) {
7792 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7793 out->ip_hdlr_handle = NULL;
7794 }
7795 }
Derek Chenf939fb72018-11-13 13:34:41 -08007796
7797 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7798 calloc(1, sizeof(streams_output_ctxt_t));
7799 if (out_ctxt == NULL) {
7800 ALOGE("%s fail to allocate output ctxt", __func__);
7801 ret = -ENOMEM;
7802 goto error_open;
7803 }
7804 out_ctxt->output = out;
7805
7806 pthread_mutex_lock(&adev->lock);
7807 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7808 pthread_mutex_unlock(&adev->lock);
7809
Eric Laurent994a6932013-07-17 11:51:42 -07007810 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007811 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007812
7813error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307814 if (out->convert_buffer)
7815 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007816 free(out);
7817 *stream_out = NULL;
7818 ALOGD("%s: exit: ret %d", __func__, ret);
7819 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007820}
7821
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307822void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007823 struct audio_stream_out *stream)
7824{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007825 struct stream_out *out = (struct stream_out *)stream;
7826 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007827 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007828
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007829 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307830
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307831 // must deregister from sndmonitor first to prevent races
7832 // between the callback and close_stream
7833 audio_extn_snd_mon_unregister_listener(out);
7834
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007835 /* close adsp hdrl session before standby */
7836 if (out->adsp_hdlr_stream_handle) {
7837 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7838 if (ret)
7839 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7840 out->adsp_hdlr_stream_handle = NULL;
7841 }
7842
Manish Dewangan21a850a2017-08-14 12:03:55 +05307843 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007844 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7845 out->ip_hdlr_handle = NULL;
7846 }
7847
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007848 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307849 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007850 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307851 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307852 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007853 if(ret != 0)
7854 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7855 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007856 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007857 out_standby(&stream->common);
7858
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007859 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007860 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007861 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007862 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007863 if (out->compr_config.codec != NULL)
7864 free(out->compr_config.codec);
7865 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007866
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307867 out->a2dp_compress_mute = false;
7868
Varun Balaraje49253e2017-07-06 19:48:56 +05307869 if (is_interactive_usecase(out->usecase))
7870 free_interactive_usecase(adev, out->usecase);
7871
Ashish Jain83a6cc22016-06-28 14:34:17 +05307872 if (out->convert_buffer != NULL) {
7873 free(out->convert_buffer);
7874 out->convert_buffer = NULL;
7875 }
7876
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007877 if (adev->voice_tx_output == out)
7878 adev->voice_tx_output = NULL;
7879
Aalique Grahame22e49102018-12-18 14:23:57 -08007880 error_log_destroy(out->error_log);
7881 out->error_log = NULL;
7882
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307883 if (adev->primary_output == out)
7884 adev->primary_output = NULL;
7885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007886 pthread_cond_destroy(&out->cond);
7887 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007888
7889 pthread_mutex_lock(&adev->lock);
7890 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7891 if (out_ctxt != NULL) {
7892 list_remove(&out_ctxt->list);
7893 free(out_ctxt);
7894 } else {
7895 ALOGW("%s, output stream already closed", __func__);
7896 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007897 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007898 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007899 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007900}
7901
7902static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7903{
7904 struct audio_device *adev = (struct audio_device *)dev;
7905 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007906 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007907 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007908 int ret;
7909 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007910 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007911 struct listnode *node;
7912 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007913
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007914 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007915 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007916
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307917 if (!parms)
7918 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307919
Zhou Songd6d71752019-05-21 18:08:51 +08007920 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307921 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7922 if (ret >= 0) {
7923 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08007924 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307925 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08007926 } else {
7927 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307928 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007929 audio_extn_sco_reset_configuration();
7930 list_for_each(node, &adev->usecase_list) {
7931 usecase = node_to_item(node, struct audio_usecase, list);
7932 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
7933 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
7934 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
7935 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
7936 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
7937 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
7938 else
7939 continue;
7940 select_devices(adev, usecase->id);
7941 }
7942 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307943 }
7944
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007945 status = voice_set_parameters(adev, parms);
7946 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007947 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007948
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007949 status = platform_set_parameters(adev->platform, parms);
7950 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007951 goto done;
7952
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007953 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7954 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007955 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007956 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7957 adev->bluetooth_nrec = true;
7958 else
7959 adev->bluetooth_nrec = false;
7960 }
7961
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007962 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7963 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007964 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7965 adev->screen_off = false;
7966 else
7967 adev->screen_off = true;
7968 }
7969
Eric Laurent4b084132018-10-19 17:33:43 -07007970 ret = str_parms_get_int(parms, "rotation", &val);
7971 if (ret >= 0) {
7972 bool reverse_speakers = false;
7973 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7974 switch (val) {
7975 // FIXME: note that the code below assumes that the speakers are in the correct placement
7976 // relative to the user when the device is rotated 90deg from its default rotation. This
7977 // assumption is device-specific, not platform-specific like this code.
7978 case 270:
7979 reverse_speakers = true;
7980 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
7981 break;
7982 case 0:
7983 case 180:
7984 camera_rotation = CAMERA_ROTATION_PORTRAIT;
7985 break;
7986 case 90:
7987 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7988 break;
7989 default:
7990 ALOGE("%s: unexpected rotation of %d", __func__, val);
7991 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007992 }
Eric Laurent4b084132018-10-19 17:33:43 -07007993 if (status == 0) {
7994 // check and set swap
7995 // - check if orientation changed and speaker active
7996 // - set rotation and cache the rotation value
7997 adev->camera_orientation =
7998 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
7999 if (!audio_extn_is_maxx_audio_enabled())
8000 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8001 }
8002 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008003
Mingming Yin514a8bc2014-07-29 15:22:21 -07008004 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8005 if (ret >= 0) {
8006 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8007 adev->bt_wb_speech_enabled = true;
8008 else
8009 adev->bt_wb_speech_enabled = false;
8010 }
8011
Zhou Song12c29502019-03-16 10:37:18 +08008012 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8013 if (ret >= 0) {
8014 val = atoi(value);
8015 adev->swb_speech_mode = val;
8016 }
8017
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008018 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8019 if (ret >= 0) {
8020 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308021 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008022 if (audio_is_output_device(val) &&
8023 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008024 ALOGV("cache new ext disp type and edid");
8025 ret = platform_get_ext_disp_type(adev->platform);
8026 if (ret < 0) {
8027 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308028 } else {
8029 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008030 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308031 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008032 /*
8033 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8034 * Per AudioPolicyManager, USB device is higher priority than WFD.
8035 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8036 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8037 * starting voice call on USB
8038 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008039 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308040 if (ret >= 0)
8041 audio_extn_usb_add_device(device, atoi(value));
8042
Zhou Song6f862822017-11-06 17:27:57 +08008043 if (!audio_extn_usb_is_tunnel_supported()) {
8044 ALOGV("detected USB connect .. disable proxy");
8045 adev->allow_afe_proxy_usage = false;
8046 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008047 }
8048 }
8049
8050 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8051 if (ret >= 0) {
8052 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308053 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008054 /*
8055 * The HDMI / Displayport disconnect handling has been moved to
8056 * audio extension to ensure that its parameters are not
8057 * invalidated prior to updating sysfs of the disconnect event
8058 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8059 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308060 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008061 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308062 if (ret >= 0)
8063 audio_extn_usb_remove_device(device, atoi(value));
8064
Zhou Song6f862822017-11-06 17:27:57 +08008065 if (!audio_extn_usb_is_tunnel_supported()) {
8066 ALOGV("detected USB disconnect .. enable proxy");
8067 adev->allow_afe_proxy_usage = true;
8068 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008069 }
8070 }
8071
Aalique Grahame22e49102018-12-18 14:23:57 -08008072 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008073 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008074
8075 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008076 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308077 struct audio_usecase *usecase;
8078 struct listnode *node;
8079 list_for_each(node, &adev->usecase_list) {
8080 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308081 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008082 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308083 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008084
8085 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308086 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008087 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308088 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308089 //force device switch to re configure encoder
8090 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308091 audio_extn_a2dp_set_handoff_mode(false);
8092 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308093 break;
8094 }
8095 }
8096 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008097
8098 //handle vr audio setparam
8099 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8100 value, sizeof(value));
8101 if (ret >= 0) {
8102 ALOGI("Setting vr mode to be %s", value);
8103 if (!strncmp(value, "true", 4)) {
8104 adev->vr_audio_mode_enabled = true;
8105 ALOGI("Setting vr mode to true");
8106 } else if (!strncmp(value, "false", 5)) {
8107 adev->vr_audio_mode_enabled = false;
8108 ALOGI("Setting vr mode to false");
8109 } else {
8110 ALOGI("wrong vr mode set");
8111 }
8112 }
8113
Eric Laurent4b084132018-10-19 17:33:43 -07008114 //FIXME: to be replaced by proper video capture properties API
8115 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8116 if (ret >= 0) {
8117 int camera_facing = CAMERA_FACING_BACK;
8118 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8119 camera_facing = CAMERA_FACING_FRONT;
8120 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8121 camera_facing = CAMERA_FACING_BACK;
8122 else {
8123 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8124 goto done;
8125 }
8126 adev->camera_orientation =
8127 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8128 struct audio_usecase *usecase;
8129 struct listnode *node;
8130 list_for_each(node, &adev->usecase_list) {
8131 usecase = node_to_item(node, struct audio_usecase, list);
8132 struct stream_in *in = usecase->stream.in;
8133 if (usecase->type == PCM_CAPTURE && in != NULL &&
8134 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8135 select_devices(adev, in->usecase);
8136 }
8137 }
8138 }
8139
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308140 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008141done:
8142 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008143 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308144error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008145 ALOGV("%s: exit with code(%d)", __func__, status);
8146 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008147}
8148
8149static char* adev_get_parameters(const struct audio_hw_device *dev,
8150 const char *keys)
8151{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308152 ALOGD("%s:%s", __func__, keys);
8153
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008154 struct audio_device *adev = (struct audio_device *)dev;
8155 struct str_parms *reply = str_parms_create();
8156 struct str_parms *query = str_parms_create_str(keys);
8157 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308158 char value[256] = {0};
8159 int ret = 0;
8160
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008161 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008162 if (reply) {
8163 str_parms_destroy(reply);
8164 }
8165 if (query) {
8166 str_parms_destroy(query);
8167 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008168 ALOGE("adev_get_parameters: failed to create query or reply");
8169 return NULL;
8170 }
8171
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008172 //handle vr audio getparam
8173
8174 ret = str_parms_get_str(query,
8175 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8176 value, sizeof(value));
8177
8178 if (ret >= 0) {
8179 bool vr_audio_enabled = false;
8180 pthread_mutex_lock(&adev->lock);
8181 vr_audio_enabled = adev->vr_audio_mode_enabled;
8182 pthread_mutex_unlock(&adev->lock);
8183
8184 ALOGI("getting vr mode to %d", vr_audio_enabled);
8185
8186 if (vr_audio_enabled) {
8187 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8188 "true");
8189 goto exit;
8190 } else {
8191 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8192 "false");
8193 goto exit;
8194 }
8195 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008196
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008197 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008198 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008199 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008200 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008201 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308202 pthread_mutex_unlock(&adev->lock);
8203
Naresh Tannirud7205b62014-06-20 02:54:48 +05308204exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008205 str = str_parms_to_str(reply);
8206 str_parms_destroy(query);
8207 str_parms_destroy(reply);
8208
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308209 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008210 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008211}
8212
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008213static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008214{
8215 return 0;
8216}
8217
8218static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8219{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008220 int ret;
8221 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008222
8223 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8224
Haynes Mathew George5191a852013-09-11 14:19:36 -07008225 pthread_mutex_lock(&adev->lock);
8226 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008227 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008228 pthread_mutex_unlock(&adev->lock);
8229 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008230}
8231
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008232static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8233 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008234{
8235 return -ENOSYS;
8236}
8237
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008238static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8239 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008240{
8241 return -ENOSYS;
8242}
8243
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008244static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8245 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008246{
8247 return -ENOSYS;
8248}
8249
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008250static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8251 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008252{
8253 return -ENOSYS;
8254}
8255
8256static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8257{
8258 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008259 struct listnode *node;
8260 struct audio_usecase *usecase = NULL;
8261 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008263 pthread_mutex_lock(&adev->lock);
8264 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008265 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008266 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008267 if (voice_is_in_call(adev) &&
8268 (mode == AUDIO_MODE_NORMAL ||
8269 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008270 list_for_each(node, &adev->usecase_list) {
8271 usecase = node_to_item(node, struct audio_usecase, list);
8272 if (usecase->type == VOICE_CALL)
8273 break;
8274 }
8275 if (usecase &&
8276 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8277 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8278 true);
8279 if (ret != 0) {
8280 /* default service interval was successfully updated,
8281 reopen USB backend with new service interval */
8282 check_usecases_codec_backend(adev,
8283 usecase,
8284 usecase->out_snd_device);
8285 }
8286 }
8287
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008288 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008289 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008290 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008291 // restore device for other active usecases after stop call
8292 list_for_each(node, &adev->usecase_list) {
8293 usecase = node_to_item(node, struct audio_usecase, list);
8294 select_devices(adev, usecase->id);
8295 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008297 }
8298 pthread_mutex_unlock(&adev->lock);
8299 return 0;
8300}
8301
8302static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8303{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008304 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008305 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008306
8307 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008308 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008309 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008310
Derek Chend2530072014-11-24 12:39:14 -08008311 if (adev->ext_hw_plugin)
8312 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008313
8314 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008315 pthread_mutex_unlock(&adev->lock);
8316
8317 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008318}
8319
8320static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8321{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008322 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008323 return 0;
8324}
8325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008326static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008327 const struct audio_config *config)
8328{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008329 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008330
Aalique Grahame22e49102018-12-18 14:23:57 -08008331 /* Don't know if USB HIFI in this context so use true to be conservative */
8332 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8333 true /*is_usb_hifi */) != 0)
8334 return 0;
8335
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008336 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8337 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008338}
8339
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008340static bool adev_input_allow_hifi_record(struct audio_device *adev,
8341 audio_devices_t devices,
8342 audio_input_flags_t flags,
8343 audio_source_t source) {
8344 const bool allowed = true;
8345
8346 if (!audio_is_usb_in_device(devices))
8347 return !allowed;
8348
8349 switch (flags) {
8350 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008351 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008352 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8353 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008354 default:
8355 return !allowed;
8356 }
8357
8358 switch (source) {
8359 case AUDIO_SOURCE_DEFAULT:
8360 case AUDIO_SOURCE_MIC:
8361 case AUDIO_SOURCE_UNPROCESSED:
8362 break;
8363 default:
8364 return !allowed;
8365 }
8366
8367 switch (adev->mode) {
8368 case 0:
8369 break;
8370 default:
8371 return !allowed;
8372 }
8373
8374 return allowed;
8375}
8376
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008377static int adev_update_voice_comm_input_stream(struct stream_in *in,
8378 struct audio_config *config)
8379{
8380 bool valid_rate = (config->sample_rate == 8000 ||
8381 config->sample_rate == 16000 ||
8382 config->sample_rate == 32000 ||
8383 config->sample_rate == 48000);
8384 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8385
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008386 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008387 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008388 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8389 in->config = default_pcm_config_voip_copp;
8390 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8391 DEFAULT_VOIP_BUF_DURATION_MS,
8392 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008393 } else {
8394 ALOGW("%s No valid input in voip, use defaults"
8395 "sample rate %u, channel mask 0x%X",
8396 __func__, config->sample_rate, in->channel_mask);
8397 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008398 in->config.rate = config->sample_rate;
8399 in->sample_rate = config->sample_rate;
8400 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008401 //XXX needed for voice_extn_compress_voip_open_input_stream
8402 in->config.rate = config->sample_rate;
8403 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8404 voice_extn_compress_voip_is_active(in->dev)) &&
8405 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8406 valid_rate && valid_ch) {
8407 voice_extn_compress_voip_open_input_stream(in);
8408 // update rate entries to match config from AF
8409 in->config.rate = config->sample_rate;
8410 in->sample_rate = config->sample_rate;
8411 } else {
8412 ALOGW("%s compress voip not active, use defaults", __func__);
8413 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008414 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008415 return 0;
8416}
8417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008418static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008419 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008420 audio_devices_t devices,
8421 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008422 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308423 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008424 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008425 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008426{
8427 struct audio_device *adev = (struct audio_device *)dev;
8428 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008429 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008430 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008431 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308432 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008433 bool is_usb_dev = audio_is_usb_in_device(devices);
8434 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8435 devices,
8436 flags,
8437 source);
Andy Hung94320602018-10-29 18:31:12 -07008438 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8439 " sample_rate %u, channel_mask %#x, format %#x",
8440 __func__, flags, is_usb_dev, may_use_hifi_record,
8441 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308442
kunleizdff872d2018-08-20 14:40:33 +08008443 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008444 is_usb_dev = false;
8445 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8446 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8447 __func__, devices);
8448 }
8449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008450 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008451
8452 if (!(is_usb_dev && may_use_hifi_record)) {
8453 if (config->sample_rate == 0)
8454 config->sample_rate = 48000;
8455 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8456 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8457 if (config->format == AUDIO_FORMAT_DEFAULT)
8458 config->format = AUDIO_FORMAT_PCM_16_BIT;
8459
8460 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8461
Aalique Grahame22e49102018-12-18 14:23:57 -08008462 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8463 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008464 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308465 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008466
8467 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008468
8469 if (!in) {
8470 ALOGE("failed to allocate input stream");
8471 return -ENOMEM;
8472 }
8473
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308474 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308475 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8476 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008477 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008478 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008480 in->stream.common.get_sample_rate = in_get_sample_rate;
8481 in->stream.common.set_sample_rate = in_set_sample_rate;
8482 in->stream.common.get_buffer_size = in_get_buffer_size;
8483 in->stream.common.get_channels = in_get_channels;
8484 in->stream.common.get_format = in_get_format;
8485 in->stream.common.set_format = in_set_format;
8486 in->stream.common.standby = in_standby;
8487 in->stream.common.dump = in_dump;
8488 in->stream.common.set_parameters = in_set_parameters;
8489 in->stream.common.get_parameters = in_get_parameters;
8490 in->stream.common.add_audio_effect = in_add_audio_effect;
8491 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8492 in->stream.set_gain = in_set_gain;
8493 in->stream.read = in_read;
8494 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008495 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308496 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008497 in->stream.set_microphone_direction = in_set_microphone_direction;
8498 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008499 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008500
8501 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008502 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008503 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008504 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008505 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008506 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008507 in->bit_width = 16;
8508 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008509 in->direction = MIC_DIRECTION_UNSPECIFIED;
8510 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008511 list_init(&in->aec_list);
8512 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008513
Andy Hung94320602018-10-29 18:31:12 -07008514 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008515 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8516 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8517 /* Force channel config requested to mono if incall
8518 record is being requested for only uplink/downlink */
8519 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8520 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8521 ret = -EINVAL;
8522 goto err_open;
8523 }
8524 }
8525
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008526 if (is_usb_dev && may_use_hifi_record) {
8527 /* HiFi record selects an appropriate format, channel, rate combo
8528 depending on sink capabilities*/
8529 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8530 &config->format,
8531 &in->supported_formats[0],
8532 MAX_SUPPORTED_FORMATS,
8533 &config->channel_mask,
8534 &in->supported_channel_masks[0],
8535 MAX_SUPPORTED_CHANNEL_MASKS,
8536 &config->sample_rate,
8537 &in->supported_sample_rates[0],
8538 MAX_SUPPORTED_SAMPLE_RATES);
8539 if (ret != 0) {
8540 ret = -EINVAL;
8541 goto err_open;
8542 }
8543 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008544 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308545 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308546 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8547 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8548 in->config.format = PCM_FORMAT_S32_LE;
8549 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308550 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8551 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8552 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8553 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8554 bool ret_error = false;
8555 in->bit_width = 24;
8556 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8557 from HAL is 24_packed and 8_24
8558 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8559 24_packed return error indicating supported format is 24_packed
8560 *> In case of any other source requesting 24 bit or float return error
8561 indicating format supported is 16 bit only.
8562
8563 on error flinger will retry with supported format passed
8564 */
8565 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8566 (source != AUDIO_SOURCE_CAMCORDER)) {
8567 config->format = AUDIO_FORMAT_PCM_16_BIT;
8568 if (config->sample_rate > 48000)
8569 config->sample_rate = 48000;
8570 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008571 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8572 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308573 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8574 ret_error = true;
8575 }
8576
8577 if (ret_error) {
8578 ret = -EINVAL;
8579 goto err_open;
8580 }
8581 }
8582
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008583 in->channel_mask = config->channel_mask;
8584 in->format = config->format;
8585
8586 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308587
8588 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8589 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8590 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8591 else {
8592 ret = -EINVAL;
8593 goto err_open;
8594 }
8595 }
8596
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008597 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8598 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8599 is_low_latency = true;
8600#if LOW_LATENCY_CAPTURE_USE_CASE
8601 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8602#endif
8603 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008604 if (!in->realtime) {
8605 in->config = pcm_config_audio_capture;
8606 frame_size = audio_stream_in_frame_size(&in->stream);
8607 buffer_size = get_input_buffer_size(config->sample_rate,
8608 config->format,
8609 channel_count,
8610 is_low_latency);
8611 in->config.period_size = buffer_size / frame_size;
8612 in->config.rate = config->sample_rate;
8613 in->af_period_multiplier = 1;
8614 } else {
8615 // period size is left untouched for rt mode playback
8616 in->config = pcm_config_audio_capture_rt;
8617 in->af_period_multiplier = af_period_multiplier;
8618 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008619 }
8620
8621 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8622 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8623 in->realtime = 0;
8624 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8625 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008626 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008627 in->stream.start = in_start;
8628 in->stream.stop = in_stop;
8629 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8630 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008631 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8632 } else if (in->realtime) {
8633 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008634 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008635 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008636 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008637 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8638 in->config = pcm_config_audio_capture;
8639 frame_size = audio_stream_in_frame_size(&in->stream);
8640 buffer_size = get_input_buffer_size(config->sample_rate,
8641 config->format,
8642 channel_count,
8643 false /*is_low_latency*/);
8644 in->config.period_size = buffer_size / frame_size;
8645 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008646 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008647 switch (config->format) {
8648 case AUDIO_FORMAT_PCM_32_BIT:
8649 in->bit_width = 32;
8650 break;
8651 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8652 case AUDIO_FORMAT_PCM_8_24_BIT:
8653 in->bit_width = 24;
8654 break;
8655 default:
8656 in->bit_width = 16;
8657 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008658 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308659 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008660 if (config->sample_rate == 0)
8661 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8662 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8663 config->sample_rate != 8000) {
8664 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8665 ret = -EINVAL;
8666 goto err_open;
8667 }
8668 if (config->format == AUDIO_FORMAT_DEFAULT)
8669 config->format = AUDIO_FORMAT_PCM_16_BIT;
8670 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8671 config->format = AUDIO_FORMAT_PCM_16_BIT;
8672 ret = -EINVAL;
8673 goto err_open;
8674 }
8675
8676 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8677 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008678 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008679 in->af_period_multiplier = 1;
8680 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8681 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8682 (config->sample_rate == 8000 ||
8683 config->sample_rate == 16000 ||
8684 config->sample_rate == 32000 ||
8685 config->sample_rate == 48000) &&
8686 channel_count == 1) {
8687 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8688 in->config = pcm_config_audio_capture;
8689 frame_size = audio_stream_in_frame_size(&in->stream);
8690 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8691 config->sample_rate,
8692 config->format,
8693 channel_count, false /*is_low_latency*/);
8694 in->config.period_size = buffer_size / frame_size;
8695 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8696 in->config.rate = config->sample_rate;
8697 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008698 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308699 int ret_val;
8700 pthread_mutex_lock(&adev->lock);
8701 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8702 in, config, &channel_mask_updated);
8703 pthread_mutex_unlock(&adev->lock);
8704
8705 if (!ret_val) {
8706 if (channel_mask_updated == true) {
8707 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8708 __func__, config->channel_mask);
8709 ret = -EINVAL;
8710 goto err_open;
8711 }
8712 ALOGD("%s: created multi-channel session succesfully",__func__);
8713 } else if (audio_extn_compr_cap_enabled() &&
8714 audio_extn_compr_cap_format_supported(config->format) &&
8715 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8716 audio_extn_compr_cap_init(in);
8717 } else if (audio_extn_cin_applicable_stream(in)) {
8718 ret = audio_extn_cin_configure_input_stream(in);
8719 if (ret)
8720 goto err_open;
8721 } else {
8722 in->config = pcm_config_audio_capture;
8723 in->config.rate = config->sample_rate;
8724 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308725 in->format = config->format;
8726 frame_size = audio_stream_in_frame_size(&in->stream);
8727 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008728 config->format,
8729 channel_count,
8730 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008731 /* prevent division-by-zero */
8732 if (frame_size == 0) {
8733 ALOGE("%s: Error frame_size==0", __func__);
8734 ret = -EINVAL;
8735 goto err_open;
8736 }
8737
Revathi Uddarajud2634032017-12-07 14:42:34 +05308738 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008739 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008740
Revathi Uddarajud2634032017-12-07 14:42:34 +05308741 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8742 /* optionally use VOIP usecase depending on config(s) */
8743 ret = adev_update_voice_comm_input_stream(in, config);
8744 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008745
Revathi Uddarajud2634032017-12-07 14:42:34 +05308746 if (ret) {
8747 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8748 goto err_open;
8749 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008750 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308751 if (audio_extn_is_concurrent_capture_enabled()) {
8752 /* Acquire lock to avoid two concurrent use cases initialized to
8753 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008754
Samyak Jainc37062f2019-04-25 18:41:06 +05308755 if (in->usecase == USECASE_AUDIO_RECORD) {
8756 pthread_mutex_lock(&adev->lock);
8757 if (!(adev->pcm_record_uc_state)) {
8758 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8759 adev->pcm_record_uc_state = 1;
8760 pthread_mutex_unlock(&adev->lock);
8761 } else {
8762 pthread_mutex_unlock(&adev->lock);
8763 /* Assign compress record use case for second record */
8764 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8765 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8766 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8767 if (audio_extn_cin_applicable_stream(in)) {
8768 in->sample_rate = config->sample_rate;
8769 ret = audio_extn_cin_configure_input_stream(in);
8770 if (ret)
8771 goto err_open;
8772 }
8773 }
8774 }
kunleiz28c73e72019-03-27 17:24:04 +08008775 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008776 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008777
8778 in->config.channels = channel_count;
8779 in->sample_rate = in->config.rate;
8780
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308781 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8782 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008783 devices, flags, in->format,
8784 in->sample_rate, in->bit_width,
8785 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308786 register_format(in->format, in->supported_formats);
8787 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8788 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308789
Aalique Grahame22e49102018-12-18 14:23:57 -08008790 in->error_log = error_log_create(
8791 ERROR_LOG_ENTRIES,
8792 1000000000 /* aggregate consecutive identical errors within one second */);
8793
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008794 /* This stream could be for sound trigger lab,
8795 get sound trigger pcm if present */
8796 audio_extn_sound_trigger_check_and_get_session(in);
8797
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308798 lock_input_stream(in);
8799 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8800 pthread_mutex_lock(&adev->lock);
8801 in->card_status = adev->card_status;
8802 pthread_mutex_unlock(&adev->lock);
8803 pthread_mutex_unlock(&in->lock);
8804
Aalique Grahame22e49102018-12-18 14:23:57 -08008805 stream_app_type_cfg_init(&in->app_type_cfg);
8806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008807 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008808
8809 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8810 calloc(1, sizeof(streams_input_ctxt_t));
8811 if (in_ctxt == NULL) {
8812 ALOGE("%s fail to allocate input ctxt", __func__);
8813 ret = -ENOMEM;
8814 goto err_open;
8815 }
8816 in_ctxt->input = in;
8817
8818 pthread_mutex_lock(&adev->lock);
8819 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8820 pthread_mutex_unlock(&adev->lock);
8821
Eric Laurent994a6932013-07-17 11:51:42 -07008822 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008823 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824
8825err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308826 if (in->usecase == USECASE_AUDIO_RECORD) {
8827 pthread_mutex_lock(&adev->lock);
8828 adev->pcm_record_uc_state = 0;
8829 pthread_mutex_unlock(&adev->lock);
8830 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008831 free(in);
8832 *stream_in = NULL;
8833 return ret;
8834}
8835
8836static void adev_close_input_stream(struct audio_hw_device *dev,
8837 struct audio_stream_in *stream)
8838{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008839 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008840 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008841 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308842
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308843 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008844
kunleiz70e57612018-12-28 17:50:23 +08008845 /* must deregister from sndmonitor first to prevent races
8846 * between the callback and close_stream
8847 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308848 audio_extn_snd_mon_unregister_listener(stream);
8849
kunleiz70e57612018-12-28 17:50:23 +08008850 /* Disable echo reference if there are no active input, hfp call
8851 * and sound trigger while closing input stream
8852 */
Eric Laurent637e2d42018-11-15 12:24:31 -08008853 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08008854 !audio_extn_hfp_is_active(adev) &&
8855 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008856 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008857 else
8858 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308859
Pallavid7c7a272018-01-16 11:22:55 +05308860 if (in == NULL) {
8861 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8862 return;
8863 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008864 error_log_destroy(in->error_log);
8865 in->error_log = NULL;
8866
Pallavid7c7a272018-01-16 11:22:55 +05308867
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008868 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308869 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008870 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308871 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008872 if (ret != 0)
8873 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8874 __func__, ret);
8875 } else
8876 in_standby(&stream->common);
8877
Revathi Uddarajud2634032017-12-07 14:42:34 +05308878 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308879 if (in->usecase == USECASE_AUDIO_RECORD) {
8880 adev->pcm_record_uc_state = 0;
8881 }
8882
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008883 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008884 audio_extn_ssr_deinit();
8885 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008886
Garmond Leunge2433c32017-09-28 21:51:22 -07008887 if (audio_extn_ffv_get_stream() == in) {
8888 audio_extn_ffv_stream_deinit();
8889 }
8890
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308891 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008892 audio_extn_compr_cap_format_supported(in->config.format))
8893 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308894
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308895 if (audio_extn_cin_attached_usecase(in->usecase))
8896 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008897
Mingming Yinfd7607b2016-01-22 12:48:44 -08008898 if (in->is_st_session) {
8899 ALOGV("%s: sound trigger pcm stop lab", __func__);
8900 audio_extn_sound_trigger_stop_lab(in);
8901 }
Derek Chenf939fb72018-11-13 13:34:41 -08008902 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8903 if (in_ctxt != NULL) {
8904 list_remove(&in_ctxt->list);
8905 free(in_ctxt);
8906 } else {
8907 ALOGW("%s, input stream already closed", __func__);
8908 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008909 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308910 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008911 return;
8912}
8913
Aalique Grahame22e49102018-12-18 14:23:57 -08008914/* verifies input and output devices and their capabilities.
8915 *
8916 * This verification is required when enabling extended bit-depth or
8917 * sampling rates, as not all qcom products support it.
8918 *
8919 * Suitable for calling only on initialization such as adev_open().
8920 * It fills the audio_device use_case_table[] array.
8921 *
8922 * Has a side-effect that it needs to configure audio routing / devices
8923 * in order to power up the devices and read the device parameters.
8924 * It does not acquire any hw device lock. Should restore the devices
8925 * back to "normal state" upon completion.
8926 */
8927static int adev_verify_devices(struct audio_device *adev)
8928{
8929 /* enumeration is a bit difficult because one really wants to pull
8930 * the use_case, device id, etc from the hidden pcm_device_table[].
8931 * In this case there are the following use cases and device ids.
8932 *
8933 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8934 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8935 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8936 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8937 * [USECASE_AUDIO_RECORD] = {0, 0},
8938 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8939 * [USECASE_VOICE_CALL] = {2, 2},
8940 *
8941 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8942 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8943 */
8944
8945 /* should be the usecases enabled in adev_open_input_stream() */
8946 static const int test_in_usecases[] = {
8947 USECASE_AUDIO_RECORD,
8948 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8949 };
8950 /* should be the usecases enabled in adev_open_output_stream()*/
8951 static const int test_out_usecases[] = {
8952 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8953 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8954 };
8955 static const usecase_type_t usecase_type_by_dir[] = {
8956 PCM_PLAYBACK,
8957 PCM_CAPTURE,
8958 };
8959 static const unsigned flags_by_dir[] = {
8960 PCM_OUT,
8961 PCM_IN,
8962 };
8963
8964 size_t i;
8965 unsigned dir;
8966 const unsigned card_id = adev->snd_card;
8967
8968 for (dir = 0; dir < 2; ++dir) {
8969 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8970 const unsigned flags_dir = flags_by_dir[dir];
8971 const size_t testsize =
8972 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8973 const int *testcases =
8974 dir ? test_in_usecases : test_out_usecases;
8975 const audio_devices_t audio_device =
8976 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8977
8978 for (i = 0; i < testsize; ++i) {
8979 const audio_usecase_t audio_usecase = testcases[i];
8980 int device_id;
8981 struct pcm_params **pparams;
8982 struct stream_out out;
8983 struct stream_in in;
8984 struct audio_usecase uc_info;
8985 int retval;
8986
8987 pparams = &adev->use_case_table[audio_usecase];
8988 pcm_params_free(*pparams); /* can accept null input */
8989 *pparams = NULL;
8990
8991 /* find the device ID for the use case (signed, for error) */
8992 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8993 if (device_id < 0)
8994 continue;
8995
8996 /* prepare structures for device probing */
8997 memset(&uc_info, 0, sizeof(uc_info));
8998 uc_info.id = audio_usecase;
8999 uc_info.type = usecase_type;
9000 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009001 memset(&in, 0, sizeof(in));
9002 in.device = audio_device;
9003 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9004 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009005 }
9006 memset(&out, 0, sizeof(out));
9007 out.devices = audio_device; /* only field needed in select_devices */
9008 uc_info.stream.out = &out;
9009 uc_info.devices = audio_device;
9010 uc_info.in_snd_device = SND_DEVICE_NONE;
9011 uc_info.out_snd_device = SND_DEVICE_NONE;
9012 list_add_tail(&adev->usecase_list, &uc_info.list);
9013
9014 /* select device - similar to start_(in/out)put_stream() */
9015 retval = select_devices(adev, audio_usecase);
9016 if (retval >= 0) {
9017 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9018#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009019 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009020 if (*pparams) {
9021 ALOGV("%s: (%s) card %d device %d", __func__,
9022 dir ? "input" : "output", card_id, device_id);
9023 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9024 } else {
9025 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9026 }
9027#endif
9028 }
9029
9030 /* deselect device - similar to stop_(in/out)put_stream() */
9031 /* 1. Get and set stream specific mixer controls */
9032 retval = disable_audio_route(adev, &uc_info);
9033 /* 2. Disable the rx device */
9034 retval = disable_snd_device(adev,
9035 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9036 list_remove(&uc_info.list);
9037 }
9038 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009039 return 0;
9040}
9041
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309042int adev_create_audio_patch(struct audio_hw_device *dev,
9043 unsigned int num_sources,
9044 const struct audio_port_config *sources,
9045 unsigned int num_sinks,
9046 const struct audio_port_config *sinks,
9047 audio_patch_handle_t *handle)
9048{
Derek Chenf939fb72018-11-13 13:34:41 -08009049 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309050
Derek Chenf939fb72018-11-13 13:34:41 -08009051 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9052 num_sources,
9053 sources,
9054 num_sinks,
9055 sinks,
9056 handle);
9057 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9058 num_sources,
9059 sources,
9060 num_sinks,
9061 sinks,
9062 handle);
9063 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309064}
9065
9066int adev_release_audio_patch(struct audio_hw_device *dev,
9067 audio_patch_handle_t handle)
9068{
Derek Chenf939fb72018-11-13 13:34:41 -08009069 int ret;
9070
9071 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9072 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9073 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309074}
9075
9076int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9077{
9078 return audio_extn_hw_loopback_get_audio_port(dev, config);
9079}
9080
9081int adev_set_audio_port_config(struct audio_hw_device *dev,
9082 const struct audio_port_config *config)
9083{
9084 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
9085}
9086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009087static int adev_dump(const audio_hw_device_t *device __unused,
9088 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009089{
9090 return 0;
9091}
9092
9093static int adev_close(hw_device_t *device)
9094{
Aalique Grahame22e49102018-12-18 14:23:57 -08009095 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009096 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009097
9098 if (!adev)
9099 return 0;
9100
9101 pthread_mutex_lock(&adev_init_lock);
9102
9103 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309104 if (audio_extn_spkr_prot_is_enabled())
9105 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309106 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009107 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009108 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009109 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009110 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309111 audio_extn_utils_release_streams_cfg_lists(
9112 &adev->streams_output_cfg_list,
9113 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309114 if (audio_extn_qaf_is_enabled())
9115 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009116 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009117 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009118 free(adev->snd_dev_ref_cnt);
9119 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009120 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9121 pcm_params_free(adev->use_case_table[i]);
9122 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009123 if (adev->adm_deinit)
9124 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309125 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009126 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309127 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309128 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009129 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309130 if (adev->device_cfg_params) {
9131 free(adev->device_cfg_params);
9132 adev->device_cfg_params = NULL;
9133 }
Derek Chend2530072014-11-24 12:39:14 -08009134 if(adev->ext_hw_plugin)
9135 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009136 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009137 free(device);
9138 adev = NULL;
9139 }
9140 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309141 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009142 return 0;
9143}
9144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009145/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9146 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9147 * just that it _might_ work.
9148 */
9149static int period_size_is_plausible_for_low_latency(int period_size)
9150{
9151 switch (period_size) {
9152 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009153 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009154 case 240:
9155 case 320:
9156 case 480:
9157 return 1;
9158 default:
9159 return 0;
9160 }
9161}
9162
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309163static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9164{
9165 bool is_snd_card_status = false;
9166 bool is_ext_device_status = false;
9167 char value[32];
9168 int card = -1;
9169 card_status_t status;
9170
9171 if (cookie != adev || !parms)
9172 return;
9173
9174 if (!parse_snd_card_status(parms, &card, &status)) {
9175 is_snd_card_status = true;
9176 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9177 is_ext_device_status = true;
9178 } else {
9179 // not a valid event
9180 return;
9181 }
9182
9183 pthread_mutex_lock(&adev->lock);
9184 if (card == adev->snd_card || is_ext_device_status) {
9185 if (is_snd_card_status && adev->card_status != status) {
9186 adev->card_status = status;
9187 platform_snd_card_update(adev->platform, status);
9188 audio_extn_fm_set_parameters(adev, parms);
9189 } else if (is_ext_device_status) {
9190 platform_set_parameters(adev->platform, parms);
9191 }
9192 }
9193 pthread_mutex_unlock(&adev->lock);
9194 return;
9195}
9196
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309197/* out and adev lock held */
9198static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9199{
9200 struct audio_usecase *uc_info;
9201 float left_p;
9202 float right_p;
9203 audio_devices_t devices;
9204
9205 uc_info = get_usecase_from_list(adev, out->usecase);
9206 if (uc_info == NULL) {
9207 ALOGE("%s: Could not find the usecase (%d) in the list",
9208 __func__, out->usecase);
9209 return -EINVAL;
9210 }
9211
9212 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9213 out->usecase, use_case_table[out->usecase]);
9214
9215 if (restore) {
9216 // restore A2DP device for active usecases and unmute if required
9217 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9218 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9219 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9220 select_devices(adev, uc_info->id);
9221 pthread_mutex_lock(&out->compr_mute_lock);
9222 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9223 (out->a2dp_compress_mute)) {
9224 out->a2dp_compress_mute = false;
9225 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9226 }
9227 pthread_mutex_unlock(&out->compr_mute_lock);
9228 }
9229 } else {
9230 // mute compress stream if suspended
9231 pthread_mutex_lock(&out->compr_mute_lock);
9232 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9233 (!out->a2dp_compress_mute)) {
9234 if (!out->standby) {
9235 ALOGD("%s: selecting speaker and muting stream", __func__);
9236 devices = out->devices;
9237 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9238 left_p = out->volume_l;
9239 right_p = out->volume_r;
9240 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9241 compress_pause(out->compr);
9242 out_set_compr_volume(&out->stream, (float)0, (float)0);
9243 out->a2dp_compress_mute = true;
9244 select_devices(adev, out->usecase);
9245 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9246 compress_resume(out->compr);
9247 out->devices = devices;
9248 out->volume_l = left_p;
9249 out->volume_r = right_p;
9250 }
9251 }
9252 pthread_mutex_unlock(&out->compr_mute_lock);
9253 }
9254 ALOGV("%s: exit", __func__);
9255 return 0;
9256}
9257
9258int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9259{
9260 int ret = 0;
9261
9262 lock_output_stream(out);
9263 pthread_mutex_lock(&adev->lock);
9264
9265 ret = check_a2dp_restore_l(adev, out, restore);
9266
9267 pthread_mutex_unlock(&adev->lock);
9268 pthread_mutex_unlock(&out->lock);
9269 return ret;
9270}
9271
Haynes Mathew George01156f92018-04-13 15:29:54 -07009272void adev_on_battery_status_changed(bool charging)
9273{
9274 pthread_mutex_lock(&adev->lock);
9275 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9276 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009277 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009278 pthread_mutex_unlock(&adev->lock);
9279}
9280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009281static int adev_open(const hw_module_t *module, const char *name,
9282 hw_device_t **device)
9283{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309284 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009285 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309286 char mixer_ctl_name[128] = {0};
9287 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309288
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009289 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009290 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9291
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009292 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009293 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009294 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009295 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009296 ALOGD("%s: returning existing instance of adev", __func__);
9297 ALOGD("%s: exit", __func__);
9298 pthread_mutex_unlock(&adev_init_lock);
9299 return 0;
9300 }
9301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009302 adev = calloc(1, sizeof(struct audio_device));
9303
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009304 if (!adev) {
9305 pthread_mutex_unlock(&adev_init_lock);
9306 return -ENOMEM;
9307 }
9308
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009309 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9310
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009311 // register audio ext hidl at the earliest
9312 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309313#ifdef DYNAMIC_LOG_ENABLED
9314 register_for_dynamic_logging("hal");
9315#endif
9316
Derek Chenf939fb72018-11-13 13:34:41 -08009317 /* default audio HAL major version */
9318 uint32_t maj_version = 2;
9319 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9320 maj_version = atoi(value);
9321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009322 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009323 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009324 adev->device.common.module = (struct hw_module_t *)module;
9325 adev->device.common.close = adev_close;
9326
9327 adev->device.init_check = adev_init_check;
9328 adev->device.set_voice_volume = adev_set_voice_volume;
9329 adev->device.set_master_volume = adev_set_master_volume;
9330 adev->device.get_master_volume = adev_get_master_volume;
9331 adev->device.set_master_mute = adev_set_master_mute;
9332 adev->device.get_master_mute = adev_get_master_mute;
9333 adev->device.set_mode = adev_set_mode;
9334 adev->device.set_mic_mute = adev_set_mic_mute;
9335 adev->device.get_mic_mute = adev_get_mic_mute;
9336 adev->device.set_parameters = adev_set_parameters;
9337 adev->device.get_parameters = adev_get_parameters;
9338 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9339 adev->device.open_output_stream = adev_open_output_stream;
9340 adev->device.close_output_stream = adev_close_output_stream;
9341 adev->device.open_input_stream = adev_open_input_stream;
9342 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309343 adev->device.create_audio_patch = adev_create_audio_patch;
9344 adev->device.release_audio_patch = adev_release_audio_patch;
9345 adev->device.get_audio_port = adev_get_audio_port;
9346 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009347 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309348 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009349
9350 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009351 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009352 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009353 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009354 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009355 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009356 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309357 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009358 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009359 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009360 /* Init audio and voice feature */
9361 audio_extn_feature_init();
9362 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009363 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009364 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009365 list_init(&adev->active_inputs_list);
9366 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009367 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009368 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309369 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309370 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309371 adev->perf_lock_opts[0] = 0x101;
9372 adev->perf_lock_opts[1] = 0x20E;
9373 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009374 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009375 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309376 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009377 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009379 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009380 adev->platform = platform_init(adev);
9381 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009382 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009383 free(adev->snd_dev_ref_cnt);
9384 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009385 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009386 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9387 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009388 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009389 return -EINVAL;
9390 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009391
Aalique Grahame22e49102018-12-18 14:23:57 -08009392 adev->extspk = audio_extn_extspk_init(adev);
9393
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309394 if (audio_extn_qaf_is_enabled()) {
9395 ret = audio_extn_qaf_init(adev);
9396 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009397 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309398 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009399 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309400 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9401 *device = NULL;
9402 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309403 return ret;
9404 }
9405
9406 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9407 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9408 }
9409
Derek Chenae7b0342019-02-08 15:17:04 -08009410 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009411 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9412
Eric Laurentc4aef752013-09-12 17:45:53 -07009413 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9414 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9415 if (adev->visualizer_lib == NULL) {
9416 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9417 } else {
9418 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9419 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009420 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009421 "visualizer_hal_start_output");
9422 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009423 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009424 "visualizer_hal_stop_output");
9425 }
9426 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309427 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009428 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009429 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009430 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309431 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009432 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009433
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009434 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9435 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9436 if (adev->offload_effects_lib == NULL) {
9437 ALOGE("%s: DLOPEN failed for %s", __func__,
9438 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9439 } else {
9440 ALOGV("%s: DLOPEN successful for %s", __func__,
9441 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9442 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309443 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009444 "offload_effects_bundle_hal_start_output");
9445 adev->offload_effects_stop_output =
9446 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9447 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009448 adev->offload_effects_set_hpx_state =
9449 (int (*)(bool))dlsym(adev->offload_effects_lib,
9450 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309451 adev->offload_effects_get_parameters =
9452 (void (*)(struct str_parms *, struct str_parms *))
9453 dlsym(adev->offload_effects_lib,
9454 "offload_effects_bundle_get_parameters");
9455 adev->offload_effects_set_parameters =
9456 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9457 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009458 }
9459 }
9460
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009461 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9462 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9463 if (adev->adm_lib == NULL) {
9464 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9465 } else {
9466 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9467 adev->adm_init = (adm_init_t)
9468 dlsym(adev->adm_lib, "adm_init");
9469 adev->adm_deinit = (adm_deinit_t)
9470 dlsym(adev->adm_lib, "adm_deinit");
9471 adev->adm_register_input_stream = (adm_register_input_stream_t)
9472 dlsym(adev->adm_lib, "adm_register_input_stream");
9473 adev->adm_register_output_stream = (adm_register_output_stream_t)
9474 dlsym(adev->adm_lib, "adm_register_output_stream");
9475 adev->adm_deregister_stream = (adm_deregister_stream_t)
9476 dlsym(adev->adm_lib, "adm_deregister_stream");
9477 adev->adm_request_focus = (adm_request_focus_t)
9478 dlsym(adev->adm_lib, "adm_request_focus");
9479 adev->adm_abandon_focus = (adm_abandon_focus_t)
9480 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009481 adev->adm_set_config = (adm_set_config_t)
9482 dlsym(adev->adm_lib, "adm_set_config");
9483 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9484 dlsym(adev->adm_lib, "adm_request_focus_v2");
9485 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9486 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9487 adev->adm_on_routing_change = (adm_on_routing_change_t)
9488 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009489 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9490 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009491 }
9492 }
9493
Aalique Grahame22e49102018-12-18 14:23:57 -08009494 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009495 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009496 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009497 //initialize this to false for now,
9498 //this will be set to true through set param
9499 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009500
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009501 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009502 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009503
9504 if (k_enable_extended_precision)
9505 adev_verify_devices(adev);
9506
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009507 adev->dsp_bit_width_enforce_mode =
9508 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009509
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309510 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9511 &adev->streams_output_cfg_list,
9512 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009513
Kiran Kandi910e1862013-10-29 13:29:42 -07009514 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009515
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009516 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009517 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9518 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009519 trial = atoi(value);
9520 if (period_size_is_plausible_for_low_latency(trial)) {
9521 pcm_config_low_latency.period_size = trial;
9522 pcm_config_low_latency.start_threshold = trial / 4;
9523 pcm_config_low_latency.avail_min = trial / 4;
9524 configured_low_latency_capture_period_size = trial;
9525 }
9526 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009527 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9528 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009529 trial = atoi(value);
9530 if (period_size_is_plausible_for_low_latency(trial)) {
9531 configured_low_latency_capture_period_size = trial;
9532 }
9533 }
9534
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009535 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9536
Eric Laurent4b084132018-10-19 17:33:43 -07009537 adev->camera_orientation = CAMERA_DEFAULT;
9538
Aalique Grahame22e49102018-12-18 14:23:57 -08009539 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9540 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009541 af_period_multiplier = atoi(value);
9542 if (af_period_multiplier < 0)
9543 af_period_multiplier = 2;
9544 else if (af_period_multiplier > 4)
9545 af_period_multiplier = 4;
9546
9547 ALOGV("new period_multiplier = %d", af_period_multiplier);
9548 }
9549
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009550 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009551
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009552 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009553 pthread_mutex_unlock(&adev_init_lock);
9554
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009555 if (adev->adm_init)
9556 adev->adm_data = adev->adm_init();
9557
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309558 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309559 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009560 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309561
9562 audio_extn_snd_mon_init();
9563 pthread_mutex_lock(&adev->lock);
9564 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9565 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009566 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9567 /*
9568 * if the battery state callback happens before charging can be queried,
9569 * it will be guarded with the adev->lock held in the cb function and so
9570 * the callback value will reflect the latest state
9571 */
9572 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309573 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009574 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009575 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009576 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309577 /* Allocate memory for Device config params */
9578 adev->device_cfg_params = (struct audio_device_config_param*)
9579 calloc(platform_get_max_codec_backend(),
9580 sizeof(struct audio_device_config_param));
9581 if (adev->device_cfg_params == NULL)
9582 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309583
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309584 /*
9585 * Check if new PSPD matrix mixer control is supported. If not
9586 * supported, then set flag so that old mixer ctrl is sent while
9587 * sending pspd coefficients on older kernel version. Query mixer
9588 * control for default pcm id and channel value one.
9589 */
9590 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9591 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9592
9593 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9594 if (!ctl) {
9595 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9596 __func__, mixer_ctl_name);
9597 adev->use_old_pspd_mix_ctrl = true;
9598 }
9599
Eric Laurent994a6932013-07-17 11:51:42 -07009600 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009601 return 0;
9602}
9603
9604static struct hw_module_methods_t hal_module_methods = {
9605 .open = adev_open,
9606};
9607
9608struct audio_module HAL_MODULE_INFO_SYM = {
9609 .common = {
9610 .tag = HARDWARE_MODULE_TAG,
9611 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9612 .hal_api_version = HARDWARE_HAL_API_VERSION,
9613 .id = AUDIO_HARDWARE_MODULE_ID,
9614 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009615 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009616 .methods = &hal_module_methods,
9617 },
9618};