blob: 45b0a5dbbeeedada283ca7bd012e5012b96d85ec [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, 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
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070097#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070098
Aalique Grahame22e49102018-12-18 14:23:57 -080099#define RECORD_GAIN_MIN 0.0f
100#define RECORD_GAIN_MAX 1.0f
101#define RECORD_VOLUME_CTL_MAX 0x2000
102
103/* treat as unsigned Q1.13 */
104#define APP_TYPE_GAIN_DEFAULT 0x2000
105
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700106#define PROXY_OPEN_RETRY_COUNT 100
107#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800108
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800109#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
110 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
111 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
112#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
113 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800114
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700115#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700116#define DEFAULT_VOIP_BUF_DURATION_MS 20
117#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
118#define DEFAULT_VOIP_SAMP_RATE 48000
119
120#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
121
122struct pcm_config default_pcm_config_voip_copp = {
123 .channels = 1,
124 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
125 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
126 .period_count = 2,
127 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800128 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
129 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700130};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700131
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700132#define MIN_CHANNEL_COUNT 1
133#define DEFAULT_CHANNEL_COUNT 2
134#define MAX_HIFI_CHANNEL_COUNT 8
135
Aalique Grahame22e49102018-12-18 14:23:57 -0800136#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
137#define MAX_CHANNEL_COUNT 1
138#else
139#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
140#define XSTR(x) STR(x)
141#define STR(x) #x
142#endif
143
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700144static unsigned int configured_low_latency_capture_period_size =
145 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
146
Haynes Mathew George16081042017-05-31 17:16:49 -0700147#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
148#define MMAP_PERIOD_COUNT_MIN 32
149#define MMAP_PERIOD_COUNT_MAX 512
150#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
151
Aalique Grahame22e49102018-12-18 14:23:57 -0800152/* This constant enables extended precision handling.
153 * TODO The flag is off until more testing is done.
154 */
155static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700156extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800157
Eric Laurentb23d5282013-05-14 15:27:20 -0700158struct pcm_config pcm_config_deep_buffer = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
162 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165 .stop_threshold = INT_MAX,
166 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
167};
168
169struct pcm_config pcm_config_low_latency = {
170 .channels = 2,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
173 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176 .stop_threshold = INT_MAX,
177 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
178};
179
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800180struct pcm_config pcm_config_haptics_audio = {
181 .channels = 1,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
184 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187 .stop_threshold = INT_MAX,
188 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
189};
190
191struct pcm_config pcm_config_haptics = {
192 .channels = 1,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
195 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .stop_threshold = INT_MAX,
199 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
200};
201
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700202static int af_period_multiplier = 4;
203struct pcm_config pcm_config_rt = {
204 .channels = 2,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = ULL_PERIOD_SIZE, //1 ms
207 .period_count = 512, //=> buffer size is 512ms
208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = ULL_PERIOD_SIZE, //1 ms
214};
215
Eric Laurentb23d5282013-05-14 15:27:20 -0700216struct pcm_config pcm_config_hdmi_multi = {
217 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
218 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
219 .period_size = HDMI_MULTI_PERIOD_SIZE,
220 .period_count = HDMI_MULTI_PERIOD_COUNT,
221 .format = PCM_FORMAT_S16_LE,
222 .start_threshold = 0,
223 .stop_threshold = INT_MAX,
224 .avail_min = 0,
225};
226
Haynes Mathew George16081042017-05-31 17:16:49 -0700227struct pcm_config pcm_config_mmap_playback = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = MMAP_PERIOD_SIZE,
231 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = MMAP_PERIOD_SIZE*8,
234 .stop_threshold = INT32_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = MMAP_PERIOD_SIZE, //1 ms
238};
239
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700240struct pcm_config pcm_config_hifi = {
241 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
242 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
243 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
244 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
245 .format = PCM_FORMAT_S24_3LE,
246 .start_threshold = 0,
247 .stop_threshold = INT_MAX,
248 .avail_min = 0,
249};
250
Eric Laurentb23d5282013-05-14 15:27:20 -0700251struct pcm_config pcm_config_audio_capture = {
252 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
254 .format = PCM_FORMAT_S16_LE,
255};
256
Haynes Mathew George16081042017-05-31 17:16:49 -0700257struct pcm_config pcm_config_mmap_capture = {
258 .channels = 2,
259 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
260 .period_size = MMAP_PERIOD_SIZE,
261 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
262 .format = PCM_FORMAT_S16_LE,
263 .start_threshold = 0,
264 .stop_threshold = INT_MAX,
265 .silence_threshold = 0,
266 .silence_size = 0,
267 .avail_min = MMAP_PERIOD_SIZE, //1 ms
268};
269
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700270#define AFE_PROXY_CHANNEL_COUNT 2
271#define AFE_PROXY_SAMPLING_RATE 48000
272
273#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
274#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
275
276struct pcm_config pcm_config_afe_proxy_playback = {
277 .channels = AFE_PROXY_CHANNEL_COUNT,
278 .rate = AFE_PROXY_SAMPLING_RATE,
279 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
280 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
281 .format = PCM_FORMAT_S16_LE,
282 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283 .stop_threshold = INT_MAX,
284 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
285};
286
287#define AFE_PROXY_RECORD_PERIOD_SIZE 768
288#define AFE_PROXY_RECORD_PERIOD_COUNT 4
289
Aalique Grahame22e49102018-12-18 14:23:57 -0800290struct pcm_config pcm_config_audio_capture_rt = {
291 .channels = 2,
292 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
293 .period_size = ULL_PERIOD_SIZE,
294 .period_count = 512,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = 0,
297 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
298 .silence_threshold = 0,
299 .silence_size = 0,
300 .avail_min = ULL_PERIOD_SIZE, //1 ms
301};
302
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700303struct pcm_config pcm_config_afe_proxy_record = {
304 .channels = AFE_PROXY_CHANNEL_COUNT,
305 .rate = AFE_PROXY_SAMPLING_RATE,
306 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
307 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
308 .format = PCM_FORMAT_S16_LE,
309 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
310 .stop_threshold = INT_MAX,
311 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
312};
313
Ashish Jainf1eaa582016-05-23 20:54:24 +0530314#define AUDIO_MAX_PCM_FORMATS 7
315
316const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
317 [AUDIO_FORMAT_DEFAULT] = 0,
318 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
319 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
320 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
323 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
324};
325
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800326const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700327 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
328 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800329 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700330 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
331 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700333 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700342 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
343 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700344 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800345 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700346
Eric Laurentb23d5282013-05-14 15:27:20 -0700347 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700348 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530349 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
350 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
351 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530352 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
353 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700355 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700357 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800359 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800360 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400361 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
362 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700363
Derek Chenf7092792017-05-23 12:23:53 -0400364 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700365 [USECASE_VOICE2_CALL] = "voice2-call",
366 [USECASE_VOLTE_CALL] = "volte-call",
367 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800368 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800369 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
370 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800371 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700372 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
373 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800375 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
376 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
377 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
378
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700379 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
380 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700381 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
382 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700383
384 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
385 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530386 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530388 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530389 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
390 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700391
392 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
393 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530394 /* For Interactive Audio Streams */
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700403
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800404 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
405
Derek Chenf6318be2017-06-12 17:16:24 -0400406 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
407
408 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
409 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
410 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
411 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700412 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530413 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700414};
415
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700416static const audio_usecase_t offload_usecases[] = {
417 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700418 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427
Varun Balaraje49253e2017-07-06 19:48:56 +0530428static const audio_usecase_t interactive_usecases[] = {
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
437};
438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439#define STRING_TO_ENUM(string) { #string, string }
440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441struct string_to_enum {
442 const char *name;
443 uint32_t value;
444};
445
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700446static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466};
467
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700468static const struct string_to_enum formats_name_to_enum_table[] = {
469 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700472 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
473 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700475 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
477 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700478 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800479};
480
481//list of all supported sample rates by HDMI specification.
482static const int out_hdmi_sample_rates[] = {
483 32000, 44100, 48000, 88200, 96000, 176400, 192000,
484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800487 STRING_TO_ENUM(32000),
488 STRING_TO_ENUM(44100),
489 STRING_TO_ENUM(48000),
490 STRING_TO_ENUM(88200),
491 STRING_TO_ENUM(96000),
492 STRING_TO_ENUM(176400),
493 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800494 STRING_TO_ENUM(352800),
495 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700496};
497
Carter Hsu2e429db2019-05-14 18:50:52 +0800498struct in_effect_list {
499 struct listnode list;
500 effect_handle_t handle;
501};
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700504static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700505static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700506//cache last MBDRC cal step level
507static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700508
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530509static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
510static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700511static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800512static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530513static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530514
Derek Chen6f293672019-04-01 01:40:24 -0700515static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
516static void in_snd_mon_cb(void * stream, struct str_parms * parms);
517static void out_snd_mon_cb(void * stream, struct str_parms * parms);
518
Zhou Song331c8e52019-08-26 14:16:12 +0800519static int configure_btsco_sample_rate(snd_device_t snd_device);
520
Vatsal Buchac09ae062018-11-14 13:25:08 +0530521#ifdef AUDIO_FEATURE_ENABLED_GCOV
522extern void __gcov_flush();
523static void enable_gcov()
524{
525 __gcov_flush();
526}
527#else
528static void enable_gcov()
529{
530}
531#endif
532
justinweng20fb6d82019-02-21 18:49:00 -0700533static int in_set_microphone_direction(const struct audio_stream_in *stream,
534 audio_microphone_direction_t dir);
535static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
536
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700537static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
538 int flags __unused)
539{
540 int dir = 0;
541 switch (uc_id) {
542 case USECASE_AUDIO_RECORD_LOW_LATENCY:
543 dir = 1;
544 case USECASE_AUDIO_PLAYBACK_ULL:
545 break;
546 default:
547 return false;
548 }
549
550 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
551 PCM_PLAYBACK : PCM_CAPTURE);
552 if (adev->adm_is_noirq_avail)
553 return adev->adm_is_noirq_avail(adev->adm_data,
554 adev->snd_card, dev_id, dir);
555 return false;
556}
557
558static void register_out_stream(struct stream_out *out)
559{
560 struct audio_device *adev = out->dev;
561 if (is_offload_usecase(out->usecase) ||
562 !adev->adm_register_output_stream)
563 return;
564
565 // register stream first for backward compatibility
566 adev->adm_register_output_stream(adev->adm_data,
567 out->handle,
568 out->flags);
569
570 if (!adev->adm_set_config)
571 return;
572
573 if (out->realtime)
574 adev->adm_set_config(adev->adm_data,
575 out->handle,
576 out->pcm, &out->config);
577}
578
579static void register_in_stream(struct stream_in *in)
580{
581 struct audio_device *adev = in->dev;
582 if (!adev->adm_register_input_stream)
583 return;
584
585 adev->adm_register_input_stream(adev->adm_data,
586 in->capture_handle,
587 in->flags);
588
589 if (!adev->adm_set_config)
590 return;
591
592 if (in->realtime)
593 adev->adm_set_config(adev->adm_data,
594 in->capture_handle,
595 in->pcm,
596 &in->config);
597}
598
599static void request_out_focus(struct stream_out *out, long ns)
600{
601 struct audio_device *adev = out->dev;
602
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700603 if (adev->adm_request_focus_v2)
604 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
605 else if (adev->adm_request_focus)
606 adev->adm_request_focus(adev->adm_data, out->handle);
607}
608
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700609static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700610{
611 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700612 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614 if (adev->adm_request_focus_v2_1)
615 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
616 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
618 else if (adev->adm_request_focus)
619 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620
621 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622}
623
624static void release_out_focus(struct stream_out *out)
625{
626 struct audio_device *adev = out->dev;
627
628 if (adev->adm_abandon_focus)
629 adev->adm_abandon_focus(adev->adm_data, out->handle);
630}
631
632static void release_in_focus(struct stream_in *in)
633{
634 struct audio_device *adev = in->dev;
635 if (adev->adm_abandon_focus)
636 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
637}
638
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530639static int parse_snd_card_status(struct str_parms *parms, int *card,
640 card_status_t *status)
641{
642 char value[32]={0};
643 char state[32]={0};
644
645 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
646 if (ret < 0)
647 return -1;
648
649 // sscanf should be okay as value is of max length 32.
650 // same as sizeof state.
651 if (sscanf(value, "%d,%s", card, state) < 2)
652 return -1;
653
654 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
655 CARD_STATUS_OFFLINE;
656 return 0;
657}
658
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700659static inline void adjust_frames_for_device_delay(struct stream_out *out,
660 uint32_t *dsp_frames) {
661 // Adjustment accounts for A2dp encoder latency with offload usecases
662 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800663 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700664 unsigned long offset =
665 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
666 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
667 }
668}
669
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700670static inline bool free_entry(void *key __unused,
671 void *value, void *context __unused)
672{
673 free(value);
674 return true;
675}
676
677static inline void free_map(Hashmap *map)
678{
679 if (map) {
680 hashmapForEach(map, free_entry, (void *) NULL);
681 hashmapFree(map);
682 }
683}
684
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800685static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700686 audio_patch_handle_t patch_handle)
687{
688 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
689 return;
690
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700691 struct audio_patch_info *p_info =
692 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
693 if (p_info) {
694 ALOGV("%s: Remove patch %d", __func__, patch_handle);
695 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
696 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 free(p_info);
698 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699}
700
701static inline int io_streams_map_insert(struct audio_device *adev,
702 struct audio_stream *stream,
703 audio_io_handle_t handle,
704 audio_patch_handle_t patch_handle)
705{
706 struct audio_stream_info *s_info =
707 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
708
709 if (s_info == NULL) {
710 ALOGE("%s: Could not allocate stream info", __func__);
711 return -ENOMEM;
712 }
713 s_info->stream = stream;
714 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715
716 pthread_mutex_lock(&adev->lock);
717 struct audio_stream_info *stream_info =
718 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719 if (stream_info != NULL)
720 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800721 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700722 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
723 return 0;
724}
725
726static inline void io_streams_map_remove(struct audio_device *adev,
727 audio_io_handle_t handle)
728{
729 pthread_mutex_lock(&adev->lock);
730 struct audio_stream_info *s_info =
731 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700732 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800733 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800735 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737done:
738 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700739 return;
740}
741
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 audio_patch_handle_t handle)
744{
745 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 p_info = (struct audio_patch_info *)
747 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return p_info;
749}
750
vivek mehtaa76401a2015-04-24 14:12:15 -0700751__attribute__ ((visibility ("default")))
752bool audio_hw_send_gain_dep_calibration(int level) {
753 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700754 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700755
756 pthread_mutex_lock(&adev_init_lock);
757
758 if (adev != NULL && adev->platform != NULL) {
759 pthread_mutex_lock(&adev->lock);
760 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700761
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530762 // cache level info for any of the use case which
763 // was not started.
764 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
vivek mehtaa76401a2015-04-24 14:12:15 -0700766 pthread_mutex_unlock(&adev->lock);
767 } else {
768 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
769 }
770
771 pthread_mutex_unlock(&adev_init_lock);
772
773 return ret_val;
774}
775
Ashish Jain5106d362016-05-11 19:23:33 +0530776static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
777{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800778 bool gapless_enabled = false;
779 const char *mixer_ctl_name = "Compress Gapless Playback";
780 struct mixer_ctl *ctl;
781
782 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700783 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530784
785 /*Disable gapless if its AV playback*/
786 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787
788 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
789 if (!ctl) {
790 ALOGE("%s: Could not get ctl for mixer cmd - %s",
791 __func__, mixer_ctl_name);
792 return -EINVAL;
793 }
794
795 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
796 ALOGE("%s: Could not set gapless mode %d",
797 __func__, gapless_enabled);
798 return -EINVAL;
799 }
800 return 0;
801}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700802
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700803__attribute__ ((visibility ("default")))
804int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
805 int table_size) {
806 int ret_val = 0;
807 ALOGV("%s: enter ... ", __func__);
808
809 pthread_mutex_lock(&adev_init_lock);
810 if (adev == NULL) {
811 ALOGW("%s: adev is NULL .... ", __func__);
812 goto done;
813 }
814
815 pthread_mutex_lock(&adev->lock);
816 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
817 pthread_mutex_unlock(&adev->lock);
818done:
819 pthread_mutex_unlock(&adev_init_lock);
820 ALOGV("%s: exit ... ", __func__);
821 return ret_val;
822}
823
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800824bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800825{
826 bool ret = false;
827 ALOGV("%s: enter ...", __func__);
828
829 pthread_mutex_lock(&adev_init_lock);
830
831 if (adev != NULL && adev->platform != NULL) {
832 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800834 pthread_mutex_unlock(&adev->lock);
835 }
836
837 pthread_mutex_unlock(&adev_init_lock);
838
839 ALOGV("%s: exit with ret %d", __func__, ret);
840 return ret;
841}
Aalique Grahame22e49102018-12-18 14:23:57 -0800842
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700843static bool is_supported_format(audio_format_t format)
844{
Eric Laurent86e17132013-09-12 17:49:30 -0700845 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530846 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530847 format == AUDIO_FORMAT_AAC_LC ||
848 format == AUDIO_FORMAT_AAC_HE_V1 ||
849 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530850 format == AUDIO_FORMAT_AAC_ADTS_LC ||
851 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
852 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530853 format == AUDIO_FORMAT_AAC_LATM_LC ||
854 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
855 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530856 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
857 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530858 format == AUDIO_FORMAT_PCM_FLOAT ||
859 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700860 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530861 format == AUDIO_FORMAT_AC3 ||
862 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700863 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530864 format == AUDIO_FORMAT_DTS ||
865 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800866 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530867 format == AUDIO_FORMAT_ALAC ||
868 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530869 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530870 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800871 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530872 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700873 format == AUDIO_FORMAT_APTX ||
874 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800875 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700876
877 return false;
878}
879
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700880static inline bool is_mmap_usecase(audio_usecase_t uc_id)
881{
882 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
883 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
884}
885
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700886static inline bool is_valid_volume(float left, float right)
887{
888 return ((left >= 0.0f && right >= 0.0f) ? true : false);
889}
890
Avinash Vaish71a8b972014-07-24 15:36:33 +0530891static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
892 struct audio_usecase *uc_info)
893{
894 struct listnode *node;
895 struct audio_usecase *usecase;
896
897 if (uc_info == NULL)
898 return -EINVAL;
899
900 /* Re-route all voice usecases on the shared backend other than the
901 specified usecase to new snd devices */
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800904 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530905 enable_audio_route(adev, usecase);
906 }
907 return 0;
908}
909
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530910static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530911{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530912 ALOGV("%s", __func__);
913 audio_route_apply_and_update_path(adev->audio_route,
914 "asrc-mode");
915 adev->asrc_mode_enabled = true;
916}
917
918static void disable_asrc_mode(struct audio_device *adev)
919{
920 ALOGV("%s", __func__);
921 audio_route_reset_and_update_path(adev->audio_route,
922 "asrc-mode");
923 adev->asrc_mode_enabled = false;
924}
925
926/*
927 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
928 * 44.1 or Native DSD backends are enabled for any of current use case.
929 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
930 * - Disable current mix path use case(Headphone backend) and re-enable it with
931 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
932 * e.g. Naitve DSD or Headphone 44.1 -> + 48
933 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530934static void check_and_set_asrc_mode(struct audio_device *adev,
935 struct audio_usecase *uc_info,
936 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530937{
938 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939 int i, num_new_devices = 0;
940 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
941 /*
942 *Split snd device for new combo use case
943 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
944 */
945 if (platform_split_snd_device(adev->platform,
946 snd_device,
947 &num_new_devices,
948 split_new_snd_devices) == 0) {
949 for (i = 0; i < num_new_devices; i++)
950 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
951 } else {
952 int new_backend_idx = platform_get_backend_index(snd_device);
953 if (((new_backend_idx == HEADPHONE_BACKEND) ||
954 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
955 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
956 !adev->asrc_mode_enabled) {
957 struct listnode *node = NULL;
958 struct audio_usecase *uc = NULL;
959 struct stream_out *curr_out = NULL;
960 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
961 int i, num_devices, ret = 0;
962 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530963
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530964 list_for_each(node, &adev->usecase_list) {
965 uc = node_to_item(node, struct audio_usecase, list);
966 curr_out = (struct stream_out*) uc->stream.out;
967 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
968 /*
969 *Split snd device for existing combo use case
970 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
971 */
972 ret = platform_split_snd_device(adev->platform,
973 uc->out_snd_device,
974 &num_devices,
975 split_snd_devices);
976 if (ret < 0 || num_devices == 0) {
977 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
978 split_snd_devices[0] = uc->out_snd_device;
979 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800980 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530981 for (i = 0; i < num_devices; i++) {
982 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
983 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
984 if((new_backend_idx == HEADPHONE_BACKEND) &&
985 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
986 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
987 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
988 __func__);
989 enable_asrc_mode(adev);
990 break;
991 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
992 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
993 (usecase_backend_idx == HEADPHONE_BACKEND)) {
994 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
995 __func__);
996 disable_audio_route(adev, uc);
997 disable_snd_device(adev, uc->out_snd_device);
998 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
999 if (new_backend_idx == DSD_NATIVE_BACKEND)
1000 audio_route_apply_and_update_path(adev->audio_route,
1001 "hph-true-highquality-mode");
1002 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1003 (curr_out->bit_width >= 24))
1004 audio_route_apply_and_update_path(adev->audio_route,
1005 "hph-highquality-mode");
1006 enable_asrc_mode(adev);
1007 enable_snd_device(adev, uc->out_snd_device);
1008 enable_audio_route(adev, uc);
1009 break;
1010 }
1011 }
1012 // reset split devices count
1013 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001014 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301015 if (adev->asrc_mode_enabled)
1016 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301017 }
1018 }
1019 }
1020}
1021
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001022static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1023 struct audio_effect_config effect_config,
1024 unsigned int param_value)
1025{
1026 char mixer_ctl_name[] = "Audio Effect";
1027 struct mixer_ctl *ctl;
1028 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001029 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001030
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001031 if (in == NULL) {
1032 ALOGE("%s: active input stream is NULL", __func__);
1033 return -EINVAL;
1034 }
1035
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001036 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1037 if (!ctl) {
1038 ALOGE("%s: Could not get mixer ctl - %s",
1039 __func__, mixer_ctl_name);
1040 return -EINVAL;
1041 }
1042
1043 set_values[0] = 1; //0:Rx 1:Tx
1044 set_values[1] = in->app_type_cfg.app_type;
1045 set_values[2] = (long)effect_config.module_id;
1046 set_values[3] = (long)effect_config.instance_id;
1047 set_values[4] = (long)effect_config.param_id;
1048 set_values[5] = param_value;
1049
1050 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1051
1052 return 0;
1053
1054}
1055
1056static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1057 int effect_type, unsigned int *param_value)
1058{
1059 int ret = 0;
1060 struct audio_effect_config other_effect_config;
1061 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001062 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001063
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001064 if (in == NULL) {
1065 ALOGE("%s: active input stream is NULL", __func__);
1066 return -EINVAL;
1067 }
1068
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069 usecase = get_usecase_from_list(adev, in->usecase);
1070 if (!usecase)
1071 return -EINVAL;
1072
1073 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1074 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1075 if (ret < 0) {
1076 ALOGE("%s Failed to get effect params %d", __func__, ret);
1077 return ret;
1078 }
1079
1080 if (module_id == other_effect_config.module_id) {
1081 //Same module id for AEC/NS. Values need to be combined
1082 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1083 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1084 *param_value |= other_effect_config.param_value;
1085 }
1086 }
1087
1088 return ret;
1089}
1090
1091static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301092{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 struct audio_effect_config effect_config;
1094 struct audio_usecase *usecase = NULL;
1095 int ret = 0;
1096 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001097 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001099 if(!voice_extn_is_dynamic_ecns_enabled())
1100 return ENOSYS;
1101
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 if (!in) {
1103 ALOGE("%s: Invalid input stream", __func__);
1104 return -EINVAL;
1105 }
1106
1107 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1108
1109 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001110 if (usecase == NULL) {
1111 ALOGE("%s: Could not find the usecase (%d) in the list",
1112 __func__, in->usecase);
1113 return -EINVAL;
1114 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001115
1116 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1117 if (ret < 0) {
1118 ALOGE("%s Failed to get module id %d", __func__, ret);
1119 return ret;
1120 }
1121 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1122 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1123
1124 if(enable)
1125 param_value = effect_config.param_value;
1126
1127 /*Special handling for AEC & NS effects Param values need to be
1128 updated if module ids are same*/
1129
1130 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1131 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1132 if (ret < 0)
1133 return ret;
1134 }
1135
1136 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1137
1138 return ret;
1139}
1140
1141static void check_and_enable_effect(struct audio_device *adev)
1142{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001143 if(!voice_extn_is_dynamic_ecns_enabled())
1144 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001145
Eric Laurent637e2d42018-11-15 12:24:31 -08001146 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Eric Laurent637e2d42018-11-15 12:24:31 -08001148 if (in != NULL && !in->standby) {
1149 if (in->enable_aec)
1150 enable_disable_effect(adev, EFFECT_AEC, true);
1151
1152 if (in->enable_ns &&
1153 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1154 enable_disable_effect(adev, EFFECT_NS, true);
1155 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156 }
1157}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001159int pcm_ioctl(struct pcm *pcm, int request, ...)
1160{
1161 va_list ap;
1162 void * arg;
1163 int pcm_fd = *(int*)pcm;
1164
1165 va_start(ap, request);
1166 arg = va_arg(ap, void *);
1167 va_end(ap);
1168
1169 return ioctl(pcm_fd, request, arg);
1170}
1171
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001172int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001173 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001176 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301177 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301178 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001179 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301180 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001181
1182 if (usecase == NULL)
1183 return -EINVAL;
1184
1185 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1186
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 if (usecase->type == PCM_CAPTURE) {
1188 struct stream_in *in = usecase->stream.in;
1189 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001191
1192 if (in) {
1193 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001194 list_init(&out_devices);
1195 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 struct listnode *node;
1197 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1198 USECASE_AUDIO_PLAYBACK_VOIP);
1199 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001200 assign_devices(&out_devices,
1201 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001202 } else if (adev->primary_output &&
1203 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001204 assign_devices(&out_devices,
1205 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001206 } else {
1207 list_for_each(node, &adev->usecase_list) {
1208 uinfo = node_to_item(node, struct audio_usecase, list);
1209 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001210 assign_devices(&out_devices,
1211 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 break;
1213 }
1214 }
1215 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216
1217 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 in->ec_opened = true;
1219 }
1220 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001221 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1222 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1223 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 snd_device = usecase->in_snd_device;
1225 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001228
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001229#ifdef DS1_DOLBY_DAP_ENABLED
1230 audio_extn_dolby_set_dmid(adev);
1231 audio_extn_dolby_set_endpoint(adev);
1232#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001233 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001234 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301235 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001236 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001237 if (audio_extn_is_maxx_audio_enabled())
1238 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301239 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301240 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1241 out = usecase->stream.out;
1242 if (out && out->compr)
1243 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1244 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301245
1246 if (usecase->type == PCM_CAPTURE) {
1247 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001248 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301249 ALOGD("%s: set custom mtmx params v1", __func__);
1250 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1251 }
1252 } else {
1253 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1254 }
Manish Dewangan58229382017-02-02 15:48:41 +05301255
Andy Hung756ecc12018-10-19 17:47:12 -07001256 // we shouldn't truncate mixer_path
1257 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1258 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1259 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001260 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001261 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301262 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1263 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1264 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1265 if (parms) {
1266 audio_extn_fm_set_parameters(adev, parms);
1267 str_parms_destroy(parms);
1268 }
1269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 ALOGV("%s: exit", __func__);
1271 return 0;
1272}
1273
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001274int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001275 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001278 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301279 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001280
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301281 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001282 return -EINVAL;
1283
1284 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301285 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 snd_device = usecase->in_snd_device;
1287 else
1288 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001289 // we shouldn't truncate mixer_path
1290 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1291 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1292 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001293 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001294 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001295 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001296 if (usecase->type == PCM_CAPTURE) {
1297 struct stream_in *in = usecase->stream.in;
1298 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001299 struct listnode out_devices;
1300 list_init(&out_devices);
1301 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001302 in->ec_opened = false;
1303 }
1304 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001305 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301306 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301307
1308 if (usecase->type == PCM_CAPTURE) {
1309 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001310 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301311 ALOGD("%s: reset custom mtmx params v1", __func__);
1312 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1313 }
1314 } else {
1315 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1316 }
1317
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001318 if ((usecase->type == PCM_PLAYBACK) &&
1319 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301320 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322 ALOGV("%s: exit", __func__);
1323 return 0;
1324}
1325
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001326int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001327 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001328{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301329 int i, num_devices = 0;
1330 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001331 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1332
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001333 if (snd_device < SND_DEVICE_MIN ||
1334 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001335 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001336 return -EINVAL;
1337 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001339 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001340 ALOGE("%s: Invalid sound device returned", __func__);
1341 return -EINVAL;
1342 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001343
1344 adev->snd_dev_ref_cnt[snd_device]++;
1345
1346 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1347 (platform_split_snd_device(adev->platform,
1348 snd_device,
1349 &num_devices,
1350 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001351 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001352 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353 return 0;
1354 }
1355
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001356 if (audio_extn_spkr_prot_is_enabled())
1357 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001358
Aalique Grahame22e49102018-12-18 14:23:57 -08001359 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1360
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001361 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1362 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001363 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1364 goto err;
1365 }
1366 audio_extn_dev_arbi_acquire(snd_device);
1367 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001368 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001369 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001370 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001371 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001372 } else if (platform_split_snd_device(adev->platform,
1373 snd_device,
1374 &num_devices,
1375 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301376 for (i = 0; i < num_devices; i++) {
1377 enable_snd_device(adev, new_snd_devices[i]);
1378 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001379 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001380 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001381 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301382
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301383
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1385 (audio_extn_a2dp_start_playback() < 0)) {
1386 ALOGE(" fail to configure A2dp Source control path ");
1387 goto err;
1388 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001389
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001390 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1391 (audio_extn_a2dp_start_capture() < 0)) {
1392 ALOGE(" fail to configure A2dp Sink control path ");
1393 goto err;
1394 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301395
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001396 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1397 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1398 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1399 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1400 ALOGE(" fail to configure sco control path ");
1401 goto err;
1402 }
Zhou Song12c29502019-03-16 10:37:18 +08001403 }
1404
Zhou Song331c8e52019-08-26 14:16:12 +08001405 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001406 /* due to the possibility of calibration overwrite between listen
1407 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001408 audio_extn_sound_trigger_update_device_status(snd_device,
1409 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301410 audio_extn_listen_update_device_status(snd_device,
1411 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001412 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001417 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001418 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001419 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001420 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421
1422 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1423 !adev->native_playback_enabled &&
1424 audio_is_true_native_stream_active(adev)) {
1425 ALOGD("%s: %d: napb: enabling native mode in hardware",
1426 __func__, __LINE__);
1427 audio_route_apply_and_update_path(adev->audio_route,
1428 "true-native-mode");
1429 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301430 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301431 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1432 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001433 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001434 ALOGD("%s: init ec ref loopback", __func__);
1435 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001439err:
1440 adev->snd_dev_ref_cnt[snd_device]--;
1441 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442}
1443
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001444int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001445 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301447 int i, num_devices = 0;
1448 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001449 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1450
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001451 if (snd_device < SND_DEVICE_MIN ||
1452 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001453 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 return -EINVAL;
1455 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001456
1457 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1458 ALOGE("%s: Invalid sound device returned", __func__);
1459 return -EINVAL;
1460 }
1461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1463 ALOGE("%s: device ref cnt is already 0", __func__);
1464 return -EINVAL;
1465 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001468
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001469
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001471 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301472
Aalique Grahame22e49102018-12-18 14:23:57 -08001473 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1474
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001475 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1476 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001477 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001478
1479 // when speaker device is disabled, reset swap.
1480 // will be renabled on usecase start
1481 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001482 } else if (platform_split_snd_device(adev->platform,
1483 snd_device,
1484 &num_devices,
1485 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 for (i = 0; i < num_devices; i++) {
1487 disable_snd_device(adev, new_snd_devices[i]);
1488 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001489 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001490 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001491 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001492 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001493
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301495 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001496 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001497 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001498 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301500 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301502 adev->native_playback_enabled) {
1503 ALOGD("%s: %d: napb: disabling native mode in hardware",
1504 __func__, __LINE__);
1505 audio_route_reset_and_update_path(adev->audio_route,
1506 "true-native-mode");
1507 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001508 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301509 adev->asrc_mode_enabled) {
1510 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301511 disable_asrc_mode(adev);
1512 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301514 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001515 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001516 ALOGD("%s: deinit ec ref loopback", __func__);
1517 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1518 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001519
1520 audio_extn_utils_release_snd_device(snd_device);
1521 } else {
1522 if (platform_split_snd_device(adev->platform,
1523 snd_device,
1524 &num_devices,
1525 new_snd_devices) == 0) {
1526 for (i = 0; i < num_devices; i++) {
1527 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1528 }
1529 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 return 0;
1533}
1534
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001535/*
1536 legend:
1537 uc - existing usecase
1538 new_uc - new usecase
1539 d1, d11, d2 - SND_DEVICE enums
1540 a1, a2 - corresponding ANDROID device enums
1541 B1, B2 - backend strings
1542
1543case 1
1544 uc->dev d1 (a1) B1
1545 new_uc->dev d1 (a1), d2 (a2) B1, B2
1546
1547 resolution: disable and enable uc->dev on d1
1548
1549case 2
1550 uc->dev d1 (a1) B1
1551 new_uc->dev d11 (a1) B1
1552
1553 resolution: need to switch uc since d1 and d11 are related
1554 (e.g. speaker and voice-speaker)
1555 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1556
1557case 3
1558 uc->dev d1 (a1) B1
1559 new_uc->dev d2 (a2) B2
1560
1561 resolution: no need to switch uc
1562
1563case 4
1564 uc->dev d1 (a1) B1
1565 new_uc->dev d2 (a2) B1
1566
1567 resolution: disable enable uc-dev on d2 since backends match
1568 we cannot enable two streams on two different devices if they
1569 share the same backend. e.g. if offload is on speaker device using
1570 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1571 using the same backend, offload must also be switched to voice-handset.
1572
1573case 5
1574 uc->dev d1 (a1) B1
1575 new_uc->dev d1 (a1), d2 (a2) B1
1576
1577 resolution: disable enable uc-dev on d2 since backends match
1578 we cannot enable two streams on two different devices if they
1579 share the same backend.
1580
1581case 6
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d2 (a1) B2
1584
1585 resolution: no need to switch
1586
1587case 7
1588 uc->dev d1 (a1), d2 (a2) B1, B2
1589 new_uc->dev d1 (a1) B1
1590
1591 resolution: no need to switch
1592
Zhou Song4ba65882018-07-09 14:48:07 +08001593case 8
1594 uc->dev d1 (a1) B1
1595 new_uc->dev d11 (a1), d2 (a2) B1, B2
1596 resolution: compared to case 1, for this case, d1 and d11 are related
1597 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001598*/
1599static snd_device_t derive_playback_snd_device(void * platform,
1600 struct audio_usecase *uc,
1601 struct audio_usecase *new_uc,
1602 snd_device_t new_snd_device)
1603{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001604 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001605
1606 snd_device_t d1 = uc->out_snd_device;
1607 snd_device_t d2 = new_snd_device;
1608
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 list_init(&a1);
1610 list_init(&a2);
1611
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301612 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301613 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1615 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301616 break;
1617 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001618 assign_devices(&a1, &uc->stream.out->device_list);
1619 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301620 break;
1621 }
1622
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001623 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001624 if (!compare_devices(&a1, &a2) &&
1625 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001626 snd_device_t d3[2];
1627 int num_devices = 0;
1628 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001630 &num_devices,
1631 d3);
1632 if (ret < 0) {
1633 if (ret != -ENOSYS) {
1634 ALOGW("%s failed to split snd_device %d",
1635 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001636 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001637 }
1638 goto end;
1639 }
1640
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001641 if (platform_check_backends_match(d3[0], d3[1])) {
1642 return d2; // case 5
1643 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001644 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301645 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001646 // check if d1 is related to any of d3's
1647 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001648 return d1; // case 1
1649 else
1650 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001651 }
1652 } else {
1653 if (platform_check_backends_match(d1, d2)) {
1654 return d2; // case 2, 4
1655 } else {
1656 return d1; // case 6, 3
1657 }
1658 }
1659
1660end:
1661 return d2; // return whatever was calculated before.
1662}
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301665 struct audio_usecase *uc_info,
1666 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667{
1668 struct listnode *node;
1669 struct audio_usecase *usecase;
1670 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301671 snd_device_t uc_derive_snd_device;
1672 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001673 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1674 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001675 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301676 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 /*
1678 * This function is to make sure that all the usecases that are active on
1679 * the hardware codec backend are always routed to any one device that is
1680 * handled by the hardware codec.
1681 * For example, if low-latency and deep-buffer usecases are currently active
1682 * on speaker and out_set_parameters(headset) is received on low-latency
1683 * output, then we have to make sure deep-buffer is also switched to headset,
1684 * because of the limitation that both the devices cannot be enabled
1685 * at the same time as they share the same backend.
1686 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001687 /*
1688 * This call is to check if we need to force routing for a particular stream
1689 * If there is a backend configuration change for the device when a
1690 * new stream starts, then ADM needs to be closed and re-opened with the new
1691 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001692 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001693 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001694 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1695 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301696 /* For a2dp device reconfigure all active sessions
1697 * with new AFE encoder format based on a2dp state
1698 */
1699 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1700 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1701 audio_extn_a2dp_is_force_device_switch()) {
1702 force_routing = true;
1703 force_restart_session = true;
1704 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301705 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1706
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001708 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001709 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1711 switch_device[i] = false;
1712
1713 list_for_each(node, &adev->usecase_list) {
1714 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001715
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301716 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1717 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301718 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301719 platform_get_snd_device_name(usecase->out_snd_device),
1720 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301721 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1722 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301723 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1724 usecase, uc_info, snd_device);
1725 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001726 (is_codec_backend_out_device_type(&usecase->device_list) ||
1727 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1728 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1730 is_a2dp_out_device_type(&usecase->device_list) ||
1731 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301732 ((force_restart_session) ||
1733 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301734 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1735 __func__, use_case_table[usecase->id],
1736 platform_get_snd_device_name(usecase->out_snd_device));
1737 disable_audio_route(adev, usecase);
1738 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301739 /* Enable existing usecase on derived playback device */
1740 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301741 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001743 }
1744 }
1745
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301746 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1747 num_uc_to_switch);
1748
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001750 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301752 /* Make sure the previous devices to be disabled first and then enable the
1753 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 list_for_each(node, &adev->usecase_list) {
1755 usecase = node_to_item(node, struct audio_usecase, list);
1756 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001757 /* Check if output sound device to be switched can be split and if any
1758 of the split devices match with derived sound device */
1759 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1760 &num_devices, split_snd_devices) == 0) {
1761 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1762 for (i = 0; i < num_devices; i++) {
1763 /* Disable devices that do not match with derived sound device */
1764 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1765 disable_snd_device(adev, split_snd_devices[i]);
1766 }
1767 } else {
1768 disable_snd_device(adev, usecase->out_snd_device);
1769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 }
1771 }
1772
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
1775 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001776 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1777 &num_devices, split_snd_devices) == 0) {
1778 /* Enable derived sound device only if it does not match with
1779 one of the split sound devices. This is because the matching
1780 sound device was not disabled */
1781 bool should_enable = true;
1782 for (i = 0; i < num_devices; i++) {
1783 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1784 should_enable = false;
1785 break;
1786 }
1787 }
1788 if (should_enable)
1789 enable_snd_device(adev, derive_snd_device[usecase->id]);
1790 } else {
1791 enable_snd_device(adev, derive_snd_device[usecase->id]);
1792 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001793 }
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796 /* Re-route all the usecases on the shared backend other than the
1797 specified usecase to new snd devices */
1798 list_for_each(node, &adev->usecase_list) {
1799 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301800 /* Update the out_snd_device only before enabling the audio route */
1801 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301802 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301803 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301804 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 use_case_table[usecase->id],
1806 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001807 /* Update voc calibration before enabling VoIP route */
1808 if (usecase->type == VOIP_CALL)
1809 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001810 usecase->out_snd_device,
1811 platform_get_input_snd_device(
1812 adev->platform, NULL,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001813 &uc_info->device_list));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301814 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301815 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001816 out_set_voip_volume(&usecase->stream.out->stream,
1817 usecase->stream.out->volume_l,
1818 usecase->stream.out->volume_r);
1819 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301820 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821 }
1822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 }
1824}
1825
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301826static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001827 struct audio_usecase *uc_info,
1828 snd_device_t snd_device)
1829{
1830 struct listnode *node;
1831 struct audio_usecase *usecase;
1832 bool switch_device[AUDIO_USECASE_MAX];
1833 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001834 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001835 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001836
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301837 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1838 snd_device);
1839 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301840
1841 /*
1842 * Make sure out devices is checked against out codec backend device and
1843 * also in devices against in codec backend. Checking out device against in
1844 * codec backend or vice versa causes issues.
1845 */
1846 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001847 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001848 /*
1849 * This function is to make sure that all the active capture usecases
1850 * are always routed to the same input sound device.
1851 * For example, if audio-record and voice-call usecases are currently
1852 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1853 * is received for voice call then we have to make sure that audio-record
1854 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1855 * because of the limitation that two devices cannot be enabled
1856 * at the same time if they share the same backend.
1857 */
1858 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1859 switch_device[i] = false;
1860
1861 list_for_each(node, &adev->usecase_list) {
1862 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301863 /*
1864 * TODO: Enhance below condition to handle BT sco/USB multi recording
1865 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001866 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001867 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301868 (usecase->in_snd_device != snd_device || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001869 ((backend_check_cond &&
1870 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001871 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001872 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001873 is_single_device_type_equal(&usecase->device_list,
1874 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001875 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001876 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001877 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001878 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1879 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001880 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001881 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001882 switch_device[usecase->id] = true;
1883 num_uc_to_switch++;
1884 }
1885 }
1886
1887 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001888 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001889
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301890 /* Make sure the previous devices to be disabled first and then enable the
1891 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001892 list_for_each(node, &adev->usecase_list) {
1893 usecase = node_to_item(node, struct audio_usecase, list);
1894 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001895 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001896 }
1897 }
1898
1899 list_for_each(node, &adev->usecase_list) {
1900 usecase = node_to_item(node, struct audio_usecase, list);
1901 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001902 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001903 }
1904 }
1905
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001906 /* Re-route all the usecases on the shared backend other than the
1907 specified usecase to new snd devices */
1908 list_for_each(node, &adev->usecase_list) {
1909 usecase = node_to_item(node, struct audio_usecase, list);
1910 /* Update the in_snd_device only before enabling the audio route */
1911 if (switch_device[usecase->id] ) {
1912 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001913 if (usecase->type != VOICE_CALL) {
1914 /* Update voc calibration before enabling VoIP route */
1915 if (usecase->type == VOIP_CALL)
1916 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001917 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001918 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301919 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001920 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001921 }
1922 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 }
1924}
1925
Mingming Yin3a941d42016-02-17 18:08:05 -08001926static void reset_hdmi_sink_caps(struct stream_out *out) {
1927 int i = 0;
1928
1929 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1930 out->supported_channel_masks[i] = 0;
1931 }
1932 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1933 out->supported_formats[i] = 0;
1934 }
1935 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1936 out->supported_sample_rates[i] = 0;
1937 }
1938}
1939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001941static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942{
Mingming Yin3a941d42016-02-17 18:08:05 -08001943 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001944 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1945 out->extconn.cs.controller,
1946 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947
Mingming Yin3a941d42016-02-17 18:08:05 -08001948 reset_hdmi_sink_caps(out);
1949
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001950 /* Cache ext disp type */
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001951 if (platform_get_ext_disp_type_v2(adev->platform,
1952 out->extconn.cs.controller,
1953 out->extconn.cs.stream <= 0)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001954 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001955 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001956 }
1957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001960 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001961 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001962 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1963 case 6:
1964 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1965 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1966 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1967 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1968 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1969 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 break;
1971 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001972 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001973 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 break;
1975 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001976
1977 // check channel format caps
1978 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001979 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1980 out->extconn.cs.controller,
1981 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001982 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1983 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1984 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1985 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1986 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1987 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1988 }
1989
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001990 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
1991 out->extconn.cs.controller,
1992 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07001993 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1994 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1995 }
1996
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001997 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
1998 out->extconn.cs.controller,
1999 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002000 ALOGV(":%s HDMI supports DTS format", __func__);
2001 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2002 }
2003
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002004 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2005 out->extconn.cs.controller,
2006 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002007 ALOGV(":%s HDMI supports DTS HD format", __func__);
2008 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2009 }
2010
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002011 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2012 out->extconn.cs.controller,
2013 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002014 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2015 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2016 }
2017
Mingming Yin3a941d42016-02-17 18:08:05 -08002018
2019 // check sample rate caps
2020 i = 0;
2021 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002022 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2023 out->extconn.cs.controller,
2024 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002025 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2026 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2027 }
2028 }
2029
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002030 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031}
2032
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002033static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2034 uint32_t *supported_sample_rates __unused,
2035 uint32_t max_rates __unused)
2036{
2037 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2038 supported_sample_rates,
2039 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302040 ssize_t i = 0;
2041
2042 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002043 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2044 supported_sample_rates[i]);
2045 }
2046 return count;
2047}
2048
2049static inline int read_usb_sup_channel_masks(bool is_playback,
2050 audio_channel_mask_t *supported_channel_masks,
2051 uint32_t max_masks)
2052{
2053 int channels = audio_extn_usb_get_max_channels(is_playback);
2054 int channel_count;
2055 uint32_t num_masks = 0;
2056 if (channels > MAX_HIFI_CHANNEL_COUNT)
2057 channels = MAX_HIFI_CHANNEL_COUNT;
2058
2059 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002060 // start from 2 channels as framework currently doesn't support mono.
2061 if (channels >= FCC_2) {
2062 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2063 }
2064 for (channel_count = FCC_2;
2065 channel_count <= channels && num_masks < max_masks;
2066 ++channel_count) {
2067 supported_channel_masks[num_masks++] =
2068 audio_channel_mask_for_index_assignment_from_count(channel_count);
2069 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002070 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002071 // For capture we report all supported channel masks from 1 channel up.
2072 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002073 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2074 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002075 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2076 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2077 if (channel_count <= FCC_2) {
2078 mask = audio_channel_in_mask_from_count(channel_count);
2079 supported_channel_masks[num_masks++] = mask;
2080 }
2081 const audio_channel_mask_t index_mask =
2082 audio_channel_mask_for_index_assignment_from_count(channel_count);
2083 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2084 supported_channel_masks[num_masks++] = index_mask;
2085 }
2086 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002087 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302088
vincenttewf51c94e2019-05-07 10:28:53 +08002089 for (size_t i = 0; i < num_masks; ++i) {
2090 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2091 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302092 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002093 return num_masks;
2094}
2095
2096static inline int read_usb_sup_formats(bool is_playback __unused,
2097 audio_format_t *supported_formats,
2098 uint32_t max_formats __unused)
2099{
2100 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2101 switch (bitwidth) {
2102 case 24:
2103 // XXX : usb.c returns 24 for s24 and s24_le?
2104 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2105 break;
2106 case 32:
2107 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2108 break;
2109 case 16:
2110 default :
2111 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2112 break;
2113 }
2114 ALOGV("%s: %s supported format %d", __func__,
2115 is_playback ? "P" : "C", bitwidth);
2116 return 1;
2117}
2118
2119static inline int read_usb_sup_params_and_compare(bool is_playback,
2120 audio_format_t *format,
2121 audio_format_t *supported_formats,
2122 uint32_t max_formats,
2123 audio_channel_mask_t *mask,
2124 audio_channel_mask_t *supported_channel_masks,
2125 uint32_t max_masks,
2126 uint32_t *rate,
2127 uint32_t *supported_sample_rates,
2128 uint32_t max_rates) {
2129 int ret = 0;
2130 int num_formats;
2131 int num_masks;
2132 int num_rates;
2133 int i;
2134
2135 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2136 max_formats);
2137 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2138 max_masks);
2139
2140 num_rates = read_usb_sup_sample_rates(is_playback,
2141 supported_sample_rates, max_rates);
2142
2143#define LUT(table, len, what, dflt) \
2144 for (i=0; i<len && (table[i] != what); i++); \
2145 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2146
2147 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2148 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2149 LUT(supported_sample_rates, num_rates, *rate, 0);
2150
2151#undef LUT
2152 return ret < 0 ? -EINVAL : 0; // HACK TBD
2153}
2154
Alexy Josephb1379942016-01-29 15:49:38 -08002155audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002156 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002157{
2158 struct audio_usecase *usecase;
2159 struct listnode *node;
2160
2161 list_for_each(node, &adev->usecase_list) {
2162 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002163 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002164 ALOGV("%s: usecase id %d", __func__, usecase->id);
2165 return usecase->id;
2166 }
2167 }
2168 return USECASE_INVALID;
2169}
2170
Alexy Josephb1379942016-01-29 15:49:38 -08002171struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002172 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002173{
2174 struct audio_usecase *usecase;
2175 struct listnode *node;
2176
2177 list_for_each(node, &adev->usecase_list) {
2178 usecase = node_to_item(node, struct audio_usecase, list);
2179 if (usecase->id == uc_id)
2180 return usecase;
2181 }
2182 return NULL;
2183}
2184
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302185/*
2186 * is a true native playback active
2187 */
2188bool audio_is_true_native_stream_active(struct audio_device *adev)
2189{
2190 bool active = false;
2191 int i = 0;
2192 struct listnode *node;
2193
2194 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2195 ALOGV("%s:napb: not in true mode or non hdphones device",
2196 __func__);
2197 active = false;
2198 goto exit;
2199 }
2200
2201 list_for_each(node, &adev->usecase_list) {
2202 struct audio_usecase *uc;
2203 uc = node_to_item(node, struct audio_usecase, list);
2204 struct stream_out *curr_out =
2205 (struct stream_out*) uc->stream.out;
2206
2207 if (curr_out && PCM_PLAYBACK == uc->type) {
2208 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2209 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2210 uc->id, curr_out->sample_rate,
2211 curr_out->bit_width,
2212 platform_get_snd_device_name(uc->out_snd_device));
2213
2214 if (is_offload_usecase(uc->id) &&
2215 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2216 active = true;
2217 ALOGD("%s:napb:native stream detected", __func__);
2218 }
2219 }
2220 }
2221exit:
2222 return active;
2223}
2224
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002225uint32_t adev_get_dsp_bit_width_enforce_mode()
2226{
2227 if (adev == NULL) {
2228 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2229 return 0;
2230 }
2231 return adev->dsp_bit_width_enforce_mode;
2232}
2233
2234static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2235{
2236 char value[PROPERTY_VALUE_MAX];
2237 int trial;
2238 uint32_t dsp_bit_width_enforce_mode = 0;
2239
2240 if (!mixer) {
2241 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2242 __func__);
2243 return 0;
2244 }
2245
2246 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2247 value, NULL) > 0) {
2248 trial = atoi(value);
2249 switch (trial) {
2250 case 16:
2251 dsp_bit_width_enforce_mode = 16;
2252 break;
2253 case 24:
2254 dsp_bit_width_enforce_mode = 24;
2255 break;
2256 case 32:
2257 dsp_bit_width_enforce_mode = 32;
2258 break;
2259 default:
2260 dsp_bit_width_enforce_mode = 0;
2261 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2262 break;
2263 }
2264 }
2265
2266 return dsp_bit_width_enforce_mode;
2267}
2268
2269static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2270 uint32_t enforce_mode,
2271 bool enable)
2272{
2273 struct mixer_ctl *ctl = NULL;
2274 const char *mixer_ctl_name = "ASM Bit Width";
2275 uint32_t asm_bit_width_mode = 0;
2276
2277 if (enforce_mode == 0) {
2278 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2279 return;
2280 }
2281
2282 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2283 if (!ctl) {
2284 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2285 __func__, mixer_ctl_name);
2286 return;
2287 }
2288
2289 if (enable)
2290 asm_bit_width_mode = enforce_mode;
2291 else
2292 asm_bit_width_mode = 0;
2293
2294 ALOGV("%s DSP bit width feature status is %d width=%d",
2295 __func__, enable, asm_bit_width_mode);
2296 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2297 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2298 asm_bit_width_mode);
2299
2300 return;
2301}
2302
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302303/*
2304 * if native DSD playback active
2305 */
2306bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2307{
2308 bool active = false;
2309 struct listnode *node = NULL;
2310 struct audio_usecase *uc = NULL;
2311 struct stream_out *curr_out = NULL;
2312
2313 list_for_each(node, &adev->usecase_list) {
2314 uc = node_to_item(node, struct audio_usecase, list);
2315 curr_out = (struct stream_out*) uc->stream.out;
2316
2317 if (curr_out && PCM_PLAYBACK == uc->type &&
2318 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2319 active = true;
2320 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302321 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302322 }
2323 }
2324 return active;
2325}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302326
2327static bool force_device_switch(struct audio_usecase *usecase)
2328{
2329 bool ret = false;
2330 bool is_it_true_mode = false;
2331
Zhou Song30f2c3e2018-02-08 14:02:15 +08002332 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302333 usecase->type == TRANSCODE_LOOPBACK_RX ||
2334 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002335 return false;
2336 }
2337
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002338 if(usecase->stream.out == NULL) {
2339 ALOGE("%s: stream.out is NULL", __func__);
2340 return false;
2341 }
2342
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302343 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002344 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002345 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2346 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302347 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2348 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2349 (!is_it_true_mode && adev->native_playback_enabled)){
2350 ret = true;
2351 ALOGD("napb: time to toggle native mode");
2352 }
2353 }
2354
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302355 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302356 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2357 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002358 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302359 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302360 ALOGD("Force a2dp device switch to update new encoder config");
2361 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002362 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302363
Florian Pfister1a84f312018-07-19 14:38:18 +02002364 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302365 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2366 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002367 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302368 return ret;
2369}
2370
Aalique Grahame22e49102018-12-18 14:23:57 -08002371static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2372{
2373 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2374}
2375
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302376bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2377{
2378 bool ret=false;
2379 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002380 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2381 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302382 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2383 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002384 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302385 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2386 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2387 ret = true;
2388
2389 return ret;
2390}
2391
2392bool is_a2dp_device(snd_device_t out_snd_device)
2393{
2394 bool ret=false;
2395 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2396 ret = true;
2397
2398 return ret;
2399}
2400
2401bool is_bt_soc_on(struct audio_device *adev)
2402{
2403 struct mixer_ctl *ctl;
2404 char *mixer_ctl_name = "BT SOC status";
2405 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2406 bool bt_soc_status = true;
2407 if (!ctl) {
2408 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2409 __func__, mixer_ctl_name);
2410 /*This is to ensure we dont break targets which dont have the kernel change*/
2411 return true;
2412 }
2413 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2414 ALOGD("BT SOC status: %d",bt_soc_status);
2415 return bt_soc_status;
2416}
2417
Zhou Song331c8e52019-08-26 14:16:12 +08002418static int configure_btsco_sample_rate(snd_device_t snd_device)
2419{
2420 struct mixer_ctl *ctl = NULL;
2421 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2422 char *rate_str = NULL;
2423 bool is_rx_dev = true;
2424
2425 if (is_btsco_device(snd_device, snd_device)) {
2426 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2427 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2428 if (!ctl_sr_tx || !ctl_sr_rx) {
2429 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2430 if (!ctl_sr)
2431 return -ENOSYS;
2432 }
2433
2434 switch (snd_device) {
2435 case SND_DEVICE_OUT_BT_SCO:
2436 rate_str = "KHZ_8";
2437 break;
2438 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2439 case SND_DEVICE_IN_BT_SCO_MIC:
2440 rate_str = "KHZ_8";
2441 is_rx_dev = false;
2442 break;
2443 case SND_DEVICE_OUT_BT_SCO_WB:
2444 rate_str = "KHZ_16";
2445 break;
2446 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2447 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2448 rate_str = "KHZ_16";
2449 is_rx_dev = false;
2450 break;
2451 default:
2452 return 0;
2453 }
2454
2455 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2456 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2457 return -ENOSYS;
2458 }
2459 return 0;
2460}
2461
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302462int out_standby_l(struct audio_stream *stream);
2463
Eric Laurent637e2d42018-11-15 12:24:31 -08002464struct stream_in *adev_get_active_input(const struct audio_device *adev)
2465{
2466 struct listnode *node;
2467 struct stream_in *last_active_in = NULL;
2468
2469 /* Get last added active input.
2470 * TODO: We may use a priority mechanism to pick highest priority active source */
2471 list_for_each(node, &adev->usecase_list)
2472 {
2473 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2474 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2475 last_active_in = usecase->stream.in;
2476 }
2477
2478 return last_active_in;
2479}
2480
2481struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2482{
2483 struct listnode *node;
2484
2485 /* First check active inputs with voice communication source and then
2486 * any input if audio mode is in communication */
2487 list_for_each(node, &adev->usecase_list)
2488 {
2489 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2490 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2491 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2492 return usecase->stream.in;
2493 }
2494 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2495 return adev_get_active_input(adev);
2496
2497 return NULL;
2498}
2499
Carter Hsu2e429db2019-05-14 18:50:52 +08002500/*
2501 * Aligned with policy.h
2502 */
2503static inline int source_priority(int inputSource)
2504{
2505 switch (inputSource) {
2506 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2507 return 9;
2508 case AUDIO_SOURCE_CAMCORDER:
2509 return 8;
2510 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2511 return 7;
2512 case AUDIO_SOURCE_UNPROCESSED:
2513 return 6;
2514 case AUDIO_SOURCE_MIC:
2515 return 5;
2516 case AUDIO_SOURCE_ECHO_REFERENCE:
2517 return 4;
2518 case AUDIO_SOURCE_FM_TUNER:
2519 return 3;
2520 case AUDIO_SOURCE_VOICE_RECOGNITION:
2521 return 2;
2522 case AUDIO_SOURCE_HOTWORD:
2523 return 1;
2524 default:
2525 break;
2526 }
2527 return 0;
2528}
2529
2530static struct stream_in *get_priority_input(struct audio_device *adev)
2531{
2532 struct listnode *node;
2533 struct audio_usecase *usecase;
2534 int last_priority = 0, priority;
2535 struct stream_in *priority_in = NULL;
2536 struct stream_in *in;
2537
2538 list_for_each(node, &adev->usecase_list) {
2539 usecase = node_to_item(node, struct audio_usecase, list);
2540 if (usecase->type == PCM_CAPTURE) {
2541 in = usecase->stream.in;
2542 if (!in)
2543 continue;
2544 priority = source_priority(in->source);
2545
2546 if (priority > last_priority) {
2547 last_priority = priority;
2548 priority_in = in;
2549 }
2550 }
2551 }
2552 return priority_in;
2553}
2554
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002555int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002557 snd_device_t out_snd_device = SND_DEVICE_NONE;
2558 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002559 struct audio_usecase *usecase = NULL;
2560 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002561 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002562 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302563 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002564 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002565 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302567 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2568
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002569 usecase = get_usecase_from_list(adev, uc_id);
2570 if (usecase == NULL) {
2571 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2572 return -EINVAL;
2573 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002575 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002576 (usecase->type == VOIP_CALL) ||
2577 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302578 if(usecase->stream.out == NULL) {
2579 ALOGE("%s: stream.out is NULL", __func__);
2580 return -EINVAL;
2581 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002582 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002583 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2584 uc_id);
2585 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2586 uc_id);
2587 } else {
2588 out_snd_device = platform_get_output_snd_device(adev->platform,
2589 usecase->stream.out);
2590 in_snd_device = platform_get_input_snd_device(adev->platform,
2591 NULL,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002592 &usecase->stream.out->device_list);
Guodong Hu267bdf82019-08-12 19:22:32 +08002593 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002594 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302595 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302596 if (usecase->stream.inout == NULL) {
2597 ALOGE("%s: stream.inout is NULL", __func__);
2598 return -EINVAL;
2599 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002600 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302601 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2602 stream_out.format = usecase->stream.inout->out_config.format;
2603 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2604 out_snd_device = platform_get_output_snd_device(adev->platform,
2605 &stream_out);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002606 assign_devices(&usecase->device_list,
2607 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302608 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2609 if (usecase->stream.inout == NULL) {
2610 ALOGE("%s: stream.inout is NULL", __func__);
2611 return -EINVAL;
2612 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002613 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL);
2614 assign_devices(&usecase->device_list,
2615 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 } else {
2617 /*
2618 * If the voice call is active, use the sound devices of voice call usecase
2619 * so that it would not result any device switch. All the usecases will
2620 * be switched to new device when select_devices() is called for voice call
2621 * usecase. This is to avoid switching devices for voice call when
2622 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002623 * choose voice call device only if the use case device is
2624 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002625 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002626 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002627 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002628 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002629 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2630 is_codec_backend_out_device_type(&usecase->device_list)) ||
2631 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2632 is_codec_backend_in_device_type(&usecase->device_list)) ||
2633 is_single_device_type_equal(&vc_usecase->device_list,
2634 AUDIO_DEVICE_OUT_HEARING_AID) ||
2635 is_single_device_type_equal(&usecase->device_list,
2636 AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002637 in_snd_device = vc_usecase->in_snd_device;
2638 out_snd_device = vc_usecase->out_snd_device;
2639 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002640 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002641 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002642 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002643 if ((voip_usecase != NULL) &&
2644 (usecase->type == PCM_PLAYBACK) &&
2645 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002646 out_snd_device_backend_match = platform_check_backends_match(
2647 voip_usecase->out_snd_device,
2648 platform_get_output_snd_device(
2649 adev->platform,
2650 usecase->stream.out));
2651 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002652 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2653 (is_codec_backend_out_device_type(&usecase->device_list) ||
2654 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002655 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002656 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002657 in_snd_device = voip_usecase->in_snd_device;
2658 out_snd_device = voip_usecase->out_snd_device;
2659 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002660 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002661 hfp_ucid = audio_extn_hfp_get_usecase();
2662 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002663 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002664 in_snd_device = hfp_usecase->in_snd_device;
2665 out_snd_device = hfp_usecase->out_snd_device;
2666 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002667 }
2668 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302669 if (usecase->stream.out == NULL) {
2670 ALOGE("%s: stream.out is NULL", __func__);
2671 return -EINVAL;
2672 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002673 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002674 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002675 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002676 struct stream_out *voip_out = adev->primary_output;
2677 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002678 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002679 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2680 else
2681 out_snd_device = platform_get_output_snd_device(adev->platform,
2682 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002683 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002684
Eric Laurent637e2d42018-11-15 12:24:31 -08002685 if (voip_usecase)
2686 voip_out = voip_usecase->stream.out;
2687
2688 if (usecase->stream.out == voip_out && voip_in != NULL)
2689 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002691 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302692 if (usecase->stream.in == NULL) {
2693 ALOGE("%s: stream.in is NULL", __func__);
2694 return -EINVAL;
2695 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002696 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002697 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002698 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002699 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002700 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002701 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002702
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002703 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002704 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002705 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2706 USECASE_AUDIO_PLAYBACK_VOIP);
2707
Carter Hsu2e429db2019-05-14 18:50:52 +08002708 usecase->stream.in->enable_ec_port = false;
2709
Eric Laurent637e2d42018-11-15 12:24:31 -08002710 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002711 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002712 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002713 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002714 } else if (adev->primary_output &&
2715 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002716 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002717 } else {
2718 /* forcing speaker o/p device to get matching i/p pair
2719 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002720 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002721 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002722 priority_in = voip_in;
2723 } else {
2724 /* get the input with the highest priority source*/
2725 priority_in = get_priority_input(adev);
2726
2727 if (!priority_in)
2728 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002729 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002730
Eric Laurent637e2d42018-11-15 12:24:31 -08002731 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002732 priority_in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002733 &out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002735 }
2736 }
2737
2738 if (out_snd_device == usecase->out_snd_device &&
2739 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302740
2741 if (!force_device_switch(usecase))
2742 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 }
2744
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002745 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002746 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002747 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002748 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2749 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302750 }
2751
Aalique Grahame22e49102018-12-18 14:23:57 -08002752 if (out_snd_device != SND_DEVICE_NONE &&
2753 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2754 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2755 __func__,
2756 use_case_table[uc_id],
2757 adev->last_logged_snd_device[uc_id][0],
2758 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2759 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2760 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2761 -1,
2762 out_snd_device,
2763 platform_get_snd_device_name(out_snd_device),
2764 platform_get_snd_device_acdb_id(out_snd_device));
2765 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2766 }
2767 if (in_snd_device != SND_DEVICE_NONE &&
2768 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2769 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2770 __func__,
2771 use_case_table[uc_id],
2772 adev->last_logged_snd_device[uc_id][1],
2773 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2774 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2775 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2776 -1,
2777 in_snd_device,
2778 platform_get_snd_device_name(in_snd_device),
2779 platform_get_snd_device_acdb_id(in_snd_device));
2780 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2781 }
2782
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 /*
2785 * Limitation: While in call, to do a device switch we need to disable
2786 * and enable both RX and TX devices though one of them is same as current
2787 * device.
2788 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002789 if ((usecase->type == VOICE_CALL) &&
2790 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2791 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002792 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002793 }
2794
2795 if (((usecase->type == VOICE_CALL) ||
2796 (usecase->type == VOIP_CALL)) &&
2797 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2798 /* Disable sidetone only if voice/voip call already exists */
2799 if (voice_is_call_state_active(adev) ||
2800 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002801 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002802
2803 /* Disable aanc only if voice call exists */
2804 if (voice_is_call_state_active(adev))
2805 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002806 }
2807
Aalique Grahame22e49102018-12-18 14:23:57 -08002808 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2809 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002810 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302811 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002812 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2813 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2814 else
2815 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302816 }
2817
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002818 /* Disable current sound devices */
2819 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002820 disable_audio_route(adev, usecase);
2821 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 }
2823
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002824 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002825 disable_audio_route(adev, usecase);
2826 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 }
2828
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002829 /* Applicable only on the targets that has external modem.
2830 * New device information should be sent to modem before enabling
2831 * the devices to reduce in-call device switch time.
2832 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002833 if ((usecase->type == VOICE_CALL) &&
2834 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2835 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002836 status = platform_switch_voice_call_enable_device_config(adev->platform,
2837 out_snd_device,
2838 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002839 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002840
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002841 /* Enable new sound devices */
2842 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002843 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302844 if (platform_check_codec_asrc_support(adev->platform))
2845 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002846 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 }
2848
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002849 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302850 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002851 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002852 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002853
Avinash Vaish71a8b972014-07-24 15:36:33 +05302854 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002855 status = platform_switch_voice_call_device_post(adev->platform,
2856 out_snd_device,
2857 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302858 enable_audio_route_for_voice_usecases(adev, usecase);
2859 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002860
sangwoo170731f2013-06-08 15:36:36 +09002861 usecase->in_snd_device = in_snd_device;
2862 usecase->out_snd_device = out_snd_device;
2863
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302864 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2865 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302866 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002867 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002868 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002869 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2870 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2871 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2872 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2873 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2874 /*
2875 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2876 * configured device sample rate, if not update the COPP rate to be equal to the
2877 * device sample rate, else open COPP at stream sample rate
2878 */
2879 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2880 usecase->stream.out->sample_rate,
2881 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302882 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302883 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2884 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302885 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002886 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2887 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2888 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2889 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002890 }
2891 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002892
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002893 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002894
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002895 /* If input stream is already running then effect needs to be
2896 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002897 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002898 check_and_enable_effect(adev);
2899
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002900 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002901 /* Enable aanc only if voice call exists */
2902 if (voice_is_call_state_active(adev))
2903 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2904
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002905 /* Enable sidetone only if other voice/voip call already exists */
2906 if (voice_is_call_state_active(adev) ||
2907 voice_extn_compress_voip_is_started(adev))
2908 voice_set_sidetone(adev, out_snd_device, true);
2909 }
2910
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002911 /* Applicable only on the targets that has external modem.
2912 * Enable device command should be sent to modem only after
2913 * enabling voice call mixer controls
2914 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002915 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002916 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2917 out_snd_device,
2918 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302919
2920 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002921 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302922 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002923 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302924 if (is_bt_soc_on(adev) == false){
2925 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002926 if (in->pcm != NULL)
2927 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302928 }
2929 }
2930 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2931 && usecase->stream.out->started) {
2932 if (is_bt_soc_on(adev) == false) {
2933 ALOGD("BT SCO/A2DP disconnected while in connection");
2934 out_standby_l(&usecase->stream.out->stream.common);
2935 }
2936 }
2937 } else if ((usecase->stream.out != NULL) &&
2938 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302939 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2940 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002941 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302942 usecase->stream.out->started) {
2943 if (is_bt_soc_on(adev) == false) {
2944 ALOGD("BT SCO/A2dp disconnected while in connection");
2945 out_standby_l(&usecase->stream.out->stream.common);
2946 }
2947 }
2948 }
2949
Yung Ti Su70cb8242018-06-22 17:38:47 +08002950 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002951 struct stream_out *voip_out = voip_usecase->stream.out;
2952 audio_extn_utils_send_app_type_gain(adev,
2953 voip_out->app_type_cfg.app_type,
2954 &voip_out->app_type_cfg.gain[0]);
2955 }
2956
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302957 ALOGD("%s: done",__func__);
2958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 return status;
2960}
2961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962static int stop_input_stream(struct stream_in *in)
2963{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302964 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302966
2967 if (in == NULL) {
2968 ALOGE("%s: stream_in ptr is NULL", __func__);
2969 return -EINVAL;
2970 }
2971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002973 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974
Eric Laurent994a6932013-07-17 11:51:42 -07002975 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002976 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 uc_info = get_usecase_from_list(adev, in->usecase);
2978 if (uc_info == NULL) {
2979 ALOGE("%s: Could not find the usecase (%d) in the list",
2980 __func__, in->usecase);
2981 return -EINVAL;
2982 }
2983
Carter Hsu2e429db2019-05-14 18:50:52 +08002984 priority_in = get_priority_input(adev);
2985
Derek Chenea197282019-01-07 17:35:01 -08002986 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2987 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002988
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002989 /* Close in-call recording streams */
2990 voice_check_and_stop_incall_rec_usecase(adev, in);
2991
Eric Laurent150dbfe2013-02-27 14:31:02 -08002992 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002993 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002994
2995 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002996 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002998 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302999 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3000
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003001 list_remove(&uc_info->list);
3002 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003
Carter Hsu2e429db2019-05-14 18:50:52 +08003004 if (priority_in == in) {
3005 priority_in = get_priority_input(adev);
3006 if (priority_in)
3007 select_devices(adev, priority_in->usecase);
3008 }
3009
Vatsal Buchac09ae062018-11-14 13:25:08 +05303010 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003011 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 return ret;
3013}
3014
3015int start_input_stream(struct stream_in *in)
3016{
3017 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003018 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303020
3021 if (in == NULL) {
3022 ALOGE("%s: stream_in ptr is NULL", __func__);
3023 return -EINVAL;
3024 }
3025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003027 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003028 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029
Mingming Yin2664a5b2015-09-03 10:53:11 -07003030 if (get_usecase_from_list(adev, usecase) == NULL)
3031 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303032 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3033 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003034
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303035 if (CARD_STATUS_OFFLINE == in->card_status||
3036 CARD_STATUS_OFFLINE == adev->card_status) {
3037 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303038 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303039 goto error_config;
3040 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303041
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003042 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303043 if (!adev->bt_sco_on) {
3044 ALOGE("%s: SCO profile is not ready, return error", __func__);
3045 ret = -EIO;
3046 goto error_config;
3047 }
3048 }
3049
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003050 /* Check if source matches incall recording usecase criteria */
3051 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3052 if (ret)
3053 goto error_config;
3054 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003055 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3056
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303057 if (audio_extn_cin_attached_usecase(in))
3058 audio_extn_cin_acquire_usecase(in);
3059
Mingming Yin2664a5b2015-09-03 10:53:11 -07003060 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3061 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3062 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003063 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003064 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003065
Eric Laurentb23d5282013-05-14 15:27:20 -07003066 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 if (in->pcm_device_id < 0) {
3068 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3069 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003070 ret = -EINVAL;
3071 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003075
3076 if (!uc_info) {
3077 ret = -ENOMEM;
3078 goto error_config;
3079 }
3080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 uc_info->id = in->usecase;
3082 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003083 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003084 list_init(&uc_info->device_list);
3085 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003086 uc_info->in_snd_device = SND_DEVICE_NONE;
3087 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003089 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003090 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303091 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3092 adev->perf_lock_opts,
3093 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003094 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095
Derek Chenea197282019-01-07 17:35:01 -08003096 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3097 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003098
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303099 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3100
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303101 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303102 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303103 if (ret)
3104 goto error_open;
3105 else
3106 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003107 }
3108
Haynes Mathew George16081042017-05-31 17:16:49 -07003109 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003110 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003111 ALOGE("%s: pcm stream not ready", __func__);
3112 goto error_open;
3113 }
3114 ret = pcm_start(in->pcm);
3115 if (ret < 0) {
3116 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3117 goto error_open;
3118 }
3119 } else {
3120 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3121 unsigned int pcm_open_retry_count = 0;
3122
3123 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3124 flags |= PCM_MMAP | PCM_NOIRQ;
3125 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3126 } else if (in->realtime) {
3127 flags |= PCM_MMAP | PCM_NOIRQ;
3128 }
3129
Garmond Leunge2433c32017-09-28 21:51:22 -07003130 if (audio_extn_ffv_get_stream() == in) {
3131 ALOGD("%s: ffv stream, update pcm config", __func__);
3132 audio_extn_ffv_update_pcm_config(&config);
3133 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003134 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3135 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3136
3137 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003138 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003139 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003140 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003141 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303142 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303143 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3144 adev->card_status = CARD_STATUS_OFFLINE;
3145 in->card_status = CARD_STATUS_OFFLINE;
3146 ret = -EIO;
3147 goto error_open;
3148 }
3149
Haynes Mathew George16081042017-05-31 17:16:49 -07003150 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3151 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3152 if (in->pcm != NULL) {
3153 pcm_close(in->pcm);
3154 in->pcm = NULL;
3155 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003156 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003157 ret = -EIO;
3158 goto error_open;
3159 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003160 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003161 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3162 continue;
3163 }
3164 break;
3165 }
3166
3167 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003168 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003169 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003170 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003171 if (ret < 0) {
3172 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3173 pcm_close(in->pcm);
3174 in->pcm = NULL;
3175 goto error_open;
3176 }
3177 register_in_stream(in);
3178 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003179 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003180 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003181 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003182 if (ret < 0) {
3183 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003184 pcm_close(in->pcm);
3185 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003186 goto error_open;
3187 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003188 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003189 }
3190
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003191 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003192 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3193 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003194
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003195 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303196 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3197
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303198done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003199 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303200 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003201 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303202 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003203 return ret;
3204
3205error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003206 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303207 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003209
Eric Laurentc8400632013-02-14 19:04:54 -08003210error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303211 /*
3212 * sleep 50ms to allow sufficient time for kernel
3213 * drivers to recover incases like SSR.
3214 */
3215 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003216 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303217 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003218 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219}
3220
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003221void lock_input_stream(struct stream_in *in)
3222{
3223 pthread_mutex_lock(&in->pre_lock);
3224 pthread_mutex_lock(&in->lock);
3225 pthread_mutex_unlock(&in->pre_lock);
3226}
3227
3228void lock_output_stream(struct stream_out *out)
3229{
3230 pthread_mutex_lock(&out->pre_lock);
3231 pthread_mutex_lock(&out->lock);
3232 pthread_mutex_unlock(&out->pre_lock);
3233}
3234
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235/* must be called with out->lock locked */
3236static int send_offload_cmd_l(struct stream_out* out, int command)
3237{
3238 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3239
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003240 if (!cmd) {
3241 ALOGE("failed to allocate mem for command 0x%x", command);
3242 return -ENOMEM;
3243 }
3244
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003245 ALOGVV("%s %d", __func__, command);
3246
3247 cmd->cmd = command;
3248 list_add_tail(&out->offload_cmd_list, &cmd->node);
3249 pthread_cond_signal(&out->offload_cond);
3250 return 0;
3251}
3252
3253/* must be called iwth out->lock locked */
3254static void stop_compressed_output_l(struct stream_out *out)
3255{
3256 out->offload_state = OFFLOAD_STATE_IDLE;
3257 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003258 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003259 if (out->compr != NULL) {
3260 compress_stop(out->compr);
3261 while (out->offload_thread_blocked) {
3262 pthread_cond_wait(&out->cond, &out->lock);
3263 }
3264 }
3265}
3266
Varun Balaraje49253e2017-07-06 19:48:56 +05303267bool is_interactive_usecase(audio_usecase_t uc_id)
3268{
3269 unsigned int i;
3270 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3271 if (uc_id == interactive_usecases[i])
3272 return true;
3273 }
3274 return false;
3275}
3276
3277static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3278{
3279 audio_usecase_t ret_uc = USECASE_INVALID;
3280 unsigned int intract_uc_index;
3281 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3282
3283 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3284 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3285 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3286 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3287 ret_uc = interactive_usecases[intract_uc_index];
3288 break;
3289 }
3290 }
3291
3292 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3293 return ret_uc;
3294}
3295
3296static void free_interactive_usecase(struct audio_device *adev,
3297 audio_usecase_t uc_id)
3298{
3299 unsigned int interact_uc_index;
3300 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3301
3302 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3303 if (interactive_usecases[interact_uc_index] == uc_id) {
3304 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3305 break;
3306 }
3307 }
3308 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3309}
3310
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003311bool is_offload_usecase(audio_usecase_t uc_id)
3312{
3313 unsigned int i;
3314 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3315 if (uc_id == offload_usecases[i])
3316 return true;
3317 }
3318 return false;
3319}
3320
Dhananjay Kumarac341582017-02-23 23:42:25 +05303321static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003322{
vivek mehta446c3962015-09-14 10:57:35 -07003323 audio_usecase_t ret_uc = USECASE_INVALID;
3324 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003325 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003326 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303327 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003328 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3329 else
3330 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003331
vivek mehta446c3962015-09-14 10:57:35 -07003332 pthread_mutex_lock(&adev->lock);
3333 if (get_usecase_from_list(adev, ret_uc) != NULL)
3334 ret_uc = USECASE_INVALID;
3335 pthread_mutex_unlock(&adev->lock);
3336
3337 return ret_uc;
3338 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003339
3340 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003341 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3342 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3343 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3344 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003345 break;
3346 }
3347 }
vivek mehta446c3962015-09-14 10:57:35 -07003348
3349 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3350 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351}
3352
3353static void free_offload_usecase(struct audio_device *adev,
3354 audio_usecase_t uc_id)
3355{
vivek mehta446c3962015-09-14 10:57:35 -07003356 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003357 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003358
3359 if (!adev->multi_offload_enable)
3360 return;
3361
3362 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3363 if (offload_usecases[offload_uc_index] == uc_id) {
3364 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003365 break;
3366 }
3367 }
3368 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3369}
3370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371static void *offload_thread_loop(void *context)
3372{
3373 struct stream_out *out = (struct stream_out *) context;
3374 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003375 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003377 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003378 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3380
3381 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003382 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003383 out->offload_state = OFFLOAD_STATE_IDLE;
3384 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 for (;;) {
3386 struct offload_cmd *cmd = NULL;
3387 stream_callback_event_t event;
3388 bool send_callback = false;
3389
3390 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3391 __func__, list_empty(&out->offload_cmd_list),
3392 out->offload_state);
3393 if (list_empty(&out->offload_cmd_list)) {
3394 ALOGV("%s SLEEPING", __func__);
3395 pthread_cond_wait(&out->offload_cond, &out->lock);
3396 ALOGV("%s RUNNING", __func__);
3397 continue;
3398 }
3399
3400 item = list_head(&out->offload_cmd_list);
3401 cmd = node_to_item(item, struct offload_cmd, node);
3402 list_remove(item);
3403
3404 ALOGVV("%s STATE %d CMD %d out->compr %p",
3405 __func__, out->offload_state, cmd->cmd, out->compr);
3406
3407 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3408 free(cmd);
3409 break;
3410 }
3411
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003412 // allow OFFLOAD_CMD_ERROR reporting during standby
3413 // this is needed to handle failures during compress_open
3414 // Note however that on a pause timeout, the stream is closed
3415 // and no offload usecase will be active. Therefore this
3416 // special case is needed for compress_open failures alone
3417 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3418 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003419 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003420 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003421 pthread_cond_signal(&out->cond);
3422 continue;
3423 }
3424 out->offload_thread_blocked = true;
3425 pthread_mutex_unlock(&out->lock);
3426 send_callback = false;
3427 switch(cmd->cmd) {
3428 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003429 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003431 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 send_callback = true;
3433 event = STREAM_CBK_EVENT_WRITE_READY;
3434 break;
3435 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003436 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303437 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003438 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303439 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003440 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303441 if (ret < 0)
3442 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303443 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303444 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003445 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003446 else
3447 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003448 if (-ENETRESET != ret && !(-EINTR == ret &&
3449 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303450 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303451 pthread_mutex_lock(&out->lock);
3452 out->send_new_metadata = 1;
3453 out->send_next_track_params = true;
3454 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303455 event = STREAM_CBK_EVENT_DRAIN_READY;
3456 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3457 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303458 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003459 break;
3460 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003461 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003462 ret = compress_drain(out->compr);
3463 ALOGD("copl(%p):out of compress_drain", out);
3464 // EINTR check avoids drain interruption due to SSR
3465 if (-ENETRESET != ret && !(-EINTR == ret &&
3466 CARD_STATUS_OFFLINE == out->card_status)) {
3467 send_callback = true;
3468 event = STREAM_CBK_EVENT_DRAIN_READY;
3469 } else
3470 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303472 case OFFLOAD_CMD_ERROR:
3473 ALOGD("copl(%p): sending error callback to AF", out);
3474 send_callback = true;
3475 event = STREAM_CBK_EVENT_ERROR;
3476 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 default:
3478 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3479 break;
3480 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003481 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 out->offload_thread_blocked = false;
3483 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003484 if (send_callback && out->client_callback) {
3485 ALOGVV("%s: sending client_callback event %d", __func__, event);
3486 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003487 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 free(cmd);
3489 }
3490
3491 pthread_cond_signal(&out->cond);
3492 while (!list_empty(&out->offload_cmd_list)) {
3493 item = list_head(&out->offload_cmd_list);
3494 list_remove(item);
3495 free(node_to_item(item, struct offload_cmd, node));
3496 }
3497 pthread_mutex_unlock(&out->lock);
3498
3499 return NULL;
3500}
3501
3502static int create_offload_callback_thread(struct stream_out *out)
3503{
3504 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3505 list_init(&out->offload_cmd_list);
3506 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3507 offload_thread_loop, out);
3508 return 0;
3509}
3510
3511static int destroy_offload_callback_thread(struct stream_out *out)
3512{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003513 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003514 stop_compressed_output_l(out);
3515 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3516
3517 pthread_mutex_unlock(&out->lock);
3518 pthread_join(out->offload_thread, (void **) NULL);
3519 pthread_cond_destroy(&out->offload_cond);
3520
3521 return 0;
3522}
3523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524static int stop_output_stream(struct stream_out *out)
3525{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303526 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 struct audio_usecase *uc_info;
3528 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003529 bool has_voip_usecase =
3530 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Eric Laurent994a6932013-07-17 11:51:42 -07003532 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003533 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 uc_info = get_usecase_from_list(adev, out->usecase);
3535 if (uc_info == NULL) {
3536 ALOGE("%s: Could not find the usecase (%d) in the list",
3537 __func__, out->usecase);
3538 return -EINVAL;
3539 }
3540
Derek Chenea197282019-01-07 17:35:01 -08003541 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3542 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003543
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003544 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303545 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003546 if (adev->visualizer_stop_output != NULL)
3547 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003548
3549 audio_extn_dts_remove_state_notifier_node(out->usecase);
3550
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003551 if (adev->offload_effects_stop_output != NULL)
3552 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003553 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3554 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3555 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003556 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003557
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003558 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3559 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003560 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003561 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003562
Eric Laurent150dbfe2013-02-27 14:31:02 -08003563 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003564 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003565
3566 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003567 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568
Aalique Grahame22e49102018-12-18 14:23:57 -08003569 audio_extn_extspk_update(adev->extspk);
3570
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003571 if (is_offload_usecase(out->usecase)) {
3572 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3573 adev->dsp_bit_width_enforce_mode,
3574 false);
3575 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003576 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003577 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3578 false);
3579
3580 if (ret != 0)
3581 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3582 /* default service interval was successfully updated,
3583 reopen USB backend with new service interval */
3584 ret = 0;
3585 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003586
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003587 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303588 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003589 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303590 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003591 ALOGV("Disable passthrough , reset mixer to pcm");
3592 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003593#ifdef AUDIO_GKI_ENABLED
3594 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3595 out->compr_config.codec->reserved[0] = 0;
3596#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003597 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003598#endif
Mingming Yin21854652016-04-13 11:54:02 -07003599 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003600 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3601 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003602
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303603 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003604 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303605 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303606
Manish Dewangan21a850a2017-08-14 12:03:55 +05303607 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003608 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3609 if (ret < 0)
3610 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3611 }
3612
juyuchen2d415992018-11-16 14:15:16 +08003613 /* 1) media + voip output routing to handset must route media back to
3614 speaker when voip stops.
3615 2) trigger voip input to reroute when voip output changes to
3616 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003617 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003618 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003619 struct listnode *node;
3620 struct audio_usecase *usecase;
3621 list_for_each(node, &adev->usecase_list) {
3622 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003623 if ((usecase->type == PCM_CAPTURE &&
3624 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3625 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003626 continue;
3627
3628 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3629 __func__, usecase->id, use_case_table[usecase->id],
3630 out->usecase, use_case_table[out->usecase]);
3631 select_devices(adev, usecase->id);
3632 }
3633 }
3634
Garmond Leung5fd0b552018-04-17 11:56:12 -07003635 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003636 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 return ret;
3638}
3639
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003640struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3641 unsigned int flags, unsigned int pcm_open_retry_count,
3642 struct pcm_config *config)
3643{
3644 struct pcm* pcm = NULL;
3645
3646 while (1) {
3647 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3648 if (pcm == NULL || !pcm_is_ready(pcm)) {
3649 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3650 if (pcm != NULL) {
3651 pcm_close(pcm);
3652 pcm = NULL;
3653 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003654 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003655 return NULL;
3656
Weiyin Jiang72197252019-10-09 11:49:32 +08003657 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003658 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3659 continue;
3660 }
3661 break;
3662 }
3663
3664 if (pcm_is_ready(pcm)) {
3665 int ret = pcm_prepare(pcm);
3666 if (ret < 0) {
3667 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3668 pcm_close(pcm);
3669 pcm = NULL;
3670 }
3671 }
3672
3673 return pcm;
3674}
3675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676int start_output_stream(struct stream_out *out)
3677{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 struct audio_usecase *uc_info;
3680 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003681 char mixer_ctl_name[128];
3682 struct mixer_ctl *ctl = NULL;
3683 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303684 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003685 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686
Haynes Mathew George380745d2017-10-04 15:27:45 -07003687 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003688 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3689 ret = -EINVAL;
3690 goto error_config;
3691 }
3692
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003693 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303694 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003695 get_device_types(&out->device_list), is_haptic_usecase);
3696
3697 bool is_speaker_active = compare_device_type(&out->device_list,
3698 AUDIO_DEVICE_OUT_SPEAKER);
3699 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3700 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303701
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303702 if (CARD_STATUS_OFFLINE == out->card_status ||
3703 CARD_STATUS_OFFLINE == adev->card_status) {
3704 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303705 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303706 goto error_config;
3707 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303708
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003709 //Update incall music usecase to reflect correct voice session
3710 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3711 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3712 if (ret != 0) {
3713 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3714 __func__, ret);
3715 goto error_config;
3716 }
3717 }
3718
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003719 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003720 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003721 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303722 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303723 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303724 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3725 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3726 ret = -EAGAIN;
3727 goto error_config;
3728 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303729 }
3730 }
3731 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003732 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303733 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003734 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303735 //combo usecase just by pass a2dp
3736 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003737 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303738 } else {
3739 ALOGE("%s: SCO profile is not ready, return error", __func__);
3740 ret = -EAGAIN;
3741 goto error_config;
3742 }
3743 }
3744 }
3745
Eric Laurentb23d5282013-05-14 15:27:20 -07003746 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 if (out->pcm_device_id < 0) {
3748 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3749 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003750 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003751 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 }
3753
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003754 if (is_haptic_usecase) {
3755 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3756 if (adev->haptic_pcm_device_id < 0) {
3757 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3758 __func__, adev->haptic_pcm_device_id, out->usecase);
3759 ret = -EINVAL;
3760 goto error_config;
3761 }
3762 }
3763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003765
3766 if (!uc_info) {
3767 ret = -ENOMEM;
3768 goto error_config;
3769 }
3770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 uc_info->id = out->usecase;
3772 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003773 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003774 list_init(&uc_info->device_list);
3775 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003776 uc_info->in_snd_device = SND_DEVICE_NONE;
3777 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003778
3779 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003780 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003781 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3782 /* USB backend is not reopened immediately.
3783 This is eventually done as part of select_devices */
3784 }
3785
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003786 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787
Wei Wangf7ca6c92017-11-21 14:51:20 -08003788 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303789 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3790 adev->perf_lock_opts,
3791 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303792
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003793 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303794 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303795 if (audio_extn_passthru_is_enabled() &&
3796 audio_extn_passthru_is_passthrough_stream(out)) {
3797 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303798 }
3799 }
3800
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003801 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003802 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303803 if (!a2dp_combo) {
3804 check_a2dp_restore_l(adev, out, false);
3805 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003806 struct listnode dev;
3807 list_init(&dev);
3808 assign_devices(&dev, &out->device_list);
3809 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3810 reassign_device_list(&out->device_list,
3811 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003812 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003813 reassign_device_list(&out->device_list,
3814 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303815 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003816 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303817 }
3818 } else {
3819 select_devices(adev, out->usecase);
3820 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003821
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003822 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3823 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003824 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003825 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003826
Derek Chenea197282019-01-07 17:35:01 -08003827 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3828 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003829
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003830 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3831 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003832
3833 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003834 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003835 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3836 ALOGE("%s: pcm stream not ready", __func__);
3837 goto error_open;
3838 }
3839 ret = pcm_start(out->pcm);
3840 if (ret < 0) {
3841 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3842 goto error_open;
3843 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003844 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003845 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003846 unsigned int flags = PCM_OUT;
3847 unsigned int pcm_open_retry_count = 0;
3848 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3849 flags |= PCM_MMAP | PCM_NOIRQ;
3850 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003851 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003852 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003853 } else
3854 flags |= PCM_MONOTONIC;
3855
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003856 if ((adev->vr_audio_mode_enabled) &&
3857 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3858 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3859 "PCM_Dev %d Topology", out->pcm_device_id);
3860 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3861 if (!ctl) {
3862 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3863 __func__, mixer_ctl_name);
3864 } else {
3865 //if success use ULLPP
3866 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3867 __func__, mixer_ctl_name, out->pcm_device_id);
3868 //There is a still a possibility that some sessions
3869 // that request for FAST|RAW when 3D audio is active
3870 //can go through ULLPP. Ideally we expects apps to
3871 //listen to audio focus and stop concurrent playback
3872 //Also, we will look for mode flag (voice_in_communication)
3873 //before enabling the realtime flag.
3874 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3875 }
3876 }
3877
Surendar Karka91fa3682018-07-02 18:12:12 +05303878 if (out->realtime)
3879 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3880 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3881
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3883 flags, pcm_open_retry_count,
3884 &(out->config));
3885 if (out->pcm == NULL) {
3886 ret = -EIO;
3887 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003888 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003889
3890 if (is_haptic_usecase) {
3891 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3892 adev->haptic_pcm_device_id,
3893 flags, pcm_open_retry_count,
3894 &(adev->haptics_config));
3895 // failure to open haptics pcm shouldnt stop audio,
3896 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003897
3898 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3899 ALOGD("%s: enable haptic audio synchronization", __func__);
3900 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3901 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003902 }
3903
Surendar Karka91fa3682018-07-02 18:12:12 +05303904 if (!out->realtime)
3905 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303906 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003907
Zhou Song2b8f28f2017-09-11 10:51:38 +08003908 // apply volume for voip playback after path is set up
3909 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3910 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303911 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3912 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303913 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3914 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003915 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3916 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303917 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003918 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003919 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303920 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003921 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3922 adev->dsp_bit_width_enforce_mode,
3923 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003925 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003926 out->compr = compress_open(adev->snd_card,
3927 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003928 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003929 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303930 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303931 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3932 adev->card_status = CARD_STATUS_OFFLINE;
3933 out->card_status = CARD_STATUS_OFFLINE;
3934 ret = -EIO;
3935 goto error_open;
3936 }
3937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003938 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003939 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 compress_close(out->compr);
3941 out->compr = NULL;
3942 ret = -EIO;
3943 goto error_open;
3944 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303945 /* compress_open sends params of the track, so reset the flag here */
3946 out->is_compr_metadata_avail = false;
3947
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003948 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003949 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003950
Fred Oh3f43e742015-03-04 18:42:34 -08003951 /* Since small bufs uses blocking writes, a write will be blocked
3952 for the default max poll time (20s) in the event of an SSR.
3953 Reduce the poll time to observe and deal with SSR faster.
3954 */
Ashish Jain5106d362016-05-11 19:23:33 +05303955 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003956 compress_set_max_poll_wait(out->compr, 1000);
3957 }
3958
Manish Dewangan69426c82017-01-30 17:35:36 +05303959 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303960 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303961
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003962 audio_extn_dts_create_state_notifier_node(out->usecase);
3963 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3964 popcount(out->channel_mask),
3965 out->playback_started);
3966
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003967#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303968 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003969 audio_extn_dolby_send_ddp_endp_params(adev);
3970#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303971 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3972 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003973 if (adev->visualizer_start_output != NULL)
3974 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3975 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303976 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003977 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003978 }
Derek Chenf13dd492018-11-13 14:53:51 -08003979
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003980 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003981 /* Update cached volume from media to offload/direct stream */
3982 struct listnode *node = NULL;
3983 list_for_each(node, &adev->active_outputs_list) {
3984 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3985 streams_output_ctxt_t,
3986 list);
3987 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3988 out->volume_l = out_ctxt->output->volume_l;
3989 out->volume_r = out_ctxt->output->volume_r;
3990 }
3991 }
3992 out_set_compr_volume(&out->stream,
3993 out->volume_l, out->volume_r);
3994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003996
3997 if (ret == 0) {
3998 register_out_stream(out);
3999 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004000 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4001 ALOGE("%s: pcm stream not ready", __func__);
4002 goto error_open;
4003 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004004 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004005 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004006 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004007 if (ret < 0)
4008 goto error_open;
4009 }
4010 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004011 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304012 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004013 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004014
vivek mehtad15d2bf2019-05-17 13:35:10 -07004015 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4016 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4017 audio_low_latency_hint_start();
4018 }
4019
Manish Dewangan21a850a2017-08-14 12:03:55 +05304020 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004021 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004022 if (ret < 0)
4023 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4024 }
4025
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004026 // consider a scenario where on pause lower layers are tear down.
4027 // so on resume, swap mixer control need to be sent only when
4028 // backend is active, hence rather than sending from enable device
4029 // sending it from start of streamtream
4030
4031 platform_set_swap_channels(adev, true);
4032
Haynes Mathew George380745d2017-10-04 15:27:45 -07004033 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304034 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004035 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004037 if (adev->haptic_pcm) {
4038 pcm_close(adev->haptic_pcm);
4039 adev->haptic_pcm = NULL;
4040 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004041 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304042 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004044error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304045 /*
4046 * sleep 50ms to allow sufficient time for kernel
4047 * drivers to recover incases like SSR.
4048 */
4049 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004050 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304051 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004052 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053}
4054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055static int check_input_parameters(uint32_t sample_rate,
4056 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004057 int channel_count,
4058 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304062 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4063 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4064 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004065 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004066 !audio_extn_compr_cap_format_supported(format) &&
4067 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004068 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004069
Aalique Grahame22e49102018-12-18 14:23:57 -08004070 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4071 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4072 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4073 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4074 return -EINVAL;
4075 }
4076
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004077 switch (channel_count) {
4078 case 1:
4079 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304080 case 3:
4081 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004082 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004083 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304084 case 10:
4085 case 12:
4086 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004087 break;
4088 default:
4089 ret = -EINVAL;
4090 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091
4092 switch (sample_rate) {
4093 case 8000:
4094 case 11025:
4095 case 12000:
4096 case 16000:
4097 case 22050:
4098 case 24000:
4099 case 32000:
4100 case 44100:
4101 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004102 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304103 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004104 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304105 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106 break;
4107 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004108 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109 }
4110
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004111 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112}
4113
Naresh Tanniru04f71882018-06-26 17:46:22 +05304114
4115/** Add a value in a list if not already present.
4116 * @return true if value was successfully inserted or already present,
4117 * false if the list is full and does not contain the value.
4118 */
4119static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4120 for (size_t i = 0; i < list_length; i++) {
4121 if (list[i] == value) return true; // value is already present
4122 if (list[i] == 0) { // no values in this slot
4123 list[i] = value;
4124 return true; // value inserted
4125 }
4126 }
4127 return false; // could not insert value
4128}
4129
4130/** Add channel_mask in supported_channel_masks if not already present.
4131 * @return true if channel_mask was successfully inserted or already present,
4132 * false if supported_channel_masks is full and does not contain channel_mask.
4133 */
4134static void register_channel_mask(audio_channel_mask_t channel_mask,
4135 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4136 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4137 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4138}
4139
4140/** Add format in supported_formats if not already present.
4141 * @return true if format was successfully inserted or already present,
4142 * false if supported_formats is full and does not contain format.
4143 */
4144static void register_format(audio_format_t format,
4145 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4146 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4147 "%s: stream can not declare supporting its format %x", __func__, format);
4148}
4149/** Add sample_rate in supported_sample_rates if not already present.
4150 * @return true if sample_rate was successfully inserted or already present,
4151 * false if supported_sample_rates is full and does not contain sample_rate.
4152 */
4153static void register_sample_rate(uint32_t sample_rate,
4154 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4155 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4156 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4157}
4158
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004159static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4160{
4161 uint32_t high = num1, low = num2, temp = 0;
4162
4163 if (!num1 || !num2)
4164 return 0;
4165
4166 if (num1 < num2) {
4167 high = num2;
4168 low = num1;
4169 }
4170
4171 while (low != 0) {
4172 temp = low;
4173 low = high % low;
4174 high = temp;
4175 }
4176 return (num1 * num2)/high;
4177}
4178
4179static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4180{
4181 uint32_t remainder = 0;
4182
4183 if (!multiplier)
4184 return num;
4185
4186 remainder = num % multiplier;
4187 if (remainder)
4188 num += (multiplier - remainder);
4189
4190 return num;
4191}
4192
Aalique Grahame22e49102018-12-18 14:23:57 -08004193static size_t get_stream_buffer_size(size_t duration_ms,
4194 uint32_t sample_rate,
4195 audio_format_t format,
4196 int channel_count,
4197 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198{
4199 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004200 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201
Aalique Grahame22e49102018-12-18 14:23:57 -08004202 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004203 if (is_low_latency)
4204 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304205
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004206 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004207 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208
Ralf Herzbd08d632018-09-28 15:50:49 +02004209 /* make sure the size is multiple of 32 bytes and additionally multiple of
4210 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004211 * At 48 kHz mono 16-bit PCM:
4212 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4213 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004214 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004215 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004216 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004217
4218 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219}
4220
Aalique Grahame22e49102018-12-18 14:23:57 -08004221static size_t get_input_buffer_size(uint32_t sample_rate,
4222 audio_format_t format,
4223 int channel_count,
4224 bool is_low_latency)
4225{
4226 /* Don't know if USB HIFI in this context so use true to be conservative */
4227 if (check_input_parameters(sample_rate, format, channel_count,
4228 true /*is_usb_hifi */) != 0)
4229 return 0;
4230
4231 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4232 sample_rate,
4233 format,
4234 channel_count,
4235 is_low_latency);
4236}
4237
Derek Chenf6318be2017-06-12 17:16:24 -04004238size_t get_output_period_size(uint32_t sample_rate,
4239 audio_format_t format,
4240 int channel_count,
4241 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304242{
4243 size_t size = 0;
4244 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4245
4246 if ((duration == 0) || (sample_rate == 0) ||
4247 (bytes_per_sample == 0) || (channel_count == 0)) {
4248 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4249 bytes_per_sample, channel_count);
4250 return -EINVAL;
4251 }
4252
4253 size = (sample_rate *
4254 duration *
4255 bytes_per_sample *
4256 channel_count) / 1000;
4257 /*
4258 * To have same PCM samples for all channels, the buffer size requires to
4259 * be multiple of (number of channels * bytes per sample)
4260 * For writes to succeed, the buffer must be written at address which is multiple of 32
4261 */
4262 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4263
4264 return (size/(channel_count * bytes_per_sample));
4265}
4266
Zhou Song48453a02018-01-10 17:50:59 +08004267static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304268{
4269 uint64_t actual_frames_rendered = 0;
4270 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4271
4272 /* This adjustment accounts for buffering after app processor.
4273 * It is based on estimated DSP latency per use case, rather than exact.
4274 */
4275 int64_t platform_latency = platform_render_latency(out->usecase) *
4276 out->sample_rate / 1000000LL;
4277
Zhou Song48453a02018-01-10 17:50:59 +08004278 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304279 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4280 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4281 * hence only estimate.
4282 */
George Gao62ebc722019-07-29 16:29:44 -07004283 uint64_t signed_frames = 0;
4284 if (out->written >= kernel_buffer_size)
4285 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304286
George Gao62ebc722019-07-29 16:29:44 -07004287 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4288 if (signed_frames >= platform_latency)
4289 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304290
Zhou Song48453a02018-01-10 17:50:59 +08004291 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304292 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004293 if (timestamp != NULL )
4294 *timestamp = out->writeAt;
4295 } else if (timestamp != NULL) {
4296 clock_gettime(CLOCK_MONOTONIC, timestamp);
4297 }
4298 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304299
4300 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004301 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304302 (long long int)out->written, (int)kernel_buffer_size,
4303 audio_bytes_per_sample(out->compr_config.codec->format),
4304 popcount(out->channel_mask));
4305
4306 return actual_frames_rendered;
4307}
4308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4310{
4311 struct stream_out *out = (struct stream_out *)stream;
4312
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004313 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314}
4315
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004316static int out_set_sample_rate(struct audio_stream *stream __unused,
4317 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318{
4319 return -ENOSYS;
4320}
4321
4322static size_t out_get_buffer_size(const struct audio_stream *stream)
4323{
4324 struct stream_out *out = (struct stream_out *)stream;
4325
Varun Balaraje49253e2017-07-06 19:48:56 +05304326 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304327 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304328 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304329 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4330 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4331 else
4332 return out->compr_config.fragment_size;
4333 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004334 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304335 else if (is_offload_usecase(out->usecase) &&
4336 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304337 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004338
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004339 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004340 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341}
4342
4343static uint32_t out_get_channels(const struct audio_stream *stream)
4344{
4345 struct stream_out *out = (struct stream_out *)stream;
4346
4347 return out->channel_mask;
4348}
4349
4350static audio_format_t out_get_format(const struct audio_stream *stream)
4351{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004352 struct stream_out *out = (struct stream_out *)stream;
4353
4354 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355}
4356
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004357static int out_set_format(struct audio_stream *stream __unused,
4358 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359{
4360 return -ENOSYS;
4361}
4362
4363static int out_standby(struct audio_stream *stream)
4364{
4365 struct stream_out *out = (struct stream_out *)stream;
4366 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004367 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004368
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304369 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4370 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004372 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004374 if (adev->adm_deregister_stream)
4375 adev->adm_deregister_stream(adev->adm_data, out->handle);
4376
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004377 if (is_offload_usecase(out->usecase))
4378 stop_compressed_output_l(out);
4379
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004380 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004382 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4383 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304384 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004385 pthread_mutex_unlock(&adev->lock);
4386 pthread_mutex_unlock(&out->lock);
4387 ALOGD("VOIP output entered standby");
4388 return 0;
4389 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004390 if (out->pcm) {
4391 pcm_close(out->pcm);
4392 out->pcm = NULL;
4393 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004394 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4395 do_stop = out->playback_started;
4396 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004397
4398 if (out->mmap_shared_memory_fd >= 0) {
4399 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4400 __func__, out->mmap_shared_memory_fd);
4401 close(out->mmap_shared_memory_fd);
4402 out->mmap_shared_memory_fd = -1;
4403 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004404 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004405 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004406 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304407 out->send_next_track_params = false;
4408 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004409 out->gapless_mdata.encoder_delay = 0;
4410 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004411 if (out->compr != NULL) {
4412 compress_close(out->compr);
4413 out->compr = NULL;
4414 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004415 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004416 if (do_stop) {
4417 stop_output_stream(out);
4418 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304419 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004420 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004421 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 }
4423 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304424 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425 return 0;
4426}
4427
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304428static int out_on_error(struct audio_stream *stream)
4429{
4430 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004431 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304432
4433 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004434 // always send CMD_ERROR for offload streams, this
4435 // is needed e.g. when SSR happens within compress_open
4436 // since the stream is active, offload_callback_thread is also active.
4437 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4438 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004439 }
4440 pthread_mutex_unlock(&out->lock);
4441
4442 status = out_standby(&out->stream.common);
4443
4444 lock_output_stream(out);
4445 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004446 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304447 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304448
4449 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4450 ALOGD("Setting previous card status if offline");
4451 out->prev_card_status_offline = true;
4452 }
4453
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304454 pthread_mutex_unlock(&out->lock);
4455
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004456 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304457}
4458
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304459/*
4460 *standby implementation without locks, assumes that the callee already
4461 *has taken adev and out lock.
4462 */
4463int out_standby_l(struct audio_stream *stream)
4464{
4465 struct stream_out *out = (struct stream_out *)stream;
4466 struct audio_device *adev = out->dev;
4467
4468 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4469 stream, out->usecase, use_case_table[out->usecase]);
4470
4471 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004472 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304473 if (adev->adm_deregister_stream)
4474 adev->adm_deregister_stream(adev->adm_data, out->handle);
4475
4476 if (is_offload_usecase(out->usecase))
4477 stop_compressed_output_l(out);
4478
4479 out->standby = true;
4480 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4481 voice_extn_compress_voip_close_output_stream(stream);
4482 out->started = 0;
4483 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004484 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304485 return 0;
4486 } else if (!is_offload_usecase(out->usecase)) {
4487 if (out->pcm) {
4488 pcm_close(out->pcm);
4489 out->pcm = NULL;
4490 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004491 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4492 if (adev->haptic_pcm) {
4493 pcm_close(adev->haptic_pcm);
4494 adev->haptic_pcm = NULL;
4495 }
4496
4497 if (adev->haptic_buffer != NULL) {
4498 free(adev->haptic_buffer);
4499 adev->haptic_buffer = NULL;
4500 adev->haptic_buffer_size = 0;
4501 }
4502 adev->haptic_pcm_device_id = 0;
4503 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304504 } else {
4505 ALOGD("copl(%p):standby", out);
4506 out->send_next_track_params = false;
4507 out->is_compr_metadata_avail = false;
4508 out->gapless_mdata.encoder_delay = 0;
4509 out->gapless_mdata.encoder_padding = 0;
4510 if (out->compr != NULL) {
4511 compress_close(out->compr);
4512 out->compr = NULL;
4513 }
4514 }
4515 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004516 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304517 }
4518 ALOGD("%s: exit", __func__);
4519 return 0;
4520}
4521
Aalique Grahame22e49102018-12-18 14:23:57 -08004522static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523{
Aalique Grahame22e49102018-12-18 14:23:57 -08004524 struct stream_out *out = (struct stream_out *)stream;
4525
4526 // We try to get the lock for consistency,
4527 // but it isn't necessary for these variables.
4528 // If we're not in standby, we may be blocked on a write.
4529 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4530 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4531 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4532
4533 if (locked) {
4534 pthread_mutex_unlock(&out->lock);
4535 }
4536
4537 // dump error info
4538 (void)error_log_dump(
4539 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 return 0;
4542}
4543
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004544static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4545{
4546 int ret = 0;
4547 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004548
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004549 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004550 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004551 return -EINVAL;
4552 }
4553
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304554 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004555
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004556 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4557 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304558 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004559 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004560 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4561 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304562 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004563 }
4564
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004565 ALOGV("%s new encoder delay %u and padding %u", __func__,
4566 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4567
4568 return 0;
4569}
4570
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004571static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4572{
4573 return out == adev->primary_output || out == adev->voice_tx_output;
4574}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004575
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304576// note: this call is safe only if the stream_cb is
4577// removed first in close_output_stream (as is done now).
4578static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4579{
4580 if (!stream || !parms)
4581 return;
4582
4583 struct stream_out *out = (struct stream_out *)stream;
4584 struct audio_device *adev = out->dev;
4585
4586 card_status_t status;
4587 int card;
4588 if (parse_snd_card_status(parms, &card, &status) < 0)
4589 return;
4590
4591 pthread_mutex_lock(&adev->lock);
4592 bool valid_cb = (card == adev->snd_card);
4593 pthread_mutex_unlock(&adev->lock);
4594
4595 if (!valid_cb)
4596 return;
4597
4598 lock_output_stream(out);
4599 if (out->card_status != status)
4600 out->card_status = status;
4601 pthread_mutex_unlock(&out->lock);
4602
4603 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4604 use_case_table[out->usecase],
4605 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4606
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304607 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304608 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304609 if (voice_is_call_state_active(adev) &&
4610 out == adev->primary_output) {
4611 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4612 pthread_mutex_lock(&adev->lock);
4613 voice_stop_call(adev);
4614 adev->mode = AUDIO_MODE_NORMAL;
4615 pthread_mutex_unlock(&adev->lock);
4616 }
4617 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304618 return;
4619}
4620
Kevin Rocardfce19002017-08-07 19:21:36 -07004621static int get_alive_usb_card(struct str_parms* parms) {
4622 int card;
4623 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4624 !audio_extn_usb_alive(card)) {
4625 return card;
4626 }
4627 return -ENODEV;
4628}
4629
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004630int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004631 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004632{
4633 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004634 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004635 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004636 bool bypass_a2dp = false;
4637 bool reconfig = false;
4638 unsigned long service_interval = 0;
4639
4640 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004641 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4642
4643 list_init(&new_devices);
4644 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004645
4646 lock_output_stream(out);
4647 pthread_mutex_lock(&adev->lock);
4648
4649 /*
4650 * When HDMI cable is unplugged the music playback is paused and
4651 * the policy manager sends routing=0. But the audioflinger continues
4652 * to write data until standby time (3sec). As the HDMI core is
4653 * turned off, the write gets blocked.
4654 * Avoid this by routing audio to speaker until standby.
4655 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004656 if (is_single_device_type_equal(&out->device_list,
4657 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004658 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004659 !audio_extn_passthru_is_passthrough_stream(out) &&
4660 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004661 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004662 }
4663 /*
4664 * When A2DP is disconnected the
4665 * music playback is paused and the policy manager sends routing=0
4666 * But the audioflinger continues to write data until standby time
4667 * (3sec). As BT is turned off, the write gets blocked.
4668 * Avoid this by routing audio to speaker until standby.
4669 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004670 if (is_a2dp_out_device_type(&out->device_list) &&
4671 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004672 !audio_extn_a2dp_source_is_ready() &&
4673 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004674 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004675 }
4676 /*
4677 * When USB headset is disconnected the music platback paused
4678 * and the policy manager send routing=0. But if the USB is connected
4679 * back before the standby time, AFE is not closed and opened
4680 * when USB is connected back. So routing to speker will guarantee
4681 * AFE reconfiguration and AFE will be opend once USB is connected again
4682 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004683 if (is_usb_out_device_type(&out->device_list) &&
4684 list_empty(&new_devices) &&
4685 !audio_extn_usb_connected(NULL)) {
4686 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4687 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004688 /* To avoid a2dp to sco overlapping / BT device improper state
4689 * check with BT lib about a2dp streaming support before routing
4690 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004691 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004692 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004693 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4694 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004695 //combo usecase just by pass a2dp
4696 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4697 bypass_a2dp = true;
4698 } else {
4699 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4700 /* update device to a2dp and don't route as BT returned error
4701 * However it is still possible a2dp routing called because
4702 * of current active device disconnection (like wired headset)
4703 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004704 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004705 pthread_mutex_unlock(&adev->lock);
4706 pthread_mutex_unlock(&out->lock);
4707 goto error;
4708 }
4709 }
4710 }
4711
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004712 // Workaround: If routing to an non existing usb device, fail gracefully
4713 // The routing request will otherwise block during 10 second
4714 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004715 if (is_usb_out_device_type(&new_devices)) {
4716 struct str_parms *parms =
4717 str_parms_create_str(get_usb_device_address(&new_devices));
4718 if (!parms)
4719 goto error;
4720 if ((card = get_alive_usb_card(parms)) >= 0) {
4721 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4722 pthread_mutex_unlock(&adev->lock);
4723 pthread_mutex_unlock(&out->lock);
4724 str_parms_destroy(parms);
4725 ret = -ENOSYS;
4726 goto error;
4727 }
4728 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004729 }
4730
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004731 // Workaround: If routing to an non existing hdmi device, fail gracefully
4732 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4733 (platform_get_edid_info_v2(adev->platform,
4734 out->extconn.cs.controller,
4735 out->extconn.cs.stream) != 0)) {
4736 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4737 pthread_mutex_unlock(&adev->lock);
4738 pthread_mutex_unlock(&out->lock);
4739 ret = -ENOSYS;
4740 goto error;
4741 }
4742
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004743 /*
4744 * select_devices() call below switches all the usecases on the same
4745 * backend to the new device. Refer to check_usecases_codec_backend() in
4746 * the select_devices(). But how do we undo this?
4747 *
4748 * For example, music playback is active on headset (deep-buffer usecase)
4749 * and if we go to ringtones and select a ringtone, low-latency usecase
4750 * will be started on headset+speaker. As we can't enable headset+speaker
4751 * and headset devices at the same time, select_devices() switches the music
4752 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4753 * So when the ringtone playback is completed, how do we undo the same?
4754 *
4755 * We are relying on the out_set_parameters() call on deep-buffer output,
4756 * once the ringtone playback is ended.
4757 * NOTE: We should not check if the current devices are same as new devices.
4758 * Because select_devices() must be called to switch back the music
4759 * playback to headset.
4760 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004761 if (!list_empty(&new_devices)) {
4762 bool same_dev = compare_devices(&out->device_list, &new_devices);
4763 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004764
4765 if (output_drives_call(adev, out)) {
4766 if (!voice_is_call_state_active(adev)) {
4767 if (adev->mode == AUDIO_MODE_IN_CALL) {
4768 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004769 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004770 service_interval =
4771 audio_extn_usb_find_service_interval(true, true /*playback*/);
4772 audio_extn_usb_set_service_interval(true /*playback*/,
4773 service_interval,
4774 &reconfig);
4775 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4776 }
4777 ret = voice_start_call(adev);
4778 }
4779 } else {
4780 adev->current_call_output = out;
4781 voice_update_devices_for_all_voice_usecases(adev);
4782 }
4783 }
4784
4785 if (!out->standby) {
4786 if (!same_dev) {
4787 ALOGV("update routing change");
4788 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4789 adev->perf_lock_opts,
4790 adev->perf_lock_opts_size);
4791 if (adev->adm_on_routing_change)
4792 adev->adm_on_routing_change(adev->adm_data,
4793 out->handle);
4794 }
4795 if (!bypass_a2dp) {
4796 select_devices(adev, out->usecase);
4797 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004798 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4799 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004800 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004801 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004802 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004803 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004804 }
4805
4806 if (!same_dev) {
4807 // on device switch force swap, lower functions will make sure
4808 // to check if swap is allowed or not.
4809 platform_set_swap_channels(adev, true);
4810 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4811 }
4812 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4813 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004814 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004815 pthread_mutex_lock(&out->compr_mute_lock);
4816 out->a2dp_compress_mute = false;
4817 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4818 pthread_mutex_unlock(&out->compr_mute_lock);
4819 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4820 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4821 }
4822 }
4823 }
4824
4825 pthread_mutex_unlock(&adev->lock);
4826 pthread_mutex_unlock(&out->lock);
4827
4828 /*handles device and call state changes*/
4829 audio_extn_extspk_update(adev->extspk);
4830
4831error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832 ALOGV("%s: exit: code(%d)", __func__, ret);
4833 return ret;
4834}
4835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4837{
4838 struct stream_out *out = (struct stream_out *)stream;
4839 struct audio_device *adev = out->dev;
4840 struct str_parms *parms;
4841 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004842 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004843 int ext_controller = -1;
4844 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845
sangwoobc677242013-08-08 16:53:43 +09004846 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004847 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304849 if (!parms)
4850 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004851
4852 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4853 &ext_stream);
4854 if (err >= 0) {
4855 out->extconn.cs.controller = ext_controller;
4856 out->extconn.cs.stream = ext_stream;
4857 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4858 use_case_table[out->usecase], out->extconn.cs.controller,
4859 out->extconn.cs.stream);
4860 }
4861
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004862 if (out == adev->primary_output) {
4863 pthread_mutex_lock(&adev->lock);
4864 audio_extn_set_parameters(adev, parms);
4865 pthread_mutex_unlock(&adev->lock);
4866 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004867 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004868 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004869 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004870
4871 audio_extn_dts_create_state_notifier_node(out->usecase);
4872 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4873 popcount(out->channel_mask),
4874 out->playback_started);
4875
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004876 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004877 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004878
Surendar Karkaf51b5842018-04-26 11:28:38 +05304879 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4880 sizeof(value));
4881 if (err >= 0) {
4882 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4883 audio_extn_send_dual_mono_mixing_coefficients(out);
4884 }
4885
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304886 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4887 if (err >= 0) {
4888 strlcpy(out->profile, value, sizeof(out->profile));
4889 ALOGV("updating stream profile with value '%s'", out->profile);
4890 lock_output_stream(out);
4891 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4892 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004893 &out->device_list, out->flags,
4894 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304895 out->sample_rate, out->bit_width,
4896 out->channel_mask, out->profile,
4897 &out->app_type_cfg);
4898 pthread_mutex_unlock(&out->lock);
4899 }
4900
Alexy Joseph98988832017-01-13 14:56:59 -08004901 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004902 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4903 // and vendor.audio.hal.output.suspend.supported is set to true
4904 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004905 //check suspend parameter only for low latency and if the property
4906 //is enabled
4907 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4908 ALOGI("%s: got suspend_playback %s", __func__, value);
4909 lock_output_stream(out);
4910 if (!strncmp(value, "false", 5)) {
4911 //suspend_playback=false is supposed to set QOS value back to 75%
4912 //the mixer control sent with value Enable will achieve that
4913 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4914 } else if (!strncmp (value, "true", 4)) {
4915 //suspend_playback=true is supposed to remove QOS value
4916 //resetting the mixer control will set the default value
4917 //for the mixer control which is Disable and this removes the QOS vote
4918 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4919 } else {
4920 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4921 " got %s", __func__, value);
4922 ret = -1;
4923 }
4924
4925 if (ret != 0) {
4926 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4927 __func__, out->pm_qos_mixer_path, ret);
4928 }
4929
4930 pthread_mutex_unlock(&out->lock);
4931 }
4932 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004933
Alexy Joseph98988832017-01-13 14:56:59 -08004934 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304936error:
Eric Laurent994a6932013-07-17 11:51:42 -07004937 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938 return ret;
4939}
4940
Paul McLeana50b7332018-12-17 08:24:21 -07004941static int in_set_microphone_direction(const struct audio_stream_in *stream,
4942 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004943 struct stream_in *in = (struct stream_in *)stream;
4944
4945 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4946
4947 in->direction = dir;
4948
4949 if (in->standby)
4950 return 0;
4951
4952 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004953}
4954
4955static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004956 struct stream_in *in = (struct stream_in *)stream;
4957
4958 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4959
4960 if (zoom > 1.0 || zoom < -1.0)
4961 return -EINVAL;
4962
4963 in->zoom = zoom;
4964
4965 if (in->standby)
4966 return 0;
4967
4968 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004969}
4970
4971
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004972static bool stream_get_parameter_channels(struct str_parms *query,
4973 struct str_parms *reply,
4974 audio_channel_mask_t *supported_channel_masks) {
4975 int ret = -1;
4976 char value[512];
4977 bool first = true;
4978 size_t i, j;
4979
4980 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4981 ret = 0;
4982 value[0] = '\0';
4983 i = 0;
4984 while (supported_channel_masks[i] != 0) {
4985 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4986 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4987 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304988 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004989
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304990 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004991 first = false;
4992 break;
4993 }
4994 }
4995 i++;
4996 }
4997 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4998 }
4999 return ret == 0;
5000}
5001
5002static bool stream_get_parameter_formats(struct str_parms *query,
5003 struct str_parms *reply,
5004 audio_format_t *supported_formats) {
5005 int ret = -1;
5006 char value[256];
5007 size_t i, j;
5008 bool first = true;
5009
5010 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5011 ret = 0;
5012 value[0] = '\0';
5013 i = 0;
5014 while (supported_formats[i] != 0) {
5015 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5016 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5017 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305018 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005019 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305020 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005021 first = false;
5022 break;
5023 }
5024 }
5025 i++;
5026 }
5027 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5028 }
5029 return ret == 0;
5030}
5031
5032static bool stream_get_parameter_rates(struct str_parms *query,
5033 struct str_parms *reply,
5034 uint32_t *supported_sample_rates) {
5035
5036 int i;
5037 char value[256];
5038 int ret = -1;
5039 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5040 ret = 0;
5041 value[0] = '\0';
5042 i=0;
5043 int cursor = 0;
5044 while (supported_sample_rates[i]) {
5045 int avail = sizeof(value) - cursor;
5046 ret = snprintf(value + cursor, avail, "%s%d",
5047 cursor > 0 ? "|" : "",
5048 supported_sample_rates[i]);
5049 if (ret < 0 || ret >= avail) {
5050 // if cursor is at the last element of the array
5051 // overwrite with \0 is duplicate work as
5052 // snprintf already put a \0 in place.
5053 // else
5054 // we had space to write the '|' at value[cursor]
5055 // (which will be overwritten) or no space to fill
5056 // the first element (=> cursor == 0)
5057 value[cursor] = '\0';
5058 break;
5059 }
5060 cursor += ret;
5061 ++i;
5062 }
5063 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5064 value);
5065 }
5066 return ret >= 0;
5067}
5068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005069static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5070{
5071 struct stream_out *out = (struct stream_out *)stream;
5072 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005073 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005074 char value[256];
5075 struct str_parms *reply = str_parms_create();
5076 size_t i, j;
5077 int ret;
5078 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005079
5080 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005081 if (reply) {
5082 str_parms_destroy(reply);
5083 }
5084 if (query) {
5085 str_parms_destroy(query);
5086 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005087 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5088 return NULL;
5089 }
5090
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005091 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005092 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5093 if (ret >= 0) {
5094 value[0] = '\0';
5095 i = 0;
5096 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005097 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5098 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005099 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005100 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005101 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005102 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 first = false;
5104 break;
5105 }
5106 }
5107 i++;
5108 }
5109 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5110 str = str_parms_to_str(reply);
5111 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005112 voice_extn_out_get_parameters(out, query, reply);
5113 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005115
Alexy Joseph62142aa2015-11-16 15:10:34 -08005116
5117 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5118 if (ret >= 0) {
5119 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305120 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5121 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005122 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305123 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005124 } else {
5125 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305126 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005127 }
5128 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005129 if (str)
5130 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005131 str = str_parms_to_str(reply);
5132 }
5133
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005134 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5135 if (ret >= 0) {
5136 value[0] = '\0';
5137 i = 0;
5138 first = true;
5139 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005140 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5141 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005142 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005143 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005144 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005145 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005146 first = false;
5147 break;
5148 }
5149 }
5150 i++;
5151 }
5152 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005153 if (str)
5154 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005155 str = str_parms_to_str(reply);
5156 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005157
5158 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5159 if (ret >= 0) {
5160 value[0] = '\0';
5161 i = 0;
5162 first = true;
5163 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005164 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5165 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005166 if (!first) {
5167 strlcat(value, "|", sizeof(value));
5168 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005169 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005170 first = false;
5171 break;
5172 }
5173 }
5174 i++;
5175 }
5176 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5177 if (str)
5178 free(str);
5179 str = str_parms_to_str(reply);
5180 }
5181
Alexy Joseph98988832017-01-13 14:56:59 -08005182 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5183 //only low latency track supports suspend_resume
5184 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005185 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005186 if (str)
5187 free(str);
5188 str = str_parms_to_str(reply);
5189 }
5190
5191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 str_parms_destroy(query);
5193 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005194 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195 return str;
5196}
5197
5198static uint32_t out_get_latency(const struct audio_stream_out *stream)
5199{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005200 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005201 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005202 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005203
Alexy Josephaa54c872014-12-03 02:46:47 -08005204 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305205 lock_output_stream(out);
5206 latency = audio_extn_utils_compress_get_dsp_latency(out);
5207 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005208 } else if ((out->realtime) ||
5209 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005210 // since the buffer won't be filled up faster than realtime,
5211 // return a smaller number
5212 if (out->config.rate)
5213 period_ms = (out->af_period_multiplier * out->config.period_size *
5214 1000) / (out->config.rate);
5215 else
5216 period_ms = 0;
5217 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005218 } else {
5219 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005220 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005221 }
5222
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005223 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005224 latency += audio_extn_a2dp_get_encoder_latency();
5225
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305226 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005227 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228}
5229
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305230static float AmpToDb(float amplification)
5231{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305232 float db = DSD_VOLUME_MIN_DB;
5233 if (amplification > 0) {
5234 db = 20 * log10(amplification);
5235 if(db < DSD_VOLUME_MIN_DB)
5236 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305237 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305238 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305239}
5240
Arun Mirpuri5d170872019-03-26 13:21:31 -07005241static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5242 float right)
5243{
5244 struct stream_out *out = (struct stream_out *)stream;
5245 long volume = 0;
5246 char mixer_ctl_name[128] = "";
5247 struct audio_device *adev = out->dev;
5248 struct mixer_ctl *ctl = NULL;
5249 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5250 PCM_PLAYBACK);
5251
5252 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5253 "Playback %d Volume", pcm_device_id);
5254 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5255 if (!ctl) {
5256 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5257 __func__, mixer_ctl_name);
5258 return -EINVAL;
5259 }
5260 if (left != right)
5261 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5262 __func__, left, right);
5263 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5264 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5265 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5266 __func__, mixer_ctl_name, volume);
5267 return -EINVAL;
5268 }
5269 return 0;
5270}
5271
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305272static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5273 float right)
5274{
5275 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305276 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305277 char mixer_ctl_name[128];
5278 struct audio_device *adev = out->dev;
5279 struct mixer_ctl *ctl;
5280 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5281 PCM_PLAYBACK);
5282
5283 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5284 "Compress Playback %d Volume", pcm_device_id);
5285 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5286 if (!ctl) {
5287 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5288 __func__, mixer_ctl_name);
5289 return -EINVAL;
5290 }
5291 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5292 __func__, mixer_ctl_name, left, right);
5293 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5294 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5295 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5296
5297 return 0;
5298}
5299
Zhou Song2b8f28f2017-09-11 10:51:38 +08005300static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5301 float right)
5302{
5303 struct stream_out *out = (struct stream_out *)stream;
5304 char mixer_ctl_name[] = "App Type Gain";
5305 struct audio_device *adev = out->dev;
5306 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305307 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005308
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005309 if (!is_valid_volume(left, right)) {
5310 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5311 __func__, left, right);
5312 return -EINVAL;
5313 }
5314
Zhou Song2b8f28f2017-09-11 10:51:38 +08005315 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5316 if (!ctl) {
5317 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5318 __func__, mixer_ctl_name);
5319 return -EINVAL;
5320 }
5321
5322 set_values[0] = 0; //0: Rx Session 1:Tx Session
5323 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305324 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5325 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005326
5327 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5328 return 0;
5329}
5330
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305331static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5332 float right)
5333{
5334 struct stream_out *out = (struct stream_out *)stream;
5335 /* Volume control for pcm playback */
5336 if (left != right) {
5337 return -EINVAL;
5338 } else {
5339 char mixer_ctl_name[128];
5340 struct audio_device *adev = out->dev;
5341 struct mixer_ctl *ctl;
5342 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5343 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5344 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5345 if (!ctl) {
5346 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5347 return -EINVAL;
5348 }
5349
5350 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5351 int ret = mixer_ctl_set_value(ctl, 0, volume);
5352 if (ret < 0) {
5353 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5354 return -EINVAL;
5355 }
5356
5357 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5358
5359 return 0;
5360 }
5361}
5362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363static int out_set_volume(struct audio_stream_out *stream, float left,
5364 float right)
5365{
Eric Laurenta9024de2013-04-04 09:19:12 -07005366 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005367 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305368 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005369
Arun Mirpuri5d170872019-03-26 13:21:31 -07005370 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005371 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5372 /* only take left channel into account: the API is for stereo anyway */
5373 out->muted = (left == 0.0f);
5374 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005375 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305376 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005377 /*
5378 * Set mute or umute on HDMI passthrough stream.
5379 * Only take left channel into account.
5380 * Mute is 0 and unmute 1
5381 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305382 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305383 } else if (out->format == AUDIO_FORMAT_DSD){
5384 char mixer_ctl_name[128] = "DSD Volume";
5385 struct audio_device *adev = out->dev;
5386 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5387
5388 if (!ctl) {
5389 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5390 __func__, mixer_ctl_name);
5391 return -EINVAL;
5392 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305393 volume[0] = (long)(AmpToDb(left));
5394 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305395 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5396 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005397 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005398 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005399 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5400 struct listnode *node = NULL;
5401 list_for_each(node, &adev->active_outputs_list) {
5402 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5403 streams_output_ctxt_t,
5404 list);
5405 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5406 out->volume_l = out_ctxt->output->volume_l;
5407 out->volume_r = out_ctxt->output->volume_r;
5408 }
5409 }
5410 if (!out->a2dp_compress_mute) {
5411 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5412 }
5413 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005414 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305415 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005416 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305417 if (!out->a2dp_compress_mute)
5418 ret = out_set_compr_volume(stream, left, right);
5419 out->volume_l = left;
5420 out->volume_r = right;
5421 pthread_mutex_unlock(&out->compr_mute_lock);
5422 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005423 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005424 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005425 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5426 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5427 if (!out->standby) {
5428 audio_extn_utils_send_app_type_gain(out->dev,
5429 out->app_type_cfg.app_type,
5430 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005431 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005432 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005433 out->volume_l = left;
5434 out->volume_r = right;
5435 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005436 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5437 ALOGV("%s: MMAP set volume called", __func__);
5438 if (!out->standby)
5439 ret = out_set_mmap_volume(stream, left, right);
5440 out->volume_l = left;
5441 out->volume_r = right;
5442 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305443 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305444 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5445 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305446 /* Volume control for pcm playback */
5447 if (!out->standby)
5448 ret = out_set_pcm_volume(stream, left, right);
5449 else
5450 out->apply_volume = true;
5451
5452 out->volume_l = left;
5453 out->volume_r = right;
5454 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005455 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5456 ALOGV("%s: bus device set volume called", __func__);
5457 if (!out->standby)
5458 ret = out_set_pcm_volume(stream, left, right);
5459 out->volume_l = left;
5460 out->volume_r = right;
5461 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005462 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005464 return -ENOSYS;
5465}
5466
Zhou Songc9672822017-08-16 16:01:39 +08005467static void update_frames_written(struct stream_out *out, size_t bytes)
5468{
5469 size_t bpf = 0;
5470
5471 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5472 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5473 bpf = 1;
5474 else if (!is_offload_usecase(out->usecase))
5475 bpf = audio_bytes_per_sample(out->format) *
5476 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005477
5478 pthread_mutex_lock(&out->position_query_lock);
5479 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005480 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005481 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5482 }
5483 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005484}
5485
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005486int split_and_write_audio_haptic_data(struct stream_out *out,
5487 const void *buffer, size_t bytes_to_write)
5488{
5489 struct audio_device *adev = out->dev;
5490
5491 int ret = 0;
5492 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5493 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5494 size_t frame_size = channel_count * bytes_per_sample;
5495 size_t frame_count = bytes_to_write / frame_size;
5496
5497 bool force_haptic_path =
5498 property_get_bool("vendor.audio.test_haptic", false);
5499
5500 // extract Haptics data from Audio buffer
5501 bool alloc_haptic_buffer = false;
5502 int haptic_channel_count = adev->haptics_config.channels;
5503 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5504 size_t audio_frame_size = frame_size - haptic_frame_size;
5505 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5506
5507 if (adev->haptic_buffer == NULL) {
5508 alloc_haptic_buffer = true;
5509 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5510 free(adev->haptic_buffer);
5511 adev->haptic_buffer_size = 0;
5512 alloc_haptic_buffer = true;
5513 }
5514
5515 if (alloc_haptic_buffer) {
5516 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005517 if(adev->haptic_buffer == NULL) {
5518 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5519 return -ENOMEM;
5520 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005521 adev->haptic_buffer_size = total_haptic_buffer_size;
5522 }
5523
5524 size_t src_index = 0, aud_index = 0, hap_index = 0;
5525 uint8_t *audio_buffer = (uint8_t *)buffer;
5526 uint8_t *haptic_buffer = adev->haptic_buffer;
5527
5528 // This is required for testing only. This works for stereo data only.
5529 // One channel is fed to audio stream and other to haptic stream for testing.
5530 if (force_haptic_path)
5531 audio_frame_size = haptic_frame_size = bytes_per_sample;
5532
5533 for (size_t i = 0; i < frame_count; i++) {
5534 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5535 audio_frame_size);
5536 aud_index += audio_frame_size;
5537 src_index += audio_frame_size;
5538
5539 if (adev->haptic_pcm)
5540 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5541 haptic_frame_size);
5542 hap_index += haptic_frame_size;
5543 src_index += haptic_frame_size;
5544
5545 // This is required for testing only.
5546 // Discard haptic channel data.
5547 if (force_haptic_path)
5548 src_index += haptic_frame_size;
5549 }
5550
5551 // write to audio pipeline
5552 ret = pcm_write(out->pcm, (void *)audio_buffer,
5553 frame_count * audio_frame_size);
5554
5555 // write to haptics pipeline
5556 if (adev->haptic_pcm)
5557 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5558 frame_count * haptic_frame_size);
5559
5560 return ret;
5561}
5562
Aalique Grahame22e49102018-12-18 14:23:57 -08005563#ifdef NO_AUDIO_OUT
5564static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5565 const void *buffer __unused, size_t bytes)
5566{
5567 struct stream_out *out = (struct stream_out *)stream;
5568
5569 /* No Output device supported other than BT for playback.
5570 * Sleep for the amount of buffer duration
5571 */
5572 lock_output_stream(out);
5573 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5574 (const struct audio_stream_out *)&out->stream) /
5575 out_get_sample_rate(&out->stream.common));
5576 pthread_mutex_unlock(&out->lock);
5577 return bytes;
5578}
5579#endif
5580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005581static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5582 size_t bytes)
5583{
5584 struct stream_out *out = (struct stream_out *)stream;
5585 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005586 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305587 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005588 const size_t frame_size = audio_stream_out_frame_size(stream);
5589 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305590 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005591 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005592
Haynes Mathew George380745d2017-10-04 15:27:45 -07005593 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005594 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305595
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305596 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005597
Dhananjay Kumarac341582017-02-23 23:42:25 +05305598 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305599 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305600 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5601 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005602 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305603 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305604 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305605 ALOGD(" %s: sound card is not active/SSR state", __func__);
5606 ret= -EIO;
5607 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305608 }
5609 }
5610
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305611 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305612 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305613 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305614 goto exit;
5615 }
5616
Haynes Mathew George16081042017-05-31 17:16:49 -07005617 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5618 ret = -EINVAL;
5619 goto exit;
5620 }
5621
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005622 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305623 !out->is_iec61937_info_available) {
5624
5625 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5626 out->is_iec61937_info_available = true;
5627 } else if (audio_extn_passthru_is_enabled()) {
5628 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305629 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305630
5631 if((out->format == AUDIO_FORMAT_DTS) ||
5632 (out->format == AUDIO_FORMAT_DTS_HD)) {
5633 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5634 buffer, bytes);
5635 if (ret) {
5636 if (ret != -ENOSYS) {
5637 out->is_iec61937_info_available = false;
5638 ALOGD("iec61937 transmission info not yet updated retry");
5639 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305640 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305641 /* if stream has started and after that there is
5642 * stream config change (iec transmission config)
5643 * then trigger select_device to update backend configuration.
5644 */
5645 out->stream_config_changed = true;
5646 pthread_mutex_lock(&adev->lock);
5647 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305648 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005649 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305650 ret = -EINVAL;
5651 goto exit;
5652 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305653 pthread_mutex_unlock(&adev->lock);
5654 out->stream_config_changed = false;
5655 out->is_iec61937_info_available = true;
5656 }
5657 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305658
Meng Wang4c32fb42020-01-16 17:57:11 +08005659#ifdef AUDIO_GKI_ENABLED
5660 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5661 compr_passthr = out->compr_config.codec->reserved[0];
5662#else
5663 compr_passthr = out->compr_config.codec->compr_passthr;
5664#endif
5665
Garmond Leung317cbf12017-09-13 16:20:50 -07005666 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005667 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305668 (out->is_iec61937_info_available == true)) {
5669 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5670 ret = -EINVAL;
5671 goto exit;
5672 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305673 }
5674 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305675
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005676 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005677 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005678 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5679 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305680 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305681 ret = -EIO;
5682 goto exit;
5683 }
5684 }
5685 }
5686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005688 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005689 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005690 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5691 ret = voice_extn_compress_voip_start_output_stream(out);
5692 else
5693 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005694 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005695 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005697 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005698 goto exit;
5699 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305700 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005701 if (last_known_cal_step != -1) {
5702 ALOGD("%s: retry previous failed cal level set", __func__);
5703 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305704 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005705 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305706
5707 if ((out->is_iec61937_info_available == true) &&
5708 (audio_extn_passthru_is_passthrough_stream(out))&&
5709 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5710 ret = -EINVAL;
5711 goto exit;
5712 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305713 if (out->set_dual_mono)
5714 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005716
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005717 if (adev->is_channel_status_set == false &&
5718 compare_device_type(&out->device_list,
5719 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005720 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305721 adev->is_channel_status_set = true;
5722 }
5723
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305724 if ((adev->use_old_pspd_mix_ctrl == true) &&
5725 (out->pspd_coeff_sent == false)) {
5726 /*
5727 * Need to resend pspd coefficients after stream started for
5728 * older kernel version as it does not save the coefficients
5729 * and also stream has to be started for coeff to apply.
5730 */
5731 usecase = get_usecase_from_list(adev, out->usecase);
5732 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305733 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305734 out->pspd_coeff_sent = true;
5735 }
5736 }
5737
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005738 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005739 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005740 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005741 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005742 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5743 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305744 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5745 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005746 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305747 out->send_next_track_params = false;
5748 out->is_compr_metadata_avail = false;
5749 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005750 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305751 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305752 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005753
Ashish Jain83a6cc22016-06-28 14:34:17 +05305754 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305755 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305756 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305757 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005758 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305759 return -EINVAL;
5760 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305761 audio_format_t dst_format = out->hal_op_format;
5762 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305763
Dieter Luecking5d57def2018-09-07 14:23:37 +02005764 /* prevent division-by-zero */
5765 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5766 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5767 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5768 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305769 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005770 ATRACE_END();
5771 return -EINVAL;
5772 }
5773
Ashish Jainf1eaa582016-05-23 20:54:24 +05305774 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5775 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5776
Ashish Jain83a6cc22016-06-28 14:34:17 +05305777 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305778 dst_format,
5779 buffer,
5780 src_format,
5781 frames);
5782
Ashish Jain83a6cc22016-06-28 14:34:17 +05305783 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305784 bytes_to_write);
5785
5786 /*Convert written bytes in audio flinger format*/
5787 if (ret > 0)
5788 ret = ((ret * format_to_bitwidth_table[out->format]) /
5789 format_to_bitwidth_table[dst_format]);
5790 }
5791 } else
5792 ret = compress_write(out->compr, buffer, bytes);
5793
Zhou Songc9672822017-08-16 16:01:39 +08005794 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5795 update_frames_written(out, bytes);
5796
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305797 if (ret < 0)
5798 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005799 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305800 /*msg to cb thread only if non blocking write is enabled*/
5801 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305802 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005803 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305804 } else if (-ENETRESET == ret) {
5805 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305806 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305807 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305808 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005809 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305810 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005811 }
Ashish Jain5106d362016-05-11 19:23:33 +05305812
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305813 /* Call compr start only when non-zero bytes of data is there to be rendered */
5814 if (!out->playback_started && ret > 0) {
5815 int status = compress_start(out->compr);
5816 if (status < 0) {
5817 ret = status;
5818 ALOGE("%s: compr start failed with err %d", __func__, errno);
5819 goto exit;
5820 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005821 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005822 out->playback_started = 1;
5823 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005824
5825 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5826 popcount(out->channel_mask),
5827 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005828 }
5829 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005830 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005831 return ret;
5832 } else {
5833 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005834 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005835 if (out->muted)
5836 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005837 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5838 __func__, frames, frame_size, bytes_to_write);
5839
Aalique Grahame22e49102018-12-18 14:23:57 -08005840 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005841 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5842 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5843 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005844 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5845 int16_t *src = (int16_t *)buffer;
5846 int16_t *dst = (int16_t *)buffer;
5847
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005848 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005849 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005850 "out_write called for %s use case with wrong properties",
5851 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005852
5853 /*
5854 * FIXME: this can be removed once audio flinger mixer supports
5855 * mono output
5856 */
5857
5858 /*
5859 * Code below goes over each frame in the buffer and adds both
5860 * L and R samples and then divides by 2 to convert to mono
5861 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005862 if (channel_count == 2) {
5863 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5864 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5865 }
5866 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005867 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005868 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305869 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005870
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005871 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005872
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005873 if (out->config.rate)
5874 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5875 out->config.rate;
5876
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005877 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005878 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5879
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005880 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005881 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005882 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305883 out->convert_buffer != NULL) {
5884
5885 memcpy_by_audio_format(out->convert_buffer,
5886 out->hal_op_format,
5887 buffer,
5888 out->hal_ip_format,
5889 out->config.period_size * out->config.channels);
5890
5891 ret = pcm_write(out->pcm, out->convert_buffer,
5892 (out->config.period_size *
5893 out->config.channels *
5894 format_to_bitwidth_table[out->hal_op_format]));
5895 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305896 /*
5897 * To avoid underrun in DSP when the application is not pumping
5898 * data at required rate, check for the no. of bytes and ignore
5899 * pcm_write if it is less than actual buffer size.
5900 * It is a work around to a change in compress VOIP driver.
5901 */
5902 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5903 bytes < (out->config.period_size * out->config.channels *
5904 audio_bytes_per_sample(out->format))) {
5905 size_t voip_buf_size =
5906 out->config.period_size * out->config.channels *
5907 audio_bytes_per_sample(out->format);
5908 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5909 __func__, bytes, voip_buf_size);
5910 usleep(((uint64_t)voip_buf_size - bytes) *
5911 1000000 / audio_stream_out_frame_size(stream) /
5912 out_get_sample_rate(&out->stream.common));
5913 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005914 } else {
5915 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5916 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5917 else
5918 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5919 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305920 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005921
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005922 release_out_focus(out);
5923
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305924 if (ret < 0)
5925 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005926 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305927 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005928 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005929 }
5930
5931exit:
Zhou Songc9672822017-08-16 16:01:39 +08005932 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305933 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305934 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305935 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005936 pthread_mutex_unlock(&out->lock);
5937
5938 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005939 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005940 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305941 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305942 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305943 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305944 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305945 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305946 out->standby = true;
5947 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305948 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005949 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5950 /* prevent division-by-zero */
5951 uint32_t stream_size = audio_stream_out_frame_size(stream);
5952 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005953
Dieter Luecking5d57def2018-09-07 14:23:37 +02005954 if ((stream_size == 0) || (srate == 0)) {
5955 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5956 ATRACE_END();
5957 return -EINVAL;
5958 }
5959 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5960 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005961 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305962 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005963 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005964 return ret;
5965 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005966 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005967 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005968 return bytes;
5969}
5970
5971static int out_get_render_position(const struct audio_stream_out *stream,
5972 uint32_t *dsp_frames)
5973{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005974 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005975
5976 if (dsp_frames == NULL)
5977 return -EINVAL;
5978
5979 *dsp_frames = 0;
5980 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005981 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305982
5983 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5984 * this operation and adev_close_output_stream(where out gets reset).
5985 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305986 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005987 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305988 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005989 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305990 return 0;
5991 }
5992
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005993 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305994 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305995 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005996 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305997 if (ret < 0)
5998 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005999 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306000 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006001 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306002 if (-ENETRESET == ret) {
6003 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306004 out->card_status = CARD_STATUS_OFFLINE;
6005 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306006 } else if(ret < 0) {
6007 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306008 ret = -EINVAL;
6009 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306010 /*
6011 * Handle corner case where compress session is closed during SSR
6012 * and timestamp is queried
6013 */
6014 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306015 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306016 } else if (out->prev_card_status_offline) {
6017 ALOGE("ERROR: previously sound card was offline,return error");
6018 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306019 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306020 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006021 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306022 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306023 pthread_mutex_unlock(&out->lock);
6024 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006025 } else if (audio_is_linear_pcm(out->format)) {
6026 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006027 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006028 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006029 } else
6030 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006031}
6032
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006033static int out_add_audio_effect(const struct audio_stream *stream __unused,
6034 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006035{
6036 return 0;
6037}
6038
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006039static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6040 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006041{
6042 return 0;
6043}
6044
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006045static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6046 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006047{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306048 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006049}
6050
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006051static int out_get_presentation_position(const struct audio_stream_out *stream,
6052 uint64_t *frames, struct timespec *timestamp)
6053{
6054 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306055 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006056 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006057
Ashish Jain5106d362016-05-11 19:23:33 +05306058 /* below piece of code is not guarded against any lock because audioFliner serializes
6059 * this operation and adev_close_output_stream( where out gets reset).
6060 */
6061 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306062 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006063 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306064 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6065 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6066 return 0;
6067 }
6068
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006069 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006070
Ashish Jain5106d362016-05-11 19:23:33 +05306071 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6072 ret = compress_get_tstamp(out->compr, &dsp_frames,
6073 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006074 // Adjustment accounts for A2dp encoder latency with offload usecases
6075 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006076 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006077 unsigned long offset =
6078 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6079 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6080 }
Ashish Jain5106d362016-05-11 19:23:33 +05306081 ALOGVV("%s rendered frames %ld sample_rate %d",
6082 __func__, dsp_frames, out->sample_rate);
6083 *frames = dsp_frames;
6084 if (ret < 0)
6085 ret = -errno;
6086 if (-ENETRESET == ret) {
6087 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306088 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306089 ret = -EINVAL;
6090 } else
6091 ret = 0;
6092 /* this is the best we can do */
6093 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006094 } else {
6095 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006096 unsigned int avail;
6097 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6098 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006099
6100 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006101 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006102
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006103 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6104 if (out->written >= frames_temp)
6105 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006106
Weiyin Jiangd4633762018-03-16 12:05:03 +08006107 // This adjustment accounts for buffering after app processor.
6108 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006109 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6110 if (signed_frames >= frames_temp)
6111 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006112
Weiyin Jiangd4633762018-03-16 12:05:03 +08006113 // Adjustment accounts for A2dp encoder latency with non offload usecases
6114 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006115 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006116 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6117 if (signed_frames >= frames_temp)
6118 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006119 }
6120
6121 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006122 *frames = signed_frames;
6123 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006124 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306125 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306126 *frames = out->written;
6127 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306128 if (is_offload_usecase(out->usecase))
6129 ret = -EINVAL;
6130 else
6131 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006132 }
6133 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006134 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006135 return ret;
6136}
6137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006138static int out_set_callback(struct audio_stream_out *stream,
6139 stream_callback_t callback, void *cookie)
6140{
6141 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006142 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006143
6144 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006145 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006146 out->client_callback = callback;
6147 out->client_cookie = cookie;
6148 if (out->adsp_hdlr_stream_handle) {
6149 ret = audio_extn_adsp_hdlr_stream_set_callback(
6150 out->adsp_hdlr_stream_handle,
6151 callback,
6152 cookie);
6153 if (ret)
6154 ALOGW("%s:adsp hdlr callback registration failed %d",
6155 __func__, ret);
6156 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006157 pthread_mutex_unlock(&out->lock);
6158 return 0;
6159}
6160
6161static int out_pause(struct audio_stream_out* stream)
6162{
6163 struct stream_out *out = (struct stream_out *)stream;
6164 int status = -ENOSYS;
6165 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006166 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006167 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006168 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006169 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306170 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306171 status = compress_pause(out->compr);
6172
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006173 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006174
Mingming Yin21854652016-04-13 11:54:02 -07006175 if (audio_extn_passthru_is_active()) {
6176 ALOGV("offload use case, pause passthru");
6177 audio_extn_passthru_on_pause(out);
6178 }
6179
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306180 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006181 audio_extn_dts_notify_playback_state(out->usecase, 0,
6182 out->sample_rate, popcount(out->channel_mask),
6183 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006184 }
6185 pthread_mutex_unlock(&out->lock);
6186 }
6187 return status;
6188}
6189
6190static int out_resume(struct audio_stream_out* stream)
6191{
6192 struct stream_out *out = (struct stream_out *)stream;
6193 int status = -ENOSYS;
6194 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006195 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006196 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006197 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006198 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006199 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306200 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306201 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006202 }
6203 if (!status) {
6204 out->offload_state = OFFLOAD_STATE_PLAYING;
6205 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306206 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006207 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6208 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006209 }
6210 pthread_mutex_unlock(&out->lock);
6211 }
6212 return status;
6213}
6214
6215static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6216{
6217 struct stream_out *out = (struct stream_out *)stream;
6218 int status = -ENOSYS;
6219 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006220 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006221 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006222 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6223 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6224 else
6225 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6226 pthread_mutex_unlock(&out->lock);
6227 }
6228 return status;
6229}
6230
6231static int out_flush(struct audio_stream_out* stream)
6232{
6233 struct stream_out *out = (struct stream_out *)stream;
6234 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006235 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006236 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006237 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006238 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6239 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006240 } else {
6241 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6242 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006243 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006244 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006245 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006246 return 0;
6247 }
6248 return -ENOSYS;
6249}
6250
Haynes Mathew George16081042017-05-31 17:16:49 -07006251static int out_stop(const struct audio_stream_out* stream)
6252{
6253 struct stream_out *out = (struct stream_out *)stream;
6254 struct audio_device *adev = out->dev;
6255 int ret = -ENOSYS;
6256
6257 ALOGV("%s", __func__);
6258 pthread_mutex_lock(&adev->lock);
6259 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6260 out->playback_started && out->pcm != NULL) {
6261 pcm_stop(out->pcm);
6262 ret = stop_output_stream(out);
6263 out->playback_started = false;
6264 }
6265 pthread_mutex_unlock(&adev->lock);
6266 return ret;
6267}
6268
6269static int out_start(const struct audio_stream_out* stream)
6270{
6271 struct stream_out *out = (struct stream_out *)stream;
6272 struct audio_device *adev = out->dev;
6273 int ret = -ENOSYS;
6274
6275 ALOGV("%s", __func__);
6276 pthread_mutex_lock(&adev->lock);
6277 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6278 !out->playback_started && out->pcm != NULL) {
6279 ret = start_output_stream(out);
6280 if (ret == 0) {
6281 out->playback_started = true;
6282 }
6283 }
6284 pthread_mutex_unlock(&adev->lock);
6285 return ret;
6286}
6287
6288/*
6289 * Modify config->period_count based on min_size_frames
6290 */
6291static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6292{
6293 int periodCountRequested = (min_size_frames + config->period_size - 1)
6294 / config->period_size;
6295 int periodCount = MMAP_PERIOD_COUNT_MIN;
6296
6297 ALOGV("%s original config.period_size = %d config.period_count = %d",
6298 __func__, config->period_size, config->period_count);
6299
6300 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6301 periodCount *= 2;
6302 }
6303 config->period_count = periodCount;
6304
6305 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6306}
6307
Phil Burkfe17efd2019-03-25 10:23:35 -07006308// Read offset for the positional timestamp from a persistent vendor property.
6309// This is to workaround apparent inaccuracies in the timing information that
6310// is used by the AAudio timing model. The inaccuracies can cause glitches.
6311static int64_t get_mmap_out_time_offset() {
6312 const int32_t kDefaultOffsetMicros = 0;
6313 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006314 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006315 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6316 return mmap_time_offset_micros * (int64_t)1000;
6317}
6318
Haynes Mathew George16081042017-05-31 17:16:49 -07006319static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6320 int32_t min_size_frames,
6321 struct audio_mmap_buffer_info *info)
6322{
6323 struct stream_out *out = (struct stream_out *)stream;
6324 struct audio_device *adev = out->dev;
6325 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006326 unsigned int offset1 = 0;
6327 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006328 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006329 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006330 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006331
Arun Mirpuri5d170872019-03-26 13:21:31 -07006332 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306333 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006334 pthread_mutex_lock(&adev->lock);
6335
Sharad Sanglec6f32552018-05-04 16:15:38 +05306336 if (CARD_STATUS_OFFLINE == out->card_status ||
6337 CARD_STATUS_OFFLINE == adev->card_status) {
6338 ALOGW("out->card_status or adev->card_status offline, try again");
6339 ret = -EIO;
6340 goto exit;
6341 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006342 if (info == NULL || min_size_frames == 0) {
6343 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6344 ret = -EINVAL;
6345 goto exit;
6346 }
6347 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6348 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6349 ret = -ENOSYS;
6350 goto exit;
6351 }
6352 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6353 if (out->pcm_device_id < 0) {
6354 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6355 __func__, out->pcm_device_id, out->usecase);
6356 ret = -EINVAL;
6357 goto exit;
6358 }
6359
6360 adjust_mmap_period_count(&out->config, min_size_frames);
6361
Arun Mirpuri5d170872019-03-26 13:21:31 -07006362 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006363 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6364 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6365 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306366 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306367 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6368 out->card_status = CARD_STATUS_OFFLINE;
6369 adev->card_status = CARD_STATUS_OFFLINE;
6370 ret = -EIO;
6371 goto exit;
6372 }
6373
Haynes Mathew George16081042017-05-31 17:16:49 -07006374 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6375 step = "open";
6376 ret = -ENODEV;
6377 goto exit;
6378 }
6379 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6380 if (ret < 0) {
6381 step = "begin";
6382 goto exit;
6383 }
6384 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006385 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006386 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006387 ret = platform_get_mmap_data_fd(adev->platform,
6388 out->pcm_device_id, 0 /*playback*/,
6389 &info->shared_memory_fd,
6390 &mmap_size);
6391 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006392 // Fall back to non exclusive mode
6393 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6394 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006395 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6396 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6397
Arun Mirpuri5d170872019-03-26 13:21:31 -07006398 if (mmap_size < buffer_size) {
6399 step = "mmap";
6400 goto exit;
6401 }
6402 // FIXME: indicate exclusive mode support by returning a negative buffer size
6403 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006404 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006405 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006406 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006407
6408 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6409 if (ret < 0) {
6410 step = "commit";
6411 goto exit;
6412 }
6413
Phil Burkfe17efd2019-03-25 10:23:35 -07006414 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6415
Haynes Mathew George16081042017-05-31 17:16:49 -07006416 out->standby = false;
6417 ret = 0;
6418
Arun Mirpuri5d170872019-03-26 13:21:31 -07006419 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006420 __func__, info->shared_memory_address, info->buffer_size_frames);
6421
6422exit:
6423 if (ret != 0) {
6424 if (out->pcm == NULL) {
6425 ALOGE("%s: %s - %d", __func__, step, ret);
6426 } else {
6427 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6428 pcm_close(out->pcm);
6429 out->pcm = NULL;
6430 }
6431 }
6432 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306433 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006434 return ret;
6435}
6436
6437static int out_get_mmap_position(const struct audio_stream_out *stream,
6438 struct audio_mmap_position *position)
6439{
6440 struct stream_out *out = (struct stream_out *)stream;
6441 ALOGVV("%s", __func__);
6442 if (position == NULL) {
6443 return -EINVAL;
6444 }
6445 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006446 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006447 return -ENOSYS;
6448 }
6449 if (out->pcm == NULL) {
6450 return -ENOSYS;
6451 }
6452
6453 struct timespec ts = { 0, 0 };
6454 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6455 if (ret < 0) {
6456 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6457 return ret;
6458 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006459 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6460 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006461 return 0;
6462}
6463
6464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006465/** audio_stream_in implementation **/
6466static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6467{
6468 struct stream_in *in = (struct stream_in *)stream;
6469
6470 return in->config.rate;
6471}
6472
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006473static int in_set_sample_rate(struct audio_stream *stream __unused,
6474 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006475{
6476 return -ENOSYS;
6477}
6478
6479static size_t in_get_buffer_size(const struct audio_stream *stream)
6480{
6481 struct stream_in *in = (struct stream_in *)stream;
6482
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006483 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6484 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006485 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6486 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306487 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306488 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006489
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006490 return in->config.period_size * in->af_period_multiplier *
6491 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006492}
6493
6494static uint32_t in_get_channels(const struct audio_stream *stream)
6495{
6496 struct stream_in *in = (struct stream_in *)stream;
6497
6498 return in->channel_mask;
6499}
6500
6501static audio_format_t in_get_format(const struct audio_stream *stream)
6502{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006503 struct stream_in *in = (struct stream_in *)stream;
6504
6505 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006506}
6507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006508static int in_set_format(struct audio_stream *stream __unused,
6509 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006510{
6511 return -ENOSYS;
6512}
6513
6514static int in_standby(struct audio_stream *stream)
6515{
6516 struct stream_in *in = (struct stream_in *)stream;
6517 struct audio_device *adev = in->dev;
6518 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306519 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6520 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006521 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306522
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006523 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006524 if (!in->standby && in->is_st_session) {
6525 ALOGD("%s: sound trigger pcm stop lab", __func__);
6526 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006527 if (adev->num_va_sessions > 0)
6528 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006529 in->standby = 1;
6530 }
6531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006532 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006533 if (adev->adm_deregister_stream)
6534 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6535
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006536 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006537 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006538 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006539 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006540 voice_extn_compress_voip_close_input_stream(stream);
6541 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006542 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6543 do_stop = in->capture_started;
6544 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006545 if (in->mmap_shared_memory_fd >= 0) {
6546 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6547 __func__, in->mmap_shared_memory_fd);
6548 close(in->mmap_shared_memory_fd);
6549 in->mmap_shared_memory_fd = -1;
6550 }
Zhou Songa8895042016-07-05 17:54:22 +08006551 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306552 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306553 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006554 }
6555
Arun Mirpuri5d170872019-03-26 13:21:31 -07006556 if (in->pcm) {
6557 ATRACE_BEGIN("pcm_in_close");
6558 pcm_close(in->pcm);
6559 ATRACE_END();
6560 in->pcm = NULL;
6561 }
6562
Carter Hsu2e429db2019-05-14 18:50:52 +08006563 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006564 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006565
George Gao3018ede2019-10-23 13:23:00 -07006566 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6567 if (adev->num_va_sessions > 0)
6568 adev->num_va_sessions--;
6569 }
Quinn Malef6050362019-01-30 15:55:40 -08006570
Eric Laurent150dbfe2013-02-27 14:31:02 -08006571 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006572 }
6573 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006574 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006575 return status;
6576}
6577
Aalique Grahame22e49102018-12-18 14:23:57 -08006578static int in_dump(const struct audio_stream *stream,
6579 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006580{
Aalique Grahame22e49102018-12-18 14:23:57 -08006581 struct stream_in *in = (struct stream_in *)stream;
6582
6583 // We try to get the lock for consistency,
6584 // but it isn't necessary for these variables.
6585 // If we're not in standby, we may be blocked on a read.
6586 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6587 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6588 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6589 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6590
6591 if (locked) {
6592 pthread_mutex_unlock(&in->lock);
6593 }
6594
6595 // dump error info
6596 (void)error_log_dump(
6597 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006599 return 0;
6600}
6601
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306602static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6603{
6604 if (!stream || !parms)
6605 return;
6606
6607 struct stream_in *in = (struct stream_in *)stream;
6608 struct audio_device *adev = in->dev;
6609
6610 card_status_t status;
6611 int card;
6612 if (parse_snd_card_status(parms, &card, &status) < 0)
6613 return;
6614
6615 pthread_mutex_lock(&adev->lock);
6616 bool valid_cb = (card == adev->snd_card);
6617 pthread_mutex_unlock(&adev->lock);
6618
6619 if (!valid_cb)
6620 return;
6621
6622 lock_input_stream(in);
6623 if (in->card_status != status)
6624 in->card_status = status;
6625 pthread_mutex_unlock(&in->lock);
6626
6627 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6628 use_case_table[in->usecase],
6629 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6630
6631 // a better solution would be to report error back to AF and let
6632 // it put the stream to standby
6633 if (status == CARD_STATUS_OFFLINE)
6634 in_standby(&in->stream.common);
6635
6636 return;
6637}
6638
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006639int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006640 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006641 audio_source_t source)
6642{
6643 struct audio_device *adev = in->dev;
6644 int ret = 0;
6645
6646 lock_input_stream(in);
6647 pthread_mutex_lock(&adev->lock);
6648
6649 /* no audio source uses val == 0 */
6650 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6651 in->source = source;
6652 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6653 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6654 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6655 (in->config.rate == 8000 || in->config.rate == 16000 ||
6656 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6657 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6658 ret = voice_extn_compress_voip_open_input_stream(in);
6659 if (ret != 0) {
6660 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6661 __func__, ret);
6662 }
6663 }
6664 }
6665
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006666 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6667 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006668 // Workaround: If routing to an non existing usb device, fail gracefully
6669 // The routing request will otherwise block during 10 second
6670 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006671 struct str_parms *usb_addr =
6672 str_parms_create_str(get_usb_device_address(devices));
6673 if (is_usb_in_device_type(devices) && usb_addr &&
6674 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006675 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6676 ret = -ENOSYS;
6677 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006678 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006679 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006680 if (!in->standby && !in->is_st_session) {
6681 ALOGV("update input routing change");
6682 // inform adm before actual routing to prevent glitches.
6683 if (adev->adm_on_routing_change) {
6684 adev->adm_on_routing_change(adev->adm_data,
6685 in->capture_handle);
6686 ret = select_devices(adev, in->usecase);
6687 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6688 adev->adm_routing_changed = true;
6689 }
6690 }
6691 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006692 if (usb_addr)
6693 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006694 }
6695 pthread_mutex_unlock(&adev->lock);
6696 pthread_mutex_unlock(&in->lock);
6697
6698 ALOGD("%s: exit: status(%d)", __func__, ret);
6699 return ret;
6700}
6701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006702static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6703{
6704 struct stream_in *in = (struct stream_in *)stream;
6705 struct audio_device *adev = in->dev;
6706 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006707 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006708 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306710 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711 parms = str_parms_create_str(kvpairs);
6712
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306713 if (!parms)
6714 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006715 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006716 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006717
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006718 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6719 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306720 strlcpy(in->profile, value, sizeof(in->profile));
6721 ALOGV("updating stream profile with value '%s'", in->profile);
6722 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6723 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006724 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306725 in->sample_rate, in->bit_width,
6726 in->profile, &in->app_type_cfg);
6727 }
6728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006729 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006730 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006731
6732 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306733error:
Eric Laurent994a6932013-07-17 11:51:42 -07006734 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006735 return ret;
6736}
6737
6738static char* in_get_parameters(const struct audio_stream *stream,
6739 const char *keys)
6740{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006741 struct stream_in *in = (struct stream_in *)stream;
6742 struct str_parms *query = str_parms_create_str(keys);
6743 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006744 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006745
6746 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006747 if (reply) {
6748 str_parms_destroy(reply);
6749 }
6750 if (query) {
6751 str_parms_destroy(query);
6752 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006753 ALOGE("in_get_parameters: failed to create query or reply");
6754 return NULL;
6755 }
6756
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006757 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006758
6759 voice_extn_in_get_parameters(in, query, reply);
6760
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006761 stream_get_parameter_channels(query, reply,
6762 &in->supported_channel_masks[0]);
6763 stream_get_parameter_formats(query, reply,
6764 &in->supported_formats[0]);
6765 stream_get_parameter_rates(query, reply,
6766 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006767 str = str_parms_to_str(reply);
6768 str_parms_destroy(query);
6769 str_parms_destroy(reply);
6770
6771 ALOGV("%s: exit: returns - %s", __func__, str);
6772 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006773}
6774
Aalique Grahame22e49102018-12-18 14:23:57 -08006775static int in_set_gain(struct audio_stream_in *stream,
6776 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006777{
Aalique Grahame22e49102018-12-18 14:23:57 -08006778 struct stream_in *in = (struct stream_in *)stream;
6779 char mixer_ctl_name[128];
6780 struct mixer_ctl *ctl;
6781 int ctl_value;
6782
6783 ALOGV("%s: gain %f", __func__, gain);
6784
6785 if (stream == NULL)
6786 return -EINVAL;
6787
6788 /* in_set_gain() only used to silence MMAP capture for now */
6789 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6790 return -ENOSYS;
6791
6792 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6793
6794 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6795 if (!ctl) {
6796 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6797 __func__, mixer_ctl_name);
6798 return -ENOSYS;
6799 }
6800
6801 if (gain < RECORD_GAIN_MIN)
6802 gain = RECORD_GAIN_MIN;
6803 else if (gain > RECORD_GAIN_MAX)
6804 gain = RECORD_GAIN_MAX;
6805 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6806
6807 mixer_ctl_set_value(ctl, 0, ctl_value);
6808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006809 return 0;
6810}
6811
6812static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6813 size_t bytes)
6814{
6815 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306816
6817 if (in == NULL) {
6818 ALOGE("%s: stream_in ptr is NULL", __func__);
6819 return -EINVAL;
6820 }
6821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006822 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306823 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306824 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006825
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006826 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306827
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006828 if (in->is_st_session) {
6829 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6830 /* Read from sound trigger HAL */
6831 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006832 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006833 if (adev->num_va_sessions < UINT_MAX)
6834 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006835 in->standby = 0;
6836 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006837 pthread_mutex_unlock(&in->lock);
6838 return bytes;
6839 }
6840
Haynes Mathew George16081042017-05-31 17:16:49 -07006841 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6842 ret = -ENOSYS;
6843 goto exit;
6844 }
6845
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006846 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6847 !in->standby && adev->adm_routing_changed) {
6848 ret = -ENOSYS;
6849 goto exit;
6850 }
6851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006853 pthread_mutex_lock(&adev->lock);
6854 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6855 ret = voice_extn_compress_voip_start_input_stream(in);
6856 else
6857 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006858 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6859 if (adev->num_va_sessions < UINT_MAX)
6860 adev->num_va_sessions++;
6861 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006862 pthread_mutex_unlock(&adev->lock);
6863 if (ret != 0) {
6864 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006865 }
6866 in->standby = 0;
6867 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306869 /* Avoid read if capture_stopped is set */
6870 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6871 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6872 ret = -EINVAL;
6873 goto exit;
6874 }
6875
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006876 // what's the duration requested by the client?
6877 long ns = 0;
6878
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306879 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006880 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6881 in->config.rate;
6882
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006883 ret = request_in_focus(in, ns);
6884 if (ret != 0)
6885 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006886 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006887
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306888 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306889 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6890 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306891 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006892 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306893 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006894 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006895 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006896 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006897 } else if (audio_extn_ffv_get_stream() == in) {
6898 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306899 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006900 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306901 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6902 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6903 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6904 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306905 ret = -EINVAL;
6906 goto exit;
6907 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306908 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306909 ret = -errno;
6910 }
6911 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306912 /* bytes read is always set to bytes for non compress usecases */
6913 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006914 }
6915
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006916 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006918 /*
Quinn Malef6050362019-01-30 15:55:40 -08006919 * Instead of writing zeroes here, we could trust the hardware to always
6920 * provide zeroes when muted. This is also muted with voice recognition
6921 * usecases so that other clients do not have access to voice recognition
6922 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006923 */
Quinn Malef6050362019-01-30 15:55:40 -08006924 if ((ret == 0 && voice_get_mic_mute(adev) &&
6925 !voice_is_in_call_rec_stream(in) &&
6926 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6927 (adev->num_va_sessions &&
6928 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6929 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6930 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006931 memset(buffer, 0, bytes);
6932
6933exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306934 frame_size = audio_stream_in_frame_size(stream);
6935 if (frame_size > 0)
6936 in->frames_read += bytes_read/frame_size;
6937
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006938 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306939 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006940 pthread_mutex_unlock(&in->lock);
6941
6942 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306943 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306944 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306945 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306946 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306947 in->standby = true;
6948 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306949 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05306950 bytes_read = bytes;
6951 memset(buffer, 0, bytes);
6952 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006953 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006954 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6955 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006956 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306957 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306958 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006959 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306960 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961}
6962
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006963static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006964{
6965 return 0;
6966}
6967
Aalique Grahame22e49102018-12-18 14:23:57 -08006968static int in_get_capture_position(const struct audio_stream_in *stream,
6969 int64_t *frames, int64_t *time)
6970{
6971 if (stream == NULL || frames == NULL || time == NULL) {
6972 return -EINVAL;
6973 }
6974 struct stream_in *in = (struct stream_in *)stream;
6975 int ret = -ENOSYS;
6976
6977 lock_input_stream(in);
6978 // note: ST sessions do not close the alsa pcm driver synchronously
6979 // on standby. Therefore, we may return an error even though the
6980 // pcm stream is still opened.
6981 if (in->standby) {
6982 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6983 "%s stream in standby but pcm not NULL for non ST session", __func__);
6984 goto exit;
6985 }
6986 if (in->pcm) {
6987 struct timespec timestamp;
6988 unsigned int avail;
6989 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6990 *frames = in->frames_read + avail;
6991 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6992 ret = 0;
6993 }
6994 }
6995exit:
6996 pthread_mutex_unlock(&in->lock);
6997 return ret;
6998}
6999
Carter Hsu2e429db2019-05-14 18:50:52 +08007000static int in_update_effect_list(bool add, effect_handle_t effect,
7001 struct listnode *head)
7002{
7003 struct listnode *node;
7004 struct in_effect_list *elist = NULL;
7005 struct in_effect_list *target = NULL;
7006 int ret = 0;
7007
7008 if (!head)
7009 return ret;
7010
7011 list_for_each(node, head) {
7012 elist = node_to_item(node, struct in_effect_list, list);
7013 if (elist->handle == effect) {
7014 target = elist;
7015 break;
7016 }
7017 }
7018
7019 if (add) {
7020 if (target) {
7021 ALOGD("effect %p already exist", effect);
7022 return ret;
7023 }
7024
7025 target = (struct in_effect_list *)
7026 calloc(1, sizeof(struct in_effect_list));
7027
7028 if (!target) {
7029 ALOGE("%s:fail to allocate memory", __func__);
7030 return -ENOMEM;
7031 }
7032
7033 target->handle = effect;
7034 list_add_tail(head, &target->list);
7035 } else {
7036 if (target) {
7037 list_remove(&target->list);
7038 free(target);
7039 }
7040 }
7041
7042 return ret;
7043}
7044
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007045static int add_remove_audio_effect(const struct audio_stream *stream,
7046 effect_handle_t effect,
7047 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007048{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007049 struct stream_in *in = (struct stream_in *)stream;
7050 int status = 0;
7051 effect_descriptor_t desc;
7052
7053 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007054 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7055
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007056 if (status != 0)
7057 return status;
7058
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007059 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007060 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007061 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007062 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7063 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007064 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007065
7066 in_update_effect_list(enable, effect, &in->aec_list);
7067 enable = !list_empty(&in->aec_list);
7068 if (enable == in->enable_aec)
7069 goto exit;
7070
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007071 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007072 ALOGD("AEC enable %d", enable);
7073
Aalique Grahame22e49102018-12-18 14:23:57 -08007074 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7075 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7076 in->dev->enable_voicerx = enable;
7077 struct audio_usecase *usecase;
7078 struct listnode *node;
7079 list_for_each(node, &in->dev->usecase_list) {
7080 usecase = node_to_item(node, struct audio_usecase, list);
7081 if (usecase->type == PCM_PLAYBACK)
7082 select_devices(in->dev, usecase->id);
7083 }
7084 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007085 if (!in->standby) {
7086 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7087 select_devices(in->dev, in->usecase);
7088 }
7089
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007090 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007091 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7092
7093 in_update_effect_list(enable, effect, &in->ns_list);
7094 enable = !list_empty(&in->ns_list);
7095 if (enable == in->enable_ns)
7096 goto exit;
7097
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007098 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007099 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007100 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007101 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7102 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007103 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7104 select_devices(in->dev, in->usecase);
7105 } else
7106 select_devices(in->dev, in->usecase);
7107 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007108 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007109exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007110 pthread_mutex_unlock(&in->dev->lock);
7111 pthread_mutex_unlock(&in->lock);
7112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113 return 0;
7114}
7115
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007116static int in_add_audio_effect(const struct audio_stream *stream,
7117 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007118{
Eric Laurent994a6932013-07-17 11:51:42 -07007119 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007120 return add_remove_audio_effect(stream, effect, true);
7121}
7122
7123static int in_remove_audio_effect(const struct audio_stream *stream,
7124 effect_handle_t effect)
7125{
Eric Laurent994a6932013-07-17 11:51:42 -07007126 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007127 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007128}
7129
Derek Chenf939fb72018-11-13 13:34:41 -08007130streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7131 audio_io_handle_t input)
7132{
7133 struct listnode *node;
7134
7135 list_for_each(node, &dev->active_inputs_list) {
7136 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7137 streams_input_ctxt_t,
7138 list);
7139 if (in_ctxt->input->capture_handle == input) {
7140 return in_ctxt;
7141 }
7142 }
7143 return NULL;
7144}
7145
7146streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7147 audio_io_handle_t output)
7148{
7149 struct listnode *node;
7150
7151 list_for_each(node, &dev->active_outputs_list) {
7152 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7153 streams_output_ctxt_t,
7154 list);
7155 if (out_ctxt->output->handle == output) {
7156 return out_ctxt;
7157 }
7158 }
7159 return NULL;
7160}
7161
Haynes Mathew George16081042017-05-31 17:16:49 -07007162static int in_stop(const struct audio_stream_in* stream)
7163{
7164 struct stream_in *in = (struct stream_in *)stream;
7165 struct audio_device *adev = in->dev;
7166
7167 int ret = -ENOSYS;
7168 ALOGV("%s", __func__);
7169 pthread_mutex_lock(&adev->lock);
7170 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7171 in->capture_started && in->pcm != NULL) {
7172 pcm_stop(in->pcm);
7173 ret = stop_input_stream(in);
7174 in->capture_started = false;
7175 }
7176 pthread_mutex_unlock(&adev->lock);
7177 return ret;
7178}
7179
7180static int in_start(const struct audio_stream_in* stream)
7181{
7182 struct stream_in *in = (struct stream_in *)stream;
7183 struct audio_device *adev = in->dev;
7184 int ret = -ENOSYS;
7185
7186 ALOGV("%s in %p", __func__, in);
7187 pthread_mutex_lock(&adev->lock);
7188 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7189 !in->capture_started && in->pcm != NULL) {
7190 if (!in->capture_started) {
7191 ret = start_input_stream(in);
7192 if (ret == 0) {
7193 in->capture_started = true;
7194 }
7195 }
7196 }
7197 pthread_mutex_unlock(&adev->lock);
7198 return ret;
7199}
7200
Phil Burke0a86d12019-02-16 22:28:11 -08007201// Read offset for the positional timestamp from a persistent vendor property.
7202// This is to workaround apparent inaccuracies in the timing information that
7203// is used by the AAudio timing model. The inaccuracies can cause glitches.
7204static int64_t in_get_mmap_time_offset() {
7205 const int32_t kDefaultOffsetMicros = 0;
7206 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007207 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007208 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7209 return mmap_time_offset_micros * (int64_t)1000;
7210}
7211
Haynes Mathew George16081042017-05-31 17:16:49 -07007212static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7213 int32_t min_size_frames,
7214 struct audio_mmap_buffer_info *info)
7215{
7216 struct stream_in *in = (struct stream_in *)stream;
7217 struct audio_device *adev = in->dev;
7218 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007219 unsigned int offset1 = 0;
7220 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007221 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007222 uint32_t mmap_size = 0;
7223 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007224
7225 pthread_mutex_lock(&adev->lock);
7226 ALOGV("%s in %p", __func__, in);
7227
Sharad Sanglec6f32552018-05-04 16:15:38 +05307228 if (CARD_STATUS_OFFLINE == in->card_status||
7229 CARD_STATUS_OFFLINE == adev->card_status) {
7230 ALOGW("in->card_status or adev->card_status offline, try again");
7231 ret = -EIO;
7232 goto exit;
7233 }
7234
Haynes Mathew George16081042017-05-31 17:16:49 -07007235 if (info == NULL || min_size_frames == 0) {
7236 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7237 ret = -EINVAL;
7238 goto exit;
7239 }
7240 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7241 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7242 ALOGV("%s in %p", __func__, in);
7243 ret = -ENOSYS;
7244 goto exit;
7245 }
7246 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7247 if (in->pcm_device_id < 0) {
7248 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7249 __func__, in->pcm_device_id, in->usecase);
7250 ret = -EINVAL;
7251 goto exit;
7252 }
7253
7254 adjust_mmap_period_count(&in->config, min_size_frames);
7255
7256 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7257 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7258 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7259 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307260 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307261 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7262 in->card_status = CARD_STATUS_OFFLINE;
7263 adev->card_status = CARD_STATUS_OFFLINE;
7264 ret = -EIO;
7265 goto exit;
7266 }
7267
Haynes Mathew George16081042017-05-31 17:16:49 -07007268 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7269 step = "open";
7270 ret = -ENODEV;
7271 goto exit;
7272 }
7273
7274 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7275 if (ret < 0) {
7276 step = "begin";
7277 goto exit;
7278 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007279
Arun Mirpuri5d170872019-03-26 13:21:31 -07007280 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7281 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7282 info->burst_size_frames = in->config.period_size;
7283 ret = platform_get_mmap_data_fd(adev->platform,
7284 in->pcm_device_id, 1 /*capture*/,
7285 &info->shared_memory_fd,
7286 &mmap_size);
7287 if (ret < 0) {
7288 // Fall back to non exclusive mode
7289 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7290 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007291 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7292 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7293
Arun Mirpuri5d170872019-03-26 13:21:31 -07007294 if (mmap_size < buffer_size) {
7295 step = "mmap";
7296 goto exit;
7297 }
7298 // FIXME: indicate exclusive mode support by returning a negative buffer size
7299 info->buffer_size_frames *= -1;
7300 }
7301
7302 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007303
7304 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7305 if (ret < 0) {
7306 step = "commit";
7307 goto exit;
7308 }
7309
Phil Burke0a86d12019-02-16 22:28:11 -08007310 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7311
Haynes Mathew George16081042017-05-31 17:16:49 -07007312 in->standby = false;
7313 ret = 0;
7314
7315 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7316 __func__, info->shared_memory_address, info->buffer_size_frames);
7317
7318exit:
7319 if (ret != 0) {
7320 if (in->pcm == NULL) {
7321 ALOGE("%s: %s - %d", __func__, step, ret);
7322 } else {
7323 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7324 pcm_close(in->pcm);
7325 in->pcm = NULL;
7326 }
7327 }
7328 pthread_mutex_unlock(&adev->lock);
7329 return ret;
7330}
7331
7332static int in_get_mmap_position(const struct audio_stream_in *stream,
7333 struct audio_mmap_position *position)
7334{
7335 struct stream_in *in = (struct stream_in *)stream;
7336 ALOGVV("%s", __func__);
7337 if (position == NULL) {
7338 return -EINVAL;
7339 }
7340 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7341 return -ENOSYS;
7342 }
7343 if (in->pcm == NULL) {
7344 return -ENOSYS;
7345 }
7346 struct timespec ts = { 0, 0 };
7347 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7348 if (ret < 0) {
7349 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7350 return ret;
7351 }
Phil Burke0a86d12019-02-16 22:28:11 -08007352 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7353 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007354 return 0;
7355}
7356
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307357static int in_get_active_microphones(const struct audio_stream_in *stream,
7358 struct audio_microphone_characteristic_t *mic_array,
7359 size_t *mic_count) {
7360 struct stream_in *in = (struct stream_in *)stream;
7361 struct audio_device *adev = in->dev;
7362 ALOGVV("%s", __func__);
7363
7364 lock_input_stream(in);
7365 pthread_mutex_lock(&adev->lock);
7366 int ret = platform_get_active_microphones(adev->platform,
7367 audio_channel_count_from_in_mask(in->channel_mask),
7368 in->usecase, mic_array, mic_count);
7369 pthread_mutex_unlock(&adev->lock);
7370 pthread_mutex_unlock(&in->lock);
7371
7372 return ret;
7373}
7374
7375static int adev_get_microphones(const struct audio_hw_device *dev,
7376 struct audio_microphone_characteristic_t *mic_array,
7377 size_t *mic_count) {
7378 struct audio_device *adev = (struct audio_device *)dev;
7379 ALOGVV("%s", __func__);
7380
7381 pthread_mutex_lock(&adev->lock);
7382 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7383 pthread_mutex_unlock(&adev->lock);
7384
7385 return ret;
7386}
juyuchendb308c22019-01-21 11:57:17 -07007387
7388static void in_update_sink_metadata(struct audio_stream_in *stream,
7389 const struct sink_metadata *sink_metadata) {
7390
7391 if (stream == NULL
7392 || sink_metadata == NULL
7393 || sink_metadata->tracks == NULL) {
7394 return;
7395 }
7396
7397 int error = 0;
7398 struct stream_in *in = (struct stream_in *)stream;
7399 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007400 struct listnode devices;
7401
7402 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007403
7404 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007405 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007406
7407 lock_input_stream(in);
7408 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007409 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007410
7411 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007412 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007413 && adev->voice_tx_output != NULL) {
7414 /* Use the rx device from afe-proxy record to route voice call because
7415 there is no routing if tx device is on primary hal and rx device
7416 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007417 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007418
7419 if (!voice_is_call_state_active(adev)) {
7420 if (adev->mode == AUDIO_MODE_IN_CALL) {
7421 adev->current_call_output = adev->voice_tx_output;
7422 error = voice_start_call(adev);
7423 if (error != 0)
7424 ALOGE("%s: start voice call failed %d", __func__, error);
7425 }
7426 } else {
7427 adev->current_call_output = adev->voice_tx_output;
7428 voice_update_devices_for_all_voice_usecases(adev);
7429 }
7430 }
7431
7432 pthread_mutex_unlock(&adev->lock);
7433 pthread_mutex_unlock(&in->lock);
7434}
7435
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307436int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007437 audio_io_handle_t handle,
7438 audio_devices_t devices,
7439 audio_output_flags_t flags,
7440 struct audio_config *config,
7441 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007442 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007443{
7444 struct audio_device *adev = (struct audio_device *)dev;
7445 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307446 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007447 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007448 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307449 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007450 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7451 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7452 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7453 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007454 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007455 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7456 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007457 bool force_haptic_path =
7458 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007459 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007460
kunleizdff872d2018-08-20 14:40:33 +08007461 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007462 is_usb_dev = false;
7463 devices = AUDIO_DEVICE_OUT_SPEAKER;
7464 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7465 __func__, devices);
7466 }
7467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007468 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307469
Rahul Sharma99770982019-03-06 17:05:26 +05307470 pthread_mutex_lock(&adev->lock);
7471 if (out_get_stream(adev, handle) != NULL) {
7472 ALOGW("%s, output stream already opened", __func__);
7473 ret = -EEXIST;
7474 }
7475 pthread_mutex_unlock(&adev->lock);
7476 if (ret)
7477 return ret;
7478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007479 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7480
Mingming Yin3a941d42016-02-17 18:08:05 -08007481 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007482 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7483 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307484
7485
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007486 if (!out) {
7487 return -ENOMEM;
7488 }
7489
Haynes Mathew George204045b2015-02-25 20:32:03 -08007490 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007491 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307492 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007493 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007494 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007496 if (devices == AUDIO_DEVICE_NONE)
7497 devices = AUDIO_DEVICE_OUT_SPEAKER;
7498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007499 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007500 list_init(&out->device_list);
7501 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007502 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007503 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007504 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307505 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307506 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7507 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7508 else
7509 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007510 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007511 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007512 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307513 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307514 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307515 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007516 out->hal_output_suspend_supported = 0;
7517 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307518 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307519 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307520 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007521 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007522
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307523 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307524 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007525 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7526
Aalique Grahame22e49102018-12-18 14:23:57 -08007527 if (direct_dev &&
7528 (audio_is_linear_pcm(out->format) ||
7529 config->format == AUDIO_FORMAT_DEFAULT) &&
7530 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7531 audio_format_t req_format = config->format;
7532 audio_channel_mask_t req_channel_mask = config->channel_mask;
7533 uint32_t req_sample_rate = config->sample_rate;
7534
7535 pthread_mutex_lock(&adev->lock);
7536 if (is_hdmi) {
7537 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7538 ret = read_hdmi_sink_caps(out);
7539 if (config->sample_rate == 0)
7540 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7541 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7542 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7543 if (config->format == AUDIO_FORMAT_DEFAULT)
7544 config->format = AUDIO_FORMAT_PCM_16_BIT;
7545 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007546 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7547 &config->format,
7548 &out->supported_formats[0],
7549 MAX_SUPPORTED_FORMATS,
7550 &config->channel_mask,
7551 &out->supported_channel_masks[0],
7552 MAX_SUPPORTED_CHANNEL_MASKS,
7553 &config->sample_rate,
7554 &out->supported_sample_rates[0],
7555 MAX_SUPPORTED_SAMPLE_RATES);
7556 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007557 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007558
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007559 pthread_mutex_unlock(&adev->lock);
7560 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007561 if (ret == -ENOSYS) {
7562 /* ignore and go with default */
7563 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007564 }
7565 // For MMAP NO IRQ, allow conversions in ADSP
7566 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7567 goto error_open;
7568 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007569 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007570 goto error_open;
7571 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007572
7573 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7574 config->sample_rate = req_sample_rate;
7575 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7576 config->channel_mask = req_channel_mask;
7577 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7578 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007579 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007580
7581 out->sample_rate = config->sample_rate;
7582 out->channel_mask = config->channel_mask;
7583 out->format = config->format;
7584 if (is_hdmi) {
7585 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7586 out->config = pcm_config_hdmi_multi;
7587 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7588 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7589 out->config = pcm_config_mmap_playback;
7590 out->stream.start = out_start;
7591 out->stream.stop = out_stop;
7592 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7593 out->stream.get_mmap_position = out_get_mmap_position;
7594 } else {
7595 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7596 out->config = pcm_config_hifi;
7597 }
7598
7599 out->config.rate = out->sample_rate;
7600 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7601 if (is_hdmi) {
7602 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7603 audio_bytes_per_sample(out->format));
7604 }
7605 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007606 }
7607
Derek Chenf6318be2017-06-12 17:16:24 -04007608 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007609 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007610 /* extract car audio stream index */
7611 out->car_audio_stream =
7612 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7613 if (out->car_audio_stream < 0) {
7614 ALOGE("%s: invalid car audio stream %x",
7615 __func__, out->car_audio_stream);
7616 ret = -EINVAL;
7617 goto error_open;
7618 }
Derek Chen5f67a942020-02-24 23:08:13 -08007619 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007620 }
7621
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007622 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007623 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007624 if (!voice_extn_is_compress_voip_supported()) {
7625 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7626 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007627 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7628 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007629 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7630 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007631 out->volume_l = INVALID_OUT_VOLUME;
7632 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007633
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007634 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007635 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007636 uint32_t channel_count =
7637 audio_channel_count_from_out_mask(out->channel_mask);
7638 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7639 out->sample_rate, out->format,
7640 channel_count, false);
7641 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7642 if (frame_size != 0)
7643 out->config.period_size = buffer_size / frame_size;
7644 else
7645 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007646 }
7647 } else {
7648 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7649 voice_extn_compress_voip_is_active(out->dev)) &&
7650 (voice_extn_compress_voip_is_config_supported(config))) {
7651 ret = voice_extn_compress_voip_open_output_stream(out);
7652 if (ret != 0) {
7653 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7654 __func__, ret);
7655 goto error_open;
7656 }
Sujin Panicker19027262019-09-16 18:28:06 +05307657 } else {
7658 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7659 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007660 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007661 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007662 } else if (audio_is_linear_pcm(out->format) &&
7663 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7664 out->channel_mask = config->channel_mask;
7665 out->sample_rate = config->sample_rate;
7666 out->format = config->format;
7667 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7668 // does this change?
7669 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7670 out->config.rate = config->sample_rate;
7671 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7672 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7673 audio_bytes_per_sample(config->format));
7674 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007675 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307676 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307677 pthread_mutex_lock(&adev->lock);
7678 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7679 pthread_mutex_unlock(&adev->lock);
7680
7681 // reject offload during card offline to allow
7682 // fallback to s/w paths
7683 if (offline) {
7684 ret = -ENODEV;
7685 goto error_open;
7686 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007687
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007688 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7689 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7690 ALOGE("%s: Unsupported Offload information", __func__);
7691 ret = -EINVAL;
7692 goto error_open;
7693 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007694
Atul Khare3fa6e542017-08-09 00:56:17 +05307695 if (config->offload_info.format == 0)
7696 config->offload_info.format = config->format;
7697 if (config->offload_info.sample_rate == 0)
7698 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007699
Mingming Yin90310102013-11-13 16:57:00 -08007700 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307701 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007702 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007703 ret = -EINVAL;
7704 goto error_open;
7705 }
7706
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007707 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7708 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7709 (audio_extn_passthru_is_passthrough_stream(out)) &&
7710 !((config->sample_rate == 48000) ||
7711 (config->sample_rate == 96000) ||
7712 (config->sample_rate == 192000))) {
7713 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7714 __func__, config->sample_rate, config->offload_info.format);
7715 ret = -EINVAL;
7716 goto error_open;
7717 }
7718
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007719 out->compr_config.codec = (struct snd_codec *)
7720 calloc(1, sizeof(struct snd_codec));
7721
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007722 if (!out->compr_config.codec) {
7723 ret = -ENOMEM;
7724 goto error_open;
7725 }
7726
Dhananjay Kumarac341582017-02-23 23:42:25 +05307727 out->stream.pause = out_pause;
7728 out->stream.resume = out_resume;
7729 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307730 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307731 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007732 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307733 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007734 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307735 } else {
7736 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7737 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007738 }
vivek mehta446c3962015-09-14 10:57:35 -07007739
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307740 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7741 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007742#ifdef AUDIO_GKI_ENABLED
7743 /* out->compr_config.codec->reserved[1] is for flags */
7744 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7745#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307746 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007747#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307748 }
7749
vivek mehta446c3962015-09-14 10:57:35 -07007750 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007751 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007752 config->format == 0 && config->sample_rate == 0 &&
7753 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007754 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007755 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7756 } else {
7757 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7758 ret = -EEXIST;
7759 goto error_open;
7760 }
vivek mehta446c3962015-09-14 10:57:35 -07007761 }
7762
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007763 if (config->offload_info.channel_mask)
7764 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007765 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007766 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007767 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007768 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307769 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007770 ret = -EINVAL;
7771 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007772 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007773
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007774 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007775 out->sample_rate = config->offload_info.sample_rate;
7776
Mingming Yin3ee55c62014-08-04 14:23:35 -07007777 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007778
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307779 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307780 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307781 audio_extn_dolby_send_ddp_endp_params(adev);
7782 audio_extn_dolby_set_dmid(adev);
7783 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007784
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007785 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007786 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007787 out->compr_config.codec->bit_rate =
7788 config->offload_info.bit_rate;
7789 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307790 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007791 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307792 /* Update bit width only for non passthrough usecases.
7793 * For passthrough usecases, the output will always be opened @16 bit
7794 */
7795 if (!audio_extn_passthru_is_passthrough_stream(out))
7796 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307797
7798 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007799#ifdef AUDIO_GKI_ENABLED
7800 /* out->compr_config.codec->reserved[1] is for flags */
7801 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7802 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7803#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307804 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7805 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007806#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307807
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007808 /*TODO: Do we need to change it for passthrough */
7809 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007810
Manish Dewangana6fc5442015-08-24 20:30:31 +05307811 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7812 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307813 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307814 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307815 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7816 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307817
7818 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7819 AUDIO_FORMAT_PCM) {
7820
7821 /*Based on platform support, configure appropriate alsa format for corresponding
7822 *hal input format.
7823 */
7824 out->compr_config.codec->format = hal_format_to_alsa(
7825 config->offload_info.format);
7826
Ashish Jain83a6cc22016-06-28 14:34:17 +05307827 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307828 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307829 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307830
Dhananjay Kumarac341582017-02-23 23:42:25 +05307831 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307832 *hal input format and alsa format might differ based on platform support.
7833 */
7834 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307835 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307836
7837 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7838
Deeraj Soman93155a62019-09-30 19:00:37 +05307839 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7840 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7841 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7842 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7843 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307844
Ashish Jainf1eaa582016-05-23 20:54:24 +05307845 /* Check if alsa session is configured with the same format as HAL input format,
7846 * if not then derive correct fragment size needed to accomodate the
7847 * conversion of HAL input format to alsa format.
7848 */
7849 audio_extn_utils_update_direct_pcm_fragment_size(out);
7850
7851 /*if hal input and output fragment size is different this indicates HAL input format is
7852 *not same as the alsa format
7853 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307854 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307855 /*Allocate a buffer to convert input data to the alsa configured format.
7856 *size of convert buffer is equal to the size required to hold one fragment size
7857 *worth of pcm data, this is because flinger does not write more than fragment_size
7858 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307859 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7860 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307861 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7862 ret = -ENOMEM;
7863 goto error_open;
7864 }
7865 }
7866 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7867 out->compr_config.fragment_size =
7868 audio_extn_passthru_get_buffer_size(&config->offload_info);
7869 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7870 } else {
7871 out->compr_config.fragment_size =
7872 platform_get_compress_offload_buffer_size(&config->offload_info);
7873 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7874 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007875
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307876 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7877 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7878 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007879 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307880 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007881
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307882 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7883 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7884 }
7885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007886 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7887 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007888
Manish Dewangan69426c82017-01-30 17:35:36 +05307889 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7890 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7891 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7892 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7893 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7894 } else {
7895 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7896 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007897
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307898 memset(&out->channel_map_param, 0,
7899 sizeof(struct audio_out_channel_map_param));
7900
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007901 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307902 out->send_next_track_params = false;
7903 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007904 out->offload_state = OFFLOAD_STATE_IDLE;
7905 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007906 out->writeAt.tv_sec = 0;
7907 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007908
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007909 audio_extn_dts_create_state_notifier_node(out->usecase);
7910
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007911 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7912 __func__, config->offload_info.version,
7913 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307914
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307915 /* Check if DSD audio format is supported in codec
7916 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307917 */
7918
7919 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307920 (!platform_check_codec_dsd_support(adev->platform) ||
7921 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307922 ret = -EINVAL;
7923 goto error_open;
7924 }
7925
Ashish Jain5106d362016-05-11 19:23:33 +05307926 /* Disable gapless if any of the following is true
7927 * passthrough playback
7928 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307929 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307930 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307931 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307932 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007933 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307934 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307935 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307936 check_and_set_gapless_mode(adev, false);
7937 } else
7938 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007939
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307940 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007941 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7942 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307943 if (config->format == AUDIO_FORMAT_DSD) {
7944 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007945#ifdef AUDIO_GKI_ENABLED
7946 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7947 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7948#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307949 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007950#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307951 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007952
7953 create_offload_callback_thread(out);
7954
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007955 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007956 switch (config->sample_rate) {
7957 case 0:
7958 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7959 break;
7960 case 8000:
7961 case 16000:
7962 case 48000:
7963 out->sample_rate = config->sample_rate;
7964 break;
7965 default:
7966 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7967 config->sample_rate);
7968 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7969 ret = -EINVAL;
7970 goto error_open;
7971 }
7972 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7973 switch (config->channel_mask) {
7974 case AUDIO_CHANNEL_NONE:
7975 case AUDIO_CHANNEL_OUT_STEREO:
7976 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7977 break;
7978 default:
7979 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7980 config->channel_mask);
7981 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7982 ret = -EINVAL;
7983 goto error_open;
7984 }
7985 switch (config->format) {
7986 case AUDIO_FORMAT_DEFAULT:
7987 case AUDIO_FORMAT_PCM_16_BIT:
7988 out->format = AUDIO_FORMAT_PCM_16_BIT;
7989 break;
7990 default:
7991 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7992 config->format);
7993 config->format = AUDIO_FORMAT_PCM_16_BIT;
7994 ret = -EINVAL;
7995 goto error_open;
7996 }
7997
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307998 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007999 if (ret != 0) {
8000 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008001 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008002 goto error_open;
8003 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008004 } else if (is_single_device_type_equal(&out->device_list,
8005 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008006 switch (config->sample_rate) {
8007 case 0:
8008 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8009 break;
8010 case 8000:
8011 case 16000:
8012 case 48000:
8013 out->sample_rate = config->sample_rate;
8014 break;
8015 default:
8016 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8017 config->sample_rate);
8018 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8019 ret = -EINVAL;
8020 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008021 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008022 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8023 switch (config->channel_mask) {
8024 case AUDIO_CHANNEL_NONE:
8025 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8026 break;
8027 case AUDIO_CHANNEL_OUT_STEREO:
8028 out->channel_mask = config->channel_mask;
8029 break;
8030 default:
8031 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8032 config->channel_mask);
8033 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8034 ret = -EINVAL;
8035 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008036 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008037 switch (config->format) {
8038 case AUDIO_FORMAT_DEFAULT:
8039 out->format = AUDIO_FORMAT_PCM_16_BIT;
8040 break;
8041 case AUDIO_FORMAT_PCM_16_BIT:
8042 out->format = config->format;
8043 break;
8044 default:
8045 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8046 config->format);
8047 config->format = AUDIO_FORMAT_PCM_16_BIT;
8048 ret = -EINVAL;
8049 break;
8050 }
8051 if (ret != 0)
8052 goto error_open;
8053
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008054 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8055 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008056 out->config.rate = out->sample_rate;
8057 out->config.channels =
8058 audio_channel_count_from_out_mask(out->channel_mask);
8059 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008060 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008061 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308062 unsigned int channels = 0;
8063 /*Update config params to default if not set by the caller*/
8064 if (config->sample_rate == 0)
8065 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8066 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8067 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8068 if (config->format == AUDIO_FORMAT_DEFAULT)
8069 config->format = AUDIO_FORMAT_PCM_16_BIT;
8070
8071 channels = audio_channel_count_from_out_mask(out->channel_mask);
8072
Varun Balaraje49253e2017-07-06 19:48:56 +05308073 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8074 out->usecase = get_interactive_usecase(adev);
8075 out->config = pcm_config_low_latency;
8076 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308077 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008078 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8079 out->flags);
8080 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008081 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8082 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8083 out->config = pcm_config_mmap_playback;
8084 out->stream.start = out_start;
8085 out->stream.stop = out_stop;
8086 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8087 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308088 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8089 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008090 out->hal_output_suspend_supported =
8091 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8092 out->dynamic_pm_qos_config_supported =
8093 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8094 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008095 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8096 } else {
8097 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8098 //the mixer path will be a string similar to "low-latency-playback resume"
8099 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8100 strlcat(out->pm_qos_mixer_path,
8101 " resume", MAX_MIXER_PATH_LEN);
8102 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8103 out->pm_qos_mixer_path);
8104 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308105 out->config = pcm_config_low_latency;
8106 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8107 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8108 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308109 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8110 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8111 if (out->config.period_size <= 0) {
8112 ALOGE("Invalid configuration period size is not valid");
8113 ret = -EINVAL;
8114 goto error_open;
8115 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008116 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8117 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8118 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008119 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8120 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8121 out->config = pcm_config_haptics_audio;
8122 if (force_haptic_path)
8123 adev->haptics_config = pcm_config_haptics_audio;
8124 else
8125 adev->haptics_config = pcm_config_haptics;
8126
8127 out->config.channels =
8128 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8129
8130 if (force_haptic_path) {
8131 out->config.channels = 1;
8132 adev->haptics_config.channels = 1;
8133 } else
8134 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008135 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008136 ret = audio_extn_auto_hal_open_output_stream(out);
8137 if (ret) {
8138 ALOGE("%s: Failed to open output stream for bus device", __func__);
8139 ret = -EINVAL;
8140 goto error_open;
8141 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308142 } else {
8143 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008144 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8145 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308146 }
8147 out->hal_ip_format = format = out->format;
8148 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8149 out->hal_op_format = pcm_format_to_hal(out->config.format);
8150 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8151 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008152 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308153 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308154 if (out->hal_ip_format != out->hal_op_format) {
8155 uint32_t buffer_size = out->config.period_size *
8156 format_to_bitwidth_table[out->hal_op_format] *
8157 out->config.channels;
8158 out->convert_buffer = calloc(1, buffer_size);
8159 if (out->convert_buffer == NULL){
8160 ALOGE("Allocation failed for convert buffer for size %d",
8161 out->compr_config.fragment_size);
8162 ret = -ENOMEM;
8163 goto error_open;
8164 }
8165 ALOGD("Convert buffer allocated of size %d", buffer_size);
8166 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008167 }
8168
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008169 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8170 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308171
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008172 /* TODO remove this hardcoding and check why width is zero*/
8173 if (out->bit_width == 0)
8174 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308175 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008176 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008177 &out->device_list, out->flags,
8178 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308179 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308180 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008181 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008182 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8183 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008184 if(adev->primary_output == NULL)
8185 adev->primary_output = out;
8186 else {
8187 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008188 ret = -EEXIST;
8189 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008190 }
8191 }
8192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008193 /* Check if this usecase is already existing */
8194 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008195 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8196 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008197 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008198 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008199 ret = -EEXIST;
8200 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008201 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008203 pthread_mutex_unlock(&adev->lock);
8204
8205 out->stream.common.get_sample_rate = out_get_sample_rate;
8206 out->stream.common.set_sample_rate = out_set_sample_rate;
8207 out->stream.common.get_buffer_size = out_get_buffer_size;
8208 out->stream.common.get_channels = out_get_channels;
8209 out->stream.common.get_format = out_get_format;
8210 out->stream.common.set_format = out_set_format;
8211 out->stream.common.standby = out_standby;
8212 out->stream.common.dump = out_dump;
8213 out->stream.common.set_parameters = out_set_parameters;
8214 out->stream.common.get_parameters = out_get_parameters;
8215 out->stream.common.add_audio_effect = out_add_audio_effect;
8216 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8217 out->stream.get_latency = out_get_latency;
8218 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008219#ifdef NO_AUDIO_OUT
8220 out->stream.write = out_write_for_no_output;
8221#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008222 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008223#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008224 out->stream.get_render_position = out_get_render_position;
8225 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008226 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008227
Haynes Mathew George16081042017-05-31 17:16:49 -07008228 if (out->realtime)
8229 out->af_period_multiplier = af_period_multiplier;
8230 else
8231 out->af_period_multiplier = 1;
8232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008233 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008234 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008235 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008236
8237 config->format = out->stream.common.get_format(&out->stream.common);
8238 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8239 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308240 register_format(out->format, out->supported_formats);
8241 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8242 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008243
Aalique Grahame22e49102018-12-18 14:23:57 -08008244 out->error_log = error_log_create(
8245 ERROR_LOG_ENTRIES,
8246 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8247
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308248 /*
8249 By locking output stream before registering, we allow the callback
8250 to update stream's state only after stream's initial state is set to
8251 adev state.
8252 */
8253 lock_output_stream(out);
8254 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8255 pthread_mutex_lock(&adev->lock);
8256 out->card_status = adev->card_status;
8257 pthread_mutex_unlock(&adev->lock);
8258 pthread_mutex_unlock(&out->lock);
8259
Aalique Grahame22e49102018-12-18 14:23:57 -08008260 stream_app_type_cfg_init(&out->app_type_cfg);
8261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008262 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308263 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008264 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008265
8266 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8267 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8268 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008269 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308270 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008271 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008272 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308273 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8274 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008275 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8276 out->usecase, PCM_PLAYBACK);
8277 hdlr_stream_cfg.flags = out->flags;
8278 hdlr_stream_cfg.type = PCM_PLAYBACK;
8279 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8280 &hdlr_stream_cfg);
8281 if (ret) {
8282 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8283 out->adsp_hdlr_stream_handle = NULL;
8284 }
8285 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308286 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8287 is_direct_passthough, false);
8288 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8289 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008290 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008291 if (ret < 0) {
8292 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8293 out->ip_hdlr_handle = NULL;
8294 }
8295 }
Derek Chenf939fb72018-11-13 13:34:41 -08008296
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008297 ret = io_streams_map_insert(adev, &out->stream.common,
8298 out->handle, AUDIO_PATCH_HANDLE_NONE);
8299 if (ret != 0)
8300 goto error_open;
8301
Derek Chenf939fb72018-11-13 13:34:41 -08008302 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8303 calloc(1, sizeof(streams_output_ctxt_t));
8304 if (out_ctxt == NULL) {
8305 ALOGE("%s fail to allocate output ctxt", __func__);
8306 ret = -ENOMEM;
8307 goto error_open;
8308 }
8309 out_ctxt->output = out;
8310
8311 pthread_mutex_lock(&adev->lock);
8312 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8313 pthread_mutex_unlock(&adev->lock);
8314
Eric Laurent994a6932013-07-17 11:51:42 -07008315 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008316 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008317
8318error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308319 if (out->convert_buffer)
8320 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008321 free(out);
8322 *stream_out = NULL;
8323 ALOGD("%s: exit: ret %d", __func__, ret);
8324 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008325}
8326
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308327void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008328 struct audio_stream_out *stream)
8329{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008330 struct stream_out *out = (struct stream_out *)stream;
8331 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008332 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008333
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008334 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308335
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008336 io_streams_map_remove(adev, out->handle);
8337
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308338 // must deregister from sndmonitor first to prevent races
8339 // between the callback and close_stream
8340 audio_extn_snd_mon_unregister_listener(out);
8341
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008342 /* close adsp hdrl session before standby */
8343 if (out->adsp_hdlr_stream_handle) {
8344 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8345 if (ret)
8346 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8347 out->adsp_hdlr_stream_handle = NULL;
8348 }
8349
Manish Dewangan21a850a2017-08-14 12:03:55 +05308350 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008351 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8352 out->ip_hdlr_handle = NULL;
8353 }
8354
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008355 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308356 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008357 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308358 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308359 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008360 if(ret != 0)
8361 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8362 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008363 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008364 out_standby(&stream->common);
8365
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008366 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008367 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008368 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008369 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008370 if (out->compr_config.codec != NULL)
8371 free(out->compr_config.codec);
8372 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008373
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308374 out->a2dp_compress_mute = false;
8375
Varun Balaraje49253e2017-07-06 19:48:56 +05308376 if (is_interactive_usecase(out->usecase))
8377 free_interactive_usecase(adev, out->usecase);
8378
Ashish Jain83a6cc22016-06-28 14:34:17 +05308379 if (out->convert_buffer != NULL) {
8380 free(out->convert_buffer);
8381 out->convert_buffer = NULL;
8382 }
8383
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008384 if (adev->voice_tx_output == out)
8385 adev->voice_tx_output = NULL;
8386
Aalique Grahame22e49102018-12-18 14:23:57 -08008387 error_log_destroy(out->error_log);
8388 out->error_log = NULL;
8389
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308390 if (adev->primary_output == out)
8391 adev->primary_output = NULL;
8392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008393 pthread_cond_destroy(&out->cond);
8394 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008395
8396 pthread_mutex_lock(&adev->lock);
8397 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8398 if (out_ctxt != NULL) {
8399 list_remove(&out_ctxt->list);
8400 free(out_ctxt);
8401 } else {
8402 ALOGW("%s, output stream already closed", __func__);
8403 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008404 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008405 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008406 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008407}
8408
8409static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8410{
8411 struct audio_device *adev = (struct audio_device *)dev;
8412 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008413 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008414 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008415 int ret;
8416 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008417 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008418 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008419 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008420
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008421 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008422 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008423
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308424 if (!parms)
8425 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308426
Derek Chen6f293672019-04-01 01:40:24 -07008427 /* notify adev and input/output streams on the snd card status */
8428 adev_snd_mon_cb((void *)adev, parms);
8429
8430 list_for_each(node, &adev->active_outputs_list) {
8431 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8432 streams_output_ctxt_t,
8433 list);
8434 out_snd_mon_cb((void *)out_ctxt->output, parms);
8435 }
8436
8437 list_for_each(node, &adev->active_inputs_list) {
8438 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8439 streams_input_ctxt_t,
8440 list);
8441 in_snd_mon_cb((void *)in_ctxt->input, parms);
8442 }
8443
Zhou Songd6d71752019-05-21 18:08:51 +08008444 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308445 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8446 if (ret >= 0) {
8447 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008448 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308449 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008450 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308451 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008452 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008453 }
8454 }
8455
8456 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8457 if (ret>=0) {
8458 if (!strncmp(value, "false", 5) &&
8459 audio_extn_a2dp_source_is_suspended()) {
8460 struct audio_usecase *usecase;
8461 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008462 list_for_each(node, &adev->usecase_list) {
8463 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008464 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008465 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008466 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008467 reassign_device_list(&usecase->stream.in->device_list,
8468 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008469 select_devices(adev, usecase->id);
8470 }
Zhou Songd6d71752019-05-21 18:08:51 +08008471 }
8472 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308473 }
8474
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008475 status = voice_set_parameters(adev, parms);
8476 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008477 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008478
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008479 status = platform_set_parameters(adev->platform, parms);
8480 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008481 goto done;
8482
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008483 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8484 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008485 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008486 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8487 adev->bluetooth_nrec = true;
8488 else
8489 adev->bluetooth_nrec = false;
8490 }
8491
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008492 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8493 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008494 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8495 adev->screen_off = false;
8496 else
8497 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008498 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008499 }
8500
Eric Laurent4b084132018-10-19 17:33:43 -07008501 ret = str_parms_get_int(parms, "rotation", &val);
8502 if (ret >= 0) {
8503 bool reverse_speakers = false;
8504 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8505 switch (val) {
8506 // FIXME: note that the code below assumes that the speakers are in the correct placement
8507 // relative to the user when the device is rotated 90deg from its default rotation. This
8508 // assumption is device-specific, not platform-specific like this code.
8509 case 270:
8510 reverse_speakers = true;
8511 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8512 break;
8513 case 0:
8514 case 180:
8515 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8516 break;
8517 case 90:
8518 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8519 break;
8520 default:
8521 ALOGE("%s: unexpected rotation of %d", __func__, val);
8522 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008523 }
Eric Laurent4b084132018-10-19 17:33:43 -07008524 if (status == 0) {
8525 // check and set swap
8526 // - check if orientation changed and speaker active
8527 // - set rotation and cache the rotation value
8528 adev->camera_orientation =
8529 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8530 if (!audio_extn_is_maxx_audio_enabled())
8531 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8532 }
8533 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008534
Mingming Yin514a8bc2014-07-29 15:22:21 -07008535 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8536 if (ret >= 0) {
8537 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8538 adev->bt_wb_speech_enabled = true;
8539 else
8540 adev->bt_wb_speech_enabled = false;
8541 }
8542
Zhou Song12c29502019-03-16 10:37:18 +08008543 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8544 if (ret >= 0) {
8545 val = atoi(value);
8546 adev->swb_speech_mode = val;
8547 }
8548
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008549 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8550 if (ret >= 0) {
8551 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308552 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008553 if (audio_is_output_device(val) &&
8554 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008555 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008556 platform_get_controller_stream_from_params(parms, &controller, &stream);
8557 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8558 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008559 if (ret < 0) {
8560 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308561 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008562 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008563 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308564 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008565 /*
8566 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8567 * Per AudioPolicyManager, USB device is higher priority than WFD.
8568 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8569 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8570 * starting voice call on USB
8571 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008572 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308573 if (ret >= 0)
8574 audio_extn_usb_add_device(device, atoi(value));
8575
Zhou Song6f862822017-11-06 17:27:57 +08008576 if (!audio_extn_usb_is_tunnel_supported()) {
8577 ALOGV("detected USB connect .. disable proxy");
8578 adev->allow_afe_proxy_usage = false;
8579 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008580 }
8581 }
8582
8583 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8584 if (ret >= 0) {
8585 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308586 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008587 /*
8588 * The HDMI / Displayport disconnect handling has been moved to
8589 * audio extension to ensure that its parameters are not
8590 * invalidated prior to updating sysfs of the disconnect event
8591 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8592 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308593 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008594 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308595 if (ret >= 0)
8596 audio_extn_usb_remove_device(device, atoi(value));
8597
Zhou Song6f862822017-11-06 17:27:57 +08008598 if (!audio_extn_usb_is_tunnel_supported()) {
8599 ALOGV("detected USB disconnect .. enable proxy");
8600 adev->allow_afe_proxy_usage = true;
8601 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008602 }
8603 }
8604
Aalique Grahame22e49102018-12-18 14:23:57 -08008605 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008606 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008607
8608 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008609 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308610 struct audio_usecase *usecase;
8611 struct listnode *node;
8612 list_for_each(node, &adev->usecase_list) {
8613 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308614 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008615 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308616 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008617 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308618 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008619 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308620 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308621 ALOGD("Switching to speaker and muting the stream before select_devices");
8622 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308623 //force device switch to re configure encoder
8624 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308625 ALOGD("Unmuting the stream after select_devices");
8626 usecase->stream.out->a2dp_compress_mute = false;
8627 out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308628 audio_extn_a2dp_set_handoff_mode(false);
8629 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308630 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308631 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8632 usecase->stream.out->a2dp_compress_mute) {
8633 pthread_mutex_unlock(&adev->lock);
8634 lock_output_stream(usecase->stream.out);
8635 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008636 reassign_device_list(&usecase->stream.out->device_list,
8637 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308638 check_a2dp_restore_l(adev, usecase->stream.out, true);
8639 pthread_mutex_unlock(&usecase->stream.out->lock);
8640 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308641 }
8642 }
8643 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008644
8645 //handle vr audio setparam
8646 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8647 value, sizeof(value));
8648 if (ret >= 0) {
8649 ALOGI("Setting vr mode to be %s", value);
8650 if (!strncmp(value, "true", 4)) {
8651 adev->vr_audio_mode_enabled = true;
8652 ALOGI("Setting vr mode to true");
8653 } else if (!strncmp(value, "false", 5)) {
8654 adev->vr_audio_mode_enabled = false;
8655 ALOGI("Setting vr mode to false");
8656 } else {
8657 ALOGI("wrong vr mode set");
8658 }
8659 }
8660
Eric Laurent4b084132018-10-19 17:33:43 -07008661 //FIXME: to be replaced by proper video capture properties API
8662 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8663 if (ret >= 0) {
8664 int camera_facing = CAMERA_FACING_BACK;
8665 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8666 camera_facing = CAMERA_FACING_FRONT;
8667 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8668 camera_facing = CAMERA_FACING_BACK;
8669 else {
8670 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8671 goto done;
8672 }
8673 adev->camera_orientation =
8674 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8675 struct audio_usecase *usecase;
8676 struct listnode *node;
8677 list_for_each(node, &adev->usecase_list) {
8678 usecase = node_to_item(node, struct audio_usecase, list);
8679 struct stream_in *in = usecase->stream.in;
8680 if (usecase->type == PCM_CAPTURE && in != NULL &&
8681 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8682 select_devices(adev, in->usecase);
8683 }
8684 }
8685 }
8686
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308687 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008688done:
8689 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008690 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308691error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008692 ALOGV("%s: exit with code(%d)", __func__, status);
8693 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008694}
8695
8696static char* adev_get_parameters(const struct audio_hw_device *dev,
8697 const char *keys)
8698{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308699 ALOGD("%s:%s", __func__, keys);
8700
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008701 struct audio_device *adev = (struct audio_device *)dev;
8702 struct str_parms *reply = str_parms_create();
8703 struct str_parms *query = str_parms_create_str(keys);
8704 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308705 char value[256] = {0};
8706 int ret = 0;
8707
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008708 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008709 if (reply) {
8710 str_parms_destroy(reply);
8711 }
8712 if (query) {
8713 str_parms_destroy(query);
8714 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008715 ALOGE("adev_get_parameters: failed to create query or reply");
8716 return NULL;
8717 }
8718
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008719 //handle vr audio getparam
8720
8721 ret = str_parms_get_str(query,
8722 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8723 value, sizeof(value));
8724
8725 if (ret >= 0) {
8726 bool vr_audio_enabled = false;
8727 pthread_mutex_lock(&adev->lock);
8728 vr_audio_enabled = adev->vr_audio_mode_enabled;
8729 pthread_mutex_unlock(&adev->lock);
8730
8731 ALOGI("getting vr mode to %d", vr_audio_enabled);
8732
8733 if (vr_audio_enabled) {
8734 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8735 "true");
8736 goto exit;
8737 } else {
8738 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8739 "false");
8740 goto exit;
8741 }
8742 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008743
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008744 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008745 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008746 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008747 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008748 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308749 pthread_mutex_unlock(&adev->lock);
8750
Naresh Tannirud7205b62014-06-20 02:54:48 +05308751exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008752 str = str_parms_to_str(reply);
8753 str_parms_destroy(query);
8754 str_parms_destroy(reply);
8755
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308756 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008757 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008758}
8759
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008760static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008761{
8762 return 0;
8763}
8764
8765static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8766{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008767 int ret;
8768 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008769
8770 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8771
Haynes Mathew George5191a852013-09-11 14:19:36 -07008772 pthread_mutex_lock(&adev->lock);
8773 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008774 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008775 pthread_mutex_unlock(&adev->lock);
8776 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008777}
8778
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008779static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8780 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008781{
8782 return -ENOSYS;
8783}
8784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008785static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8786 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008787{
8788 return -ENOSYS;
8789}
8790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008791static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8792 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008793{
8794 return -ENOSYS;
8795}
8796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008797static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8798 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008799{
8800 return -ENOSYS;
8801}
8802
8803static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8804{
8805 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008806 struct listnode *node;
8807 struct audio_usecase *usecase = NULL;
8808 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008810 pthread_mutex_lock(&adev->lock);
8811 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008812 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008813 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008814 if (voice_is_in_call(adev) &&
8815 (mode == AUDIO_MODE_NORMAL ||
8816 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008817 list_for_each(node, &adev->usecase_list) {
8818 usecase = node_to_item(node, struct audio_usecase, list);
8819 if (usecase->type == VOICE_CALL)
8820 break;
8821 }
8822 if (usecase &&
8823 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8824 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8825 true);
8826 if (ret != 0) {
8827 /* default service interval was successfully updated,
8828 reopen USB backend with new service interval */
8829 check_usecases_codec_backend(adev,
8830 usecase,
8831 usecase->out_snd_device);
8832 }
8833 }
8834
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008835 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008836 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008837 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008838 // restore device for other active usecases after stop call
8839 list_for_each(node, &adev->usecase_list) {
8840 usecase = node_to_item(node, struct audio_usecase, list);
8841 select_devices(adev, usecase->id);
8842 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008843 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008844 }
8845 pthread_mutex_unlock(&adev->lock);
8846 return 0;
8847}
8848
8849static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8850{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008851 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008852 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008853
8854 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008855 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008856 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008857
Derek Chend2530072014-11-24 12:39:14 -08008858 if (adev->ext_hw_plugin)
8859 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008860
8861 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008862 pthread_mutex_unlock(&adev->lock);
8863
8864 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008865}
8866
8867static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8868{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008869 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008870 return 0;
8871}
8872
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008873static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008874 const struct audio_config *config)
8875{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008876 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008877
Aalique Grahame22e49102018-12-18 14:23:57 -08008878 /* Don't know if USB HIFI in this context so use true to be conservative */
8879 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8880 true /*is_usb_hifi */) != 0)
8881 return 0;
8882
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008883 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8884 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885}
8886
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008887static bool adev_input_allow_hifi_record(struct audio_device *adev,
8888 audio_devices_t devices,
8889 audio_input_flags_t flags,
8890 audio_source_t source) {
8891 const bool allowed = true;
8892
8893 if (!audio_is_usb_in_device(devices))
8894 return !allowed;
8895
8896 switch (flags) {
8897 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008898 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008899 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8900 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008901 default:
8902 return !allowed;
8903 }
8904
8905 switch (source) {
8906 case AUDIO_SOURCE_DEFAULT:
8907 case AUDIO_SOURCE_MIC:
8908 case AUDIO_SOURCE_UNPROCESSED:
8909 break;
8910 default:
8911 return !allowed;
8912 }
8913
8914 switch (adev->mode) {
8915 case 0:
8916 break;
8917 default:
8918 return !allowed;
8919 }
8920
8921 return allowed;
8922}
8923
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008924static int adev_update_voice_comm_input_stream(struct stream_in *in,
8925 struct audio_config *config)
8926{
8927 bool valid_rate = (config->sample_rate == 8000 ||
8928 config->sample_rate == 16000 ||
8929 config->sample_rate == 32000 ||
8930 config->sample_rate == 48000);
8931 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8932
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008933 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008934 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008935 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8936 in->config = default_pcm_config_voip_copp;
8937 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8938 DEFAULT_VOIP_BUF_DURATION_MS,
8939 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008940 } else {
8941 ALOGW("%s No valid input in voip, use defaults"
8942 "sample rate %u, channel mask 0x%X",
8943 __func__, config->sample_rate, in->channel_mask);
8944 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008945 in->config.rate = config->sample_rate;
8946 in->sample_rate = config->sample_rate;
8947 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008948 //XXX needed for voice_extn_compress_voip_open_input_stream
8949 in->config.rate = config->sample_rate;
8950 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308951 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008952 voice_extn_compress_voip_is_active(in->dev)) &&
8953 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8954 valid_rate && valid_ch) {
8955 voice_extn_compress_voip_open_input_stream(in);
8956 // update rate entries to match config from AF
8957 in->config.rate = config->sample_rate;
8958 in->sample_rate = config->sample_rate;
8959 } else {
8960 ALOGW("%s compress voip not active, use defaults", __func__);
8961 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008962 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008963 return 0;
8964}
8965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008966static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008967 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008968 audio_devices_t devices,
8969 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008970 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308971 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008972 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008973 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008974{
8975 struct audio_device *adev = (struct audio_device *)dev;
8976 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008977 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008978 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008979 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308980 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008981 bool is_usb_dev = audio_is_usb_in_device(devices);
8982 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8983 devices,
8984 flags,
8985 source);
Andy Hung94320602018-10-29 18:31:12 -07008986 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8987 " sample_rate %u, channel_mask %#x, format %#x",
8988 __func__, flags, is_usb_dev, may_use_hifi_record,
8989 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308990
kunleizdff872d2018-08-20 14:40:33 +08008991 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008992 is_usb_dev = false;
8993 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8994 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8995 __func__, devices);
8996 }
8997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008998 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008999
9000 if (!(is_usb_dev && may_use_hifi_record)) {
9001 if (config->sample_rate == 0)
9002 config->sample_rate = 48000;
9003 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9004 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9005 if (config->format == AUDIO_FORMAT_DEFAULT)
9006 config->format = AUDIO_FORMAT_PCM_16_BIT;
9007
9008 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9009
Aalique Grahame22e49102018-12-18 14:23:57 -08009010 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9011 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009012 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309013 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009014
Rahul Sharma99770982019-03-06 17:05:26 +05309015 pthread_mutex_lock(&adev->lock);
9016 if (in_get_stream(adev, handle) != NULL) {
9017 ALOGW("%s, input stream already opened", __func__);
9018 ret = -EEXIST;
9019 }
9020 pthread_mutex_unlock(&adev->lock);
9021 if (ret)
9022 return ret;
9023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009024 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009025
9026 if (!in) {
9027 ALOGE("failed to allocate input stream");
9028 return -ENOMEM;
9029 }
9030
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309031 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309032 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9033 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009034 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009035 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009037 in->stream.common.get_sample_rate = in_get_sample_rate;
9038 in->stream.common.set_sample_rate = in_set_sample_rate;
9039 in->stream.common.get_buffer_size = in_get_buffer_size;
9040 in->stream.common.get_channels = in_get_channels;
9041 in->stream.common.get_format = in_get_format;
9042 in->stream.common.set_format = in_set_format;
9043 in->stream.common.standby = in_standby;
9044 in->stream.common.dump = in_dump;
9045 in->stream.common.set_parameters = in_set_parameters;
9046 in->stream.common.get_parameters = in_get_parameters;
9047 in->stream.common.add_audio_effect = in_add_audio_effect;
9048 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9049 in->stream.set_gain = in_set_gain;
9050 in->stream.read = in_read;
9051 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009052 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309053 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009054 in->stream.set_microphone_direction = in_set_microphone_direction;
9055 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009056 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009057
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009058 list_init(&in->device_list);
9059 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009060 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009061 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009062 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009063 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009064 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009065 in->bit_width = 16;
9066 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009067 in->direction = MIC_DIRECTION_UNSPECIFIED;
9068 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009069 list_init(&in->aec_list);
9070 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009071 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009072
Andy Hung94320602018-10-29 18:31:12 -07009073 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009074 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9075 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9076 /* Force channel config requested to mono if incall
9077 record is being requested for only uplink/downlink */
9078 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9079 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9080 ret = -EINVAL;
9081 goto err_open;
9082 }
9083 }
9084
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009085 if (is_usb_dev && may_use_hifi_record) {
9086 /* HiFi record selects an appropriate format, channel, rate combo
9087 depending on sink capabilities*/
9088 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9089 &config->format,
9090 &in->supported_formats[0],
9091 MAX_SUPPORTED_FORMATS,
9092 &config->channel_mask,
9093 &in->supported_channel_masks[0],
9094 MAX_SUPPORTED_CHANNEL_MASKS,
9095 &config->sample_rate,
9096 &in->supported_sample_rates[0],
9097 MAX_SUPPORTED_SAMPLE_RATES);
9098 if (ret != 0) {
9099 ret = -EINVAL;
9100 goto err_open;
9101 }
9102 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009103 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309104 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309105 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9106 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9107 in->config.format = PCM_FORMAT_S32_LE;
9108 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309109 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9110 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9111 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9112 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9113 bool ret_error = false;
9114 in->bit_width = 24;
9115 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9116 from HAL is 24_packed and 8_24
9117 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9118 24_packed return error indicating supported format is 24_packed
9119 *> In case of any other source requesting 24 bit or float return error
9120 indicating format supported is 16 bit only.
9121
9122 on error flinger will retry with supported format passed
9123 */
9124 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9125 (source != AUDIO_SOURCE_CAMCORDER)) {
9126 config->format = AUDIO_FORMAT_PCM_16_BIT;
9127 if (config->sample_rate > 48000)
9128 config->sample_rate = 48000;
9129 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009130 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9131 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309132 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9133 ret_error = true;
9134 }
9135
9136 if (ret_error) {
9137 ret = -EINVAL;
9138 goto err_open;
9139 }
9140 }
9141
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009142 in->channel_mask = config->channel_mask;
9143 in->format = config->format;
9144
9145 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309146
9147 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9148 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9149 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9150 else {
9151 ret = -EINVAL;
9152 goto err_open;
9153 }
9154 }
9155
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009156 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309157 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9158 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009159 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9160 is_low_latency = true;
9161#if LOW_LATENCY_CAPTURE_USE_CASE
9162 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9163#endif
9164 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009165 if (!in->realtime) {
9166 in->config = pcm_config_audio_capture;
9167 frame_size = audio_stream_in_frame_size(&in->stream);
9168 buffer_size = get_input_buffer_size(config->sample_rate,
9169 config->format,
9170 channel_count,
9171 is_low_latency);
9172 in->config.period_size = buffer_size / frame_size;
9173 in->config.rate = config->sample_rate;
9174 in->af_period_multiplier = 1;
9175 } else {
9176 // period size is left untouched for rt mode playback
9177 in->config = pcm_config_audio_capture_rt;
9178 in->af_period_multiplier = af_period_multiplier;
9179 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009180 }
9181
9182 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9183 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9184 in->realtime = 0;
9185 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9186 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009187 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009188 in->stream.start = in_start;
9189 in->stream.stop = in_stop;
9190 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9191 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009192 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
9193 } else if (in->realtime) {
9194 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07009195 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009196 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009197 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009198 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9199 in->config = pcm_config_audio_capture;
9200 frame_size = audio_stream_in_frame_size(&in->stream);
9201 buffer_size = get_input_buffer_size(config->sample_rate,
9202 config->format,
9203 channel_count,
9204 false /*is_low_latency*/);
9205 in->config.period_size = buffer_size / frame_size;
9206 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009207 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009208 switch (config->format) {
9209 case AUDIO_FORMAT_PCM_32_BIT:
9210 in->bit_width = 32;
9211 break;
9212 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9213 case AUDIO_FORMAT_PCM_8_24_BIT:
9214 in->bit_width = 24;
9215 break;
9216 default:
9217 in->bit_width = 16;
9218 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009219 } else if (is_single_device_type_equal(&in->device_list,
9220 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9221 is_single_device_type_equal(&in->device_list,
9222 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009223 if (config->sample_rate == 0)
9224 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9225 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9226 config->sample_rate != 8000) {
9227 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9228 ret = -EINVAL;
9229 goto err_open;
9230 }
9231 if (config->format == AUDIO_FORMAT_DEFAULT)
9232 config->format = AUDIO_FORMAT_PCM_16_BIT;
9233 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9234 config->format = AUDIO_FORMAT_PCM_16_BIT;
9235 ret = -EINVAL;
9236 goto err_open;
9237 }
9238
9239 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9240 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009241 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009242 in->af_period_multiplier = 1;
9243 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9244 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9245 (config->sample_rate == 8000 ||
9246 config->sample_rate == 16000 ||
9247 config->sample_rate == 32000 ||
9248 config->sample_rate == 48000) &&
9249 channel_count == 1) {
9250 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9251 in->config = pcm_config_audio_capture;
9252 frame_size = audio_stream_in_frame_size(&in->stream);
9253 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9254 config->sample_rate,
9255 config->format,
9256 channel_count, false /*is_low_latency*/);
9257 in->config.period_size = buffer_size / frame_size;
9258 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9259 in->config.rate = config->sample_rate;
9260 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009261 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309262 int ret_val;
9263 pthread_mutex_lock(&adev->lock);
9264 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9265 in, config, &channel_mask_updated);
9266 pthread_mutex_unlock(&adev->lock);
9267
9268 if (!ret_val) {
9269 if (channel_mask_updated == true) {
9270 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9271 __func__, config->channel_mask);
9272 ret = -EINVAL;
9273 goto err_open;
9274 }
9275 ALOGD("%s: created multi-channel session succesfully",__func__);
9276 } else if (audio_extn_compr_cap_enabled() &&
9277 audio_extn_compr_cap_format_supported(config->format) &&
9278 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9279 audio_extn_compr_cap_init(in);
9280 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309281 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309282 if (ret)
9283 goto err_open;
9284 } else {
9285 in->config = pcm_config_audio_capture;
9286 in->config.rate = config->sample_rate;
9287 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309288 in->format = config->format;
9289 frame_size = audio_stream_in_frame_size(&in->stream);
9290 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009291 config->format,
9292 channel_count,
9293 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009294 /* prevent division-by-zero */
9295 if (frame_size == 0) {
9296 ALOGE("%s: Error frame_size==0", __func__);
9297 ret = -EINVAL;
9298 goto err_open;
9299 }
9300
Revathi Uddarajud2634032017-12-07 14:42:34 +05309301 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009302 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009303
Revathi Uddarajud2634032017-12-07 14:42:34 +05309304 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9305 /* optionally use VOIP usecase depending on config(s) */
9306 ret = adev_update_voice_comm_input_stream(in, config);
9307 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009308
Revathi Uddarajud2634032017-12-07 14:42:34 +05309309 if (ret) {
9310 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9311 goto err_open;
9312 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009313 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309314
9315 /* assign concurrent capture usecase if record has to caried out from
9316 * actual hardware input source */
9317 if (audio_extn_is_concurrent_capture_enabled() &&
9318 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309319 /* Acquire lock to avoid two concurrent use cases initialized to
9320 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009321
Samyak Jainc37062f2019-04-25 18:41:06 +05309322 if (in->usecase == USECASE_AUDIO_RECORD) {
9323 pthread_mutex_lock(&adev->lock);
9324 if (!(adev->pcm_record_uc_state)) {
9325 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9326 adev->pcm_record_uc_state = 1;
9327 pthread_mutex_unlock(&adev->lock);
9328 } else {
9329 pthread_mutex_unlock(&adev->lock);
9330 /* Assign compress record use case for second record */
9331 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9332 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9333 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9334 if (audio_extn_cin_applicable_stream(in)) {
9335 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309336 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309337 if (ret)
9338 goto err_open;
9339 }
9340 }
9341 }
kunleiz28c73e72019-03-27 17:24:04 +08009342 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009343 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309344 if (audio_extn_ssr_get_stream() != in)
9345 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009346
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009347 in->sample_rate = in->config.rate;
9348
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309349 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9350 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009351 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009352 in->sample_rate, in->bit_width,
9353 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309354 register_format(in->format, in->supported_formats);
9355 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9356 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309357
Aalique Grahame22e49102018-12-18 14:23:57 -08009358 in->error_log = error_log_create(
9359 ERROR_LOG_ENTRIES,
9360 1000000000 /* aggregate consecutive identical errors within one second */);
9361
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009362 /* This stream could be for sound trigger lab,
9363 get sound trigger pcm if present */
9364 audio_extn_sound_trigger_check_and_get_session(in);
9365
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309366 lock_input_stream(in);
9367 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9368 pthread_mutex_lock(&adev->lock);
9369 in->card_status = adev->card_status;
9370 pthread_mutex_unlock(&adev->lock);
9371 pthread_mutex_unlock(&in->lock);
9372
Aalique Grahame22e49102018-12-18 14:23:57 -08009373 stream_app_type_cfg_init(&in->app_type_cfg);
9374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009375 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009376
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009377 ret = io_streams_map_insert(adev, &in->stream.common,
9378 handle, AUDIO_PATCH_HANDLE_NONE);
9379 if (ret != 0)
9380 goto err_open;
9381
Derek Chenf939fb72018-11-13 13:34:41 -08009382 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9383 calloc(1, sizeof(streams_input_ctxt_t));
9384 if (in_ctxt == NULL) {
9385 ALOGE("%s fail to allocate input ctxt", __func__);
9386 ret = -ENOMEM;
9387 goto err_open;
9388 }
9389 in_ctxt->input = in;
9390
9391 pthread_mutex_lock(&adev->lock);
9392 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9393 pthread_mutex_unlock(&adev->lock);
9394
Eric Laurent994a6932013-07-17 11:51:42 -07009395 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009396 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009397
9398err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309399 if (in->usecase == USECASE_AUDIO_RECORD) {
9400 pthread_mutex_lock(&adev->lock);
9401 adev->pcm_record_uc_state = 0;
9402 pthread_mutex_unlock(&adev->lock);
9403 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009404 free(in);
9405 *stream_in = NULL;
9406 return ret;
9407}
9408
9409static void adev_close_input_stream(struct audio_hw_device *dev,
9410 struct audio_stream_in *stream)
9411{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009412 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009413 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009414 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309415
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309416 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009417
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009418 if (in == NULL) {
9419 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9420 return;
9421 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009422 io_streams_map_remove(adev, in->capture_handle);
9423
kunleiz70e57612018-12-28 17:50:23 +08009424 /* must deregister from sndmonitor first to prevent races
9425 * between the callback and close_stream
9426 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309427 audio_extn_snd_mon_unregister_listener(stream);
9428
kunleiz70e57612018-12-28 17:50:23 +08009429 /* Disable echo reference if there are no active input, hfp call
9430 * and sound trigger while closing input stream
9431 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009432 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009433 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009434 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9435 struct listnode out_devices;
9436 list_init(&out_devices);
9437 platform_set_echo_reference(adev, false, &out_devices);
9438 } else
kunleiz70e57612018-12-28 17:50:23 +08009439 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309440
Weiyin Jiang2995f662019-04-17 14:25:12 +08009441 error_log_destroy(in->error_log);
9442 in->error_log = NULL;
9443
Pallavid7c7a272018-01-16 11:22:55 +05309444
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009445 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309446 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009447 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309448 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009449 if (ret != 0)
9450 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9451 __func__, ret);
9452 } else
9453 in_standby(&stream->common);
9454
Revathi Uddarajud2634032017-12-07 14:42:34 +05309455 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309456 if (in->usecase == USECASE_AUDIO_RECORD) {
9457 adev->pcm_record_uc_state = 0;
9458 }
9459
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009460 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9461 adev->enable_voicerx = false;
9462 }
9463
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009464 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009465 audio_extn_ssr_deinit();
9466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009467
Garmond Leunge2433c32017-09-28 21:51:22 -07009468 if (audio_extn_ffv_get_stream() == in) {
9469 audio_extn_ffv_stream_deinit();
9470 }
9471
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309472 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009473 audio_extn_compr_cap_format_supported(in->config.format))
9474 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309475
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309476 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309477 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009478
Mingming Yinfd7607b2016-01-22 12:48:44 -08009479 if (in->is_st_session) {
9480 ALOGV("%s: sound trigger pcm stop lab", __func__);
9481 audio_extn_sound_trigger_stop_lab(in);
9482 }
Derek Chenf939fb72018-11-13 13:34:41 -08009483 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9484 if (in_ctxt != NULL) {
9485 list_remove(&in_ctxt->list);
9486 free(in_ctxt);
9487 } else {
9488 ALOGW("%s, input stream already closed", __func__);
9489 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009490 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309491 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009492 return;
9493}
9494
Aalique Grahame22e49102018-12-18 14:23:57 -08009495/* verifies input and output devices and their capabilities.
9496 *
9497 * This verification is required when enabling extended bit-depth or
9498 * sampling rates, as not all qcom products support it.
9499 *
9500 * Suitable for calling only on initialization such as adev_open().
9501 * It fills the audio_device use_case_table[] array.
9502 *
9503 * Has a side-effect that it needs to configure audio routing / devices
9504 * in order to power up the devices and read the device parameters.
9505 * It does not acquire any hw device lock. Should restore the devices
9506 * back to "normal state" upon completion.
9507 */
9508static int adev_verify_devices(struct audio_device *adev)
9509{
9510 /* enumeration is a bit difficult because one really wants to pull
9511 * the use_case, device id, etc from the hidden pcm_device_table[].
9512 * In this case there are the following use cases and device ids.
9513 *
9514 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9515 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9516 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9517 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9518 * [USECASE_AUDIO_RECORD] = {0, 0},
9519 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9520 * [USECASE_VOICE_CALL] = {2, 2},
9521 *
9522 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9523 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9524 */
9525
9526 /* should be the usecases enabled in adev_open_input_stream() */
9527 static const int test_in_usecases[] = {
9528 USECASE_AUDIO_RECORD,
9529 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9530 };
9531 /* should be the usecases enabled in adev_open_output_stream()*/
9532 static const int test_out_usecases[] = {
9533 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9534 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9535 };
9536 static const usecase_type_t usecase_type_by_dir[] = {
9537 PCM_PLAYBACK,
9538 PCM_CAPTURE,
9539 };
9540 static const unsigned flags_by_dir[] = {
9541 PCM_OUT,
9542 PCM_IN,
9543 };
9544
9545 size_t i;
9546 unsigned dir;
9547 const unsigned card_id = adev->snd_card;
9548
9549 for (dir = 0; dir < 2; ++dir) {
9550 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9551 const unsigned flags_dir = flags_by_dir[dir];
9552 const size_t testsize =
9553 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9554 const int *testcases =
9555 dir ? test_in_usecases : test_out_usecases;
9556 const audio_devices_t audio_device =
9557 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9558
9559 for (i = 0; i < testsize; ++i) {
9560 const audio_usecase_t audio_usecase = testcases[i];
9561 int device_id;
9562 struct pcm_params **pparams;
9563 struct stream_out out;
9564 struct stream_in in;
9565 struct audio_usecase uc_info;
9566 int retval;
9567
9568 pparams = &adev->use_case_table[audio_usecase];
9569 pcm_params_free(*pparams); /* can accept null input */
9570 *pparams = NULL;
9571
9572 /* find the device ID for the use case (signed, for error) */
9573 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9574 if (device_id < 0)
9575 continue;
9576
9577 /* prepare structures for device probing */
9578 memset(&uc_info, 0, sizeof(uc_info));
9579 uc_info.id = audio_usecase;
9580 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009581 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009582 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009583 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009584 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009585 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009586 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9587 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009588 }
9589 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009590 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009591 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009592 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009593 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009594 uc_info.in_snd_device = SND_DEVICE_NONE;
9595 uc_info.out_snd_device = SND_DEVICE_NONE;
9596 list_add_tail(&adev->usecase_list, &uc_info.list);
9597
9598 /* select device - similar to start_(in/out)put_stream() */
9599 retval = select_devices(adev, audio_usecase);
9600 if (retval >= 0) {
9601 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9602#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009603 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009604 if (*pparams) {
9605 ALOGV("%s: (%s) card %d device %d", __func__,
9606 dir ? "input" : "output", card_id, device_id);
9607 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9608 } else {
9609 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9610 }
9611#endif
9612 }
9613
9614 /* deselect device - similar to stop_(in/out)put_stream() */
9615 /* 1. Get and set stream specific mixer controls */
9616 retval = disable_audio_route(adev, &uc_info);
9617 /* 2. Disable the rx device */
9618 retval = disable_snd_device(adev,
9619 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9620 list_remove(&uc_info.list);
9621 }
9622 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009623 return 0;
9624}
9625
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009626int update_patch(unsigned int num_sources,
9627 const struct audio_port_config *sources,
9628 unsigned int num_sinks,
9629 const struct audio_port_config *sinks,
9630 audio_patch_handle_t handle,
9631 struct audio_patch_info *p_info,
9632 patch_type_t patch_type, bool new_patch)
9633{
9634 ALOGD("%s: enter", __func__);
9635
9636 if (p_info == NULL) {
9637 ALOGE("%s: Invalid patch pointer", __func__);
9638 return -EINVAL;
9639 }
9640
9641 if (new_patch) {
9642 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9643 if (p_info->patch == NULL) {
9644 ALOGE("%s: Could not allocate patch", __func__);
9645 return -ENOMEM;
9646 }
9647 }
9648
9649 p_info->patch->id = handle;
9650 p_info->patch->num_sources = num_sources;
9651 p_info->patch->num_sinks = num_sinks;
9652
9653 for (int i = 0; i < num_sources; i++)
9654 p_info->patch->sources[i] = sources[i];
9655 for (int i = 0; i < num_sinks; i++)
9656 p_info->patch->sinks[i] = sinks[i];
9657
9658 p_info->patch_type = patch_type;
9659 return 0;
9660}
9661
9662audio_patch_handle_t generate_patch_handle()
9663{
9664 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9665 if (++patch_handle < 0)
9666 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9667 return patch_handle;
9668}
9669
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309670int adev_create_audio_patch(struct audio_hw_device *dev,
9671 unsigned int num_sources,
9672 const struct audio_port_config *sources,
9673 unsigned int num_sinks,
9674 const struct audio_port_config *sinks,
9675 audio_patch_handle_t *handle)
9676{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009677 int ret = 0;
9678 struct audio_device *adev = (struct audio_device *)dev;
9679 struct audio_patch_info *p_info = NULL;
9680 patch_type_t patch_type = PATCH_NONE;
9681 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9682 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9683 struct audio_stream_info *s_info = NULL;
9684 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009685 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009686 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9687 bool new_patch = false;
9688 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309689
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009690 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9691 num_sources, num_sinks, *handle);
9692
9693 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9694 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9695 ALOGE("%s: Invalid patch arguments", __func__);
9696 ret = -EINVAL;
9697 goto done;
9698 }
9699
9700 if (num_sources > 1) {
9701 ALOGE("%s: Multiple sources are not supported", __func__);
9702 ret = -EINVAL;
9703 goto done;
9704 }
9705
9706 if (sources == NULL || sinks == NULL) {
9707 ALOGE("%s: Invalid sources or sinks port config", __func__);
9708 ret = -EINVAL;
9709 goto done;
9710 }
9711
9712 ALOGV("%s: source role %d, source type %d", __func__,
9713 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009714 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009715
9716 // Populate source/sink information and fetch stream info
9717 switch (sources[0].type) {
9718 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9719 device_type = sources[0].ext.device.type;
9720 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009721 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009722 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9723 patch_type = PATCH_CAPTURE;
9724 io_handle = sinks[0].ext.mix.handle;
9725 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009726 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009727 __func__, device_type, io_handle);
9728 } else {
9729 // Device to device patch is not implemented.
9730 // This space will need changes if audio HAL
9731 // handles device to device patches in the future.
9732 patch_type = PATCH_DEVICE_LOOPBACK;
9733 }
9734 break;
9735 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9736 io_handle = sources[0].ext.mix.handle;
9737 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009738 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009739 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009740 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009741 }
9742 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009743 ALOGD("%s: Playback patch from mix handle %d to device %x",
9744 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009745 break;
9746 case AUDIO_PORT_TYPE_SESSION:
9747 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009748 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9749 ret = -EINVAL;
9750 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009751 }
9752
9753 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009754
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009755 // Generate patch info and update patch
9756 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009757 *handle = generate_patch_handle();
9758 p_info = (struct audio_patch_info *)
9759 calloc(1, sizeof(struct audio_patch_info));
9760 if (p_info == NULL) {
9761 ALOGE("%s: Failed to allocate memory", __func__);
9762 pthread_mutex_unlock(&adev->lock);
9763 ret = -ENOMEM;
9764 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009765 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009766 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009767 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009768 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009769 if (p_info == NULL) {
9770 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9771 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009772 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009773 ret = -EINVAL;
9774 goto done;
9775 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009776 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009777 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009778 *handle, p_info, patch_type, new_patch);
9779
9780 // Fetch stream info of associated mix for playback or capture patches
9781 if (p_info->patch_type == PATCH_PLAYBACK ||
9782 p_info->patch_type == PATCH_CAPTURE) {
9783 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9784 if (s_info == NULL) {
9785 ALOGE("%s: Failed to obtain stream info", __func__);
9786 if (new_patch)
9787 free(p_info);
9788 pthread_mutex_unlock(&adev->lock);
9789 ret = -EINVAL;
9790 goto done;
9791 }
9792 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9793 s_info->patch_handle = *handle;
9794 stream = s_info->stream;
9795 }
9796 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009797
9798 // Update routing for stream
9799 if (stream != NULL) {
9800 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009801 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009802 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009803 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009804 if (ret < 0) {
9805 pthread_mutex_lock(&adev->lock);
9806 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9807 if (new_patch)
9808 free(p_info);
9809 pthread_mutex_unlock(&adev->lock);
9810 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9811 goto done;
9812 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009813 }
9814
9815 // Add new patch to patch map
9816 if (!ret && new_patch) {
9817 pthread_mutex_lock(&adev->lock);
9818 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009819 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009820 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009821 }
9822
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009823done:
9824 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009825 num_sources,
9826 sources,
9827 num_sinks,
9828 sinks,
9829 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009830 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009831 num_sources,
9832 sources,
9833 num_sinks,
9834 sinks,
9835 handle);
9836 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309837}
9838
9839int adev_release_audio_patch(struct audio_hw_device *dev,
9840 audio_patch_handle_t handle)
9841{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009842 struct audio_device *adev = (struct audio_device *) dev;
9843 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009844 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009845 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009846
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009847 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9848 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9849 ret = -EINVAL;
9850 goto done;
9851 }
9852
9853 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009854 pthread_mutex_lock(&adev->lock);
9855 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009856 if (p_info == NULL) {
9857 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009858 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009859 ret = -EINVAL;
9860 goto done;
9861 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009862 struct audio_patch *patch = p_info->patch;
9863 if (patch == NULL) {
9864 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009865 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009866 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009867 goto done;
9868 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009869 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9870 switch (patch->sources[0].type) {
9871 case AUDIO_PORT_TYPE_MIX:
9872 io_handle = patch->sources[0].ext.mix.handle;
9873 break;
9874 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009875 if (p_info->patch_type == PATCH_CAPTURE)
9876 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009877 break;
9878 case AUDIO_PORT_TYPE_SESSION:
9879 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009880 pthread_mutex_unlock(&adev->lock);
9881 ret = -EINVAL;
9882 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009883 }
9884
9885 // Remove patch and reset patch handle in stream info
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009886 patch_map_remove_l(adev, handle);
9887 if (p_info->patch_type == PATCH_PLAYBACK ||
9888 p_info->patch_type == PATCH_CAPTURE) {
9889 struct audio_stream_info *s_info =
9890 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9891 if (s_info == NULL) {
9892 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9893 pthread_mutex_unlock(&adev->lock);
9894 goto done;
9895 }
9896 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9897 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009898 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009899 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009900
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009901 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009902 struct listnode devices;
9903 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009904 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009905 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009906 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009907 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009908 }
9909
9910 if (ret < 0)
9911 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9912
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009913done:
9914 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9915 audio_extn_auto_hal_release_audio_patch(dev, handle);
9916
9917 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009918 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309919}
9920
9921int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9922{
Derek Chenf13dd492018-11-13 14:53:51 -08009923 int ret = 0;
9924
9925 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9926 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9927 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309928}
9929
9930int adev_set_audio_port_config(struct audio_hw_device *dev,
9931 const struct audio_port_config *config)
9932{
Derek Chenf13dd492018-11-13 14:53:51 -08009933 int ret = 0;
9934
9935 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9936 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9937 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309938}
9939
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009940static int adev_dump(const audio_hw_device_t *device __unused,
9941 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009942{
9943 return 0;
9944}
9945
9946static int adev_close(hw_device_t *device)
9947{
Aalique Grahame22e49102018-12-18 14:23:57 -08009948 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309949 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009950
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309951 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009952 return 0;
9953
9954 pthread_mutex_lock(&adev_init_lock);
9955
9956 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309957 if (audio_extn_spkr_prot_is_enabled())
9958 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309959 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309960 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009961 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009962 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009963 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009964 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309965 audio_extn_utils_release_streams_cfg_lists(
9966 &adev->streams_output_cfg_list,
9967 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309968 if (audio_extn_qap_is_enabled())
9969 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309970 if (audio_extn_qaf_is_enabled())
9971 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009972 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009973 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009974 free(adev->snd_dev_ref_cnt);
9975 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009976 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9977 pcm_params_free(adev->use_case_table[i]);
9978 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009979 if (adev->adm_deinit)
9980 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309981 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009982 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309983 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309984 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009985 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309986 if (adev->device_cfg_params) {
9987 free(adev->device_cfg_params);
9988 adev->device_cfg_params = NULL;
9989 }
Derek Chend2530072014-11-24 12:39:14 -08009990 if(adev->ext_hw_plugin)
9991 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009992 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009993 free_map(adev->patch_map);
9994 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -07009995 free(device);
9996 adev = NULL;
9997 }
9998 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309999 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010000 return 0;
10001}
10002
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010003/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10004 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10005 * just that it _might_ work.
10006 */
10007static int period_size_is_plausible_for_low_latency(int period_size)
10008{
10009 switch (period_size) {
10010 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010011 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010012 case 240:
10013 case 320:
10014 case 480:
10015 return 1;
10016 default:
10017 return 0;
10018 }
10019}
10020
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010021static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10022{
10023 bool is_snd_card_status = false;
10024 bool is_ext_device_status = false;
10025 char value[32];
10026 int card = -1;
10027 card_status_t status;
10028
10029 if (cookie != adev || !parms)
10030 return;
10031
10032 if (!parse_snd_card_status(parms, &card, &status)) {
10033 is_snd_card_status = true;
10034 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10035 is_ext_device_status = true;
10036 } else {
10037 // not a valid event
10038 return;
10039 }
10040
10041 pthread_mutex_lock(&adev->lock);
10042 if (card == adev->snd_card || is_ext_device_status) {
10043 if (is_snd_card_status && adev->card_status != status) {
10044 adev->card_status = status;
10045 platform_snd_card_update(adev->platform, status);
10046 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010047 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010048 if (status == CARD_STATUS_OFFLINE)
10049 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010050 } else if (is_ext_device_status) {
10051 platform_set_parameters(adev->platform, parms);
10052 }
10053 }
10054 pthread_mutex_unlock(&adev->lock);
10055 return;
10056}
10057
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010058/* out and adev lock held */
10059static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10060{
10061 struct audio_usecase *uc_info;
10062 float left_p;
10063 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010064 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010065
10066 uc_info = get_usecase_from_list(adev, out->usecase);
10067 if (uc_info == NULL) {
10068 ALOGE("%s: Could not find the usecase (%d) in the list",
10069 __func__, out->usecase);
10070 return -EINVAL;
10071 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010072 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010073
10074 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10075 out->usecase, use_case_table[out->usecase]);
10076
10077 if (restore) {
10078 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010079 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010080 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010081 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10082 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010083 pthread_mutex_lock(&out->compr_mute_lock);
10084 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010085 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010086 out->a2dp_compress_mute = false;
10087 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10088 }
10089 pthread_mutex_unlock(&out->compr_mute_lock);
10090 }
10091 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010092 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10093 // mute compress stream if suspended
10094 pthread_mutex_lock(&out->compr_mute_lock);
10095 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010096 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010097 assign_devices(&devices, &out->device_list);
10098 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010099 left_p = out->volume_l;
10100 right_p = out->volume_r;
10101 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10102 compress_pause(out->compr);
10103 out_set_compr_volume(&out->stream, (float)0, (float)0);
10104 out->a2dp_compress_mute = true;
10105 select_devices(adev, out->usecase);
10106 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10107 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010108 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010109 out->volume_l = left_p;
10110 out->volume_r = right_p;
10111 }
Zhou Songc576a452019-09-09 14:17:40 +080010112 pthread_mutex_unlock(&out->compr_mute_lock);
10113 } else {
10114 // tear down a2dp path for non offloaded streams
10115 if (audio_extn_a2dp_source_is_suspended())
10116 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010117 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010118 }
10119 ALOGV("%s: exit", __func__);
10120 return 0;
10121}
10122
10123int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10124{
10125 int ret = 0;
10126
10127 lock_output_stream(out);
10128 pthread_mutex_lock(&adev->lock);
10129
10130 ret = check_a2dp_restore_l(adev, out, restore);
10131
10132 pthread_mutex_unlock(&adev->lock);
10133 pthread_mutex_unlock(&out->lock);
10134 return ret;
10135}
10136
Haynes Mathew George01156f92018-04-13 15:29:54 -070010137void adev_on_battery_status_changed(bool charging)
10138{
10139 pthread_mutex_lock(&adev->lock);
10140 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10141 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010142 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010143 pthread_mutex_unlock(&adev->lock);
10144}
10145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010146static int adev_open(const hw_module_t *module, const char *name,
10147 hw_device_t **device)
10148{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010149 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010150 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010151 char mixer_ctl_name[128] = {0};
10152 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010153
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010154 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010155 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10156
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010157 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010158 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010159 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010160 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010161 ALOGD("%s: returning existing instance of adev", __func__);
10162 ALOGD("%s: exit", __func__);
10163 pthread_mutex_unlock(&adev_init_lock);
10164 return 0;
10165 }
10166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010167 adev = calloc(1, sizeof(struct audio_device));
10168
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010169 if (!adev) {
10170 pthread_mutex_unlock(&adev_init_lock);
10171 return -ENOMEM;
10172 }
10173
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010174 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10175
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010176 // register audio ext hidl at the earliest
10177 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010178#ifdef DYNAMIC_LOG_ENABLED
10179 register_for_dynamic_logging("hal");
10180#endif
10181
Derek Chenf939fb72018-11-13 13:34:41 -080010182 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010183 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010184 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10185 maj_version = atoi(value);
10186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010187 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010188 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010189 adev->device.common.module = (struct hw_module_t *)module;
10190 adev->device.common.close = adev_close;
10191
10192 adev->device.init_check = adev_init_check;
10193 adev->device.set_voice_volume = adev_set_voice_volume;
10194 adev->device.set_master_volume = adev_set_master_volume;
10195 adev->device.get_master_volume = adev_get_master_volume;
10196 adev->device.set_master_mute = adev_set_master_mute;
10197 adev->device.get_master_mute = adev_get_master_mute;
10198 adev->device.set_mode = adev_set_mode;
10199 adev->device.set_mic_mute = adev_set_mic_mute;
10200 adev->device.get_mic_mute = adev_get_mic_mute;
10201 adev->device.set_parameters = adev_set_parameters;
10202 adev->device.get_parameters = adev_get_parameters;
10203 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10204 adev->device.open_output_stream = adev_open_output_stream;
10205 adev->device.close_output_stream = adev_close_output_stream;
10206 adev->device.open_input_stream = adev_open_input_stream;
10207 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010208 adev->device.create_audio_patch = adev_create_audio_patch;
10209 adev->device.release_audio_patch = adev_release_audio_patch;
10210 adev->device.get_audio_port = adev_get_audio_port;
10211 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010212 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010213 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010214
10215 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010216 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010217 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010218 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010219 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010220 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010221 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010222 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010223 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010224 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010225 /* Init audio and voice feature */
10226 audio_extn_feature_init();
10227 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010228 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010229 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010230 list_init(&adev->active_inputs_list);
10231 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010232 list_init(&adev->audio_patch_record_list);
10233 adev->audio_patch_index = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010234 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10235 audio_extn_utils_hash_eq);
10236 if (!adev->io_streams_map) {
10237 ALOGE("%s: Could not create io streams map", __func__);
10238 ret = -ENOMEM;
10239 goto adev_open_err;
10240 }
10241 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10242 audio_extn_utils_hash_eq);
10243 if (!adev->patch_map) {
10244 ALOGE("%s: Could not create audio patch map", __func__);
10245 ret = -ENOMEM;
10246 goto adev_open_err;
10247 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010248 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010249 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010250 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010251 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010252 adev->perf_lock_opts[0] = 0x101;
10253 adev->perf_lock_opts[1] = 0x20E;
10254 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010255 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010256 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010257 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010258 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010260 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010261 adev->platform = platform_init(adev);
10262 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010263 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010264 ret = -EINVAL;
10265 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010266 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010267
Aalique Grahame22e49102018-12-18 14:23:57 -080010268 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010269 if (audio_extn_qap_is_enabled()) {
10270 ret = audio_extn_qap_init(adev);
10271 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010272 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010273 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010274 }
10275 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10276 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10277 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010278
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010279 if (audio_extn_qaf_is_enabled()) {
10280 ret = audio_extn_qaf_init(adev);
10281 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010282 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010283 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010284 }
10285
10286 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10287 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10288 }
10289
Derek Chenae7b0342019-02-08 15:17:04 -080010290 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010291 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10292
Eric Laurentc4aef752013-09-12 17:45:53 -070010293 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10294 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10295 if (adev->visualizer_lib == NULL) {
10296 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10297 } else {
10298 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10299 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010300 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010301 "visualizer_hal_start_output");
10302 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010303 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010304 "visualizer_hal_stop_output");
10305 }
10306 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010307 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010308 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010309 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010310 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010311 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010312 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010313
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010314 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10315 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10316 if (adev->offload_effects_lib == NULL) {
10317 ALOGE("%s: DLOPEN failed for %s", __func__,
10318 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10319 } else {
10320 ALOGV("%s: DLOPEN successful for %s", __func__,
10321 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10322 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010323 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010324 "offload_effects_bundle_hal_start_output");
10325 adev->offload_effects_stop_output =
10326 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10327 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010328 adev->offload_effects_set_hpx_state =
10329 (int (*)(bool))dlsym(adev->offload_effects_lib,
10330 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010331 adev->offload_effects_get_parameters =
10332 (void (*)(struct str_parms *, struct str_parms *))
10333 dlsym(adev->offload_effects_lib,
10334 "offload_effects_bundle_get_parameters");
10335 adev->offload_effects_set_parameters =
10336 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10337 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010338 }
10339 }
10340
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010341 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10342 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10343 if (adev->adm_lib == NULL) {
10344 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10345 } else {
10346 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10347 adev->adm_init = (adm_init_t)
10348 dlsym(adev->adm_lib, "adm_init");
10349 adev->adm_deinit = (adm_deinit_t)
10350 dlsym(adev->adm_lib, "adm_deinit");
10351 adev->adm_register_input_stream = (adm_register_input_stream_t)
10352 dlsym(adev->adm_lib, "adm_register_input_stream");
10353 adev->adm_register_output_stream = (adm_register_output_stream_t)
10354 dlsym(adev->adm_lib, "adm_register_output_stream");
10355 adev->adm_deregister_stream = (adm_deregister_stream_t)
10356 dlsym(adev->adm_lib, "adm_deregister_stream");
10357 adev->adm_request_focus = (adm_request_focus_t)
10358 dlsym(adev->adm_lib, "adm_request_focus");
10359 adev->adm_abandon_focus = (adm_abandon_focus_t)
10360 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010361 adev->adm_set_config = (adm_set_config_t)
10362 dlsym(adev->adm_lib, "adm_set_config");
10363 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10364 dlsym(adev->adm_lib, "adm_request_focus_v2");
10365 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10366 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10367 adev->adm_on_routing_change = (adm_on_routing_change_t)
10368 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010369 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10370 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010371 }
10372 }
10373
Aalique Grahame22e49102018-12-18 14:23:57 -080010374 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010375 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010376 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010377 //initialize this to false for now,
10378 //this will be set to true through set param
10379 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010380
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010381 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010382 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010383
10384 if (k_enable_extended_precision)
10385 adev_verify_devices(adev);
10386
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010387 adev->dsp_bit_width_enforce_mode =
10388 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010389
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010390 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10391 &adev->streams_output_cfg_list,
10392 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010393
Kiran Kandi910e1862013-10-29 13:29:42 -070010394 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010395
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010396 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -080010397 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
10398 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010399 trial = atoi(value);
10400 if (period_size_is_plausible_for_low_latency(trial)) {
10401 pcm_config_low_latency.period_size = trial;
10402 pcm_config_low_latency.start_threshold = trial / 4;
10403 pcm_config_low_latency.avail_min = trial / 4;
10404 configured_low_latency_capture_period_size = trial;
10405 }
10406 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010407 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10408 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010409 trial = atoi(value);
10410 if (period_size_is_plausible_for_low_latency(trial)) {
10411 configured_low_latency_capture_period_size = trial;
10412 }
10413 }
10414
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010415 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10416
Eric Laurent4b084132018-10-19 17:33:43 -070010417 adev->camera_orientation = CAMERA_DEFAULT;
10418
Aalique Grahame22e49102018-12-18 14:23:57 -080010419 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
10420 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010421 af_period_multiplier = atoi(value);
10422 if (af_period_multiplier < 0)
10423 af_period_multiplier = 2;
10424 else if (af_period_multiplier > 4)
10425 af_period_multiplier = 4;
10426
10427 ALOGV("new period_multiplier = %d", af_period_multiplier);
10428 }
10429
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010430 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010431
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010432 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010433 pthread_mutex_unlock(&adev_init_lock);
10434
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010435 if (adev->adm_init)
10436 adev->adm_data = adev->adm_init();
10437
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010438 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010439 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010440 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010441
10442 audio_extn_snd_mon_init();
10443 pthread_mutex_lock(&adev->lock);
10444 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10445 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010446 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10447 /*
10448 * if the battery state callback happens before charging can be queried,
10449 * it will be guarded with the adev->lock held in the cb function and so
10450 * the callback value will reflect the latest state
10451 */
10452 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010453 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010454 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010455 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010456 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010457 /* Allocate memory for Device config params */
10458 adev->device_cfg_params = (struct audio_device_config_param*)
10459 calloc(platform_get_max_codec_backend(),
10460 sizeof(struct audio_device_config_param));
10461 if (adev->device_cfg_params == NULL)
10462 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010463
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010464 /*
10465 * Check if new PSPD matrix mixer control is supported. If not
10466 * supported, then set flag so that old mixer ctrl is sent while
10467 * sending pspd coefficients on older kernel version. Query mixer
10468 * control for default pcm id and channel value one.
10469 */
10470 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10471 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10472
10473 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10474 if (!ctl) {
10475 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10476 __func__, mixer_ctl_name);
10477 adev->use_old_pspd_mix_ctrl = true;
10478 }
10479
Eric Laurent994a6932013-07-17 11:51:42 -070010480 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010481 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010482
10483adev_open_err:
10484 free_map(adev->patch_map);
10485 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010486 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010487 pthread_mutex_destroy(&adev->lock);
10488 free(adev);
10489 adev = NULL;
10490 *device = NULL;
10491 pthread_mutex_unlock(&adev_init_lock);
10492 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010493}
10494
10495static struct hw_module_methods_t hal_module_methods = {
10496 .open = adev_open,
10497};
10498
10499struct audio_module HAL_MODULE_INFO_SYM = {
10500 .common = {
10501 .tag = HARDWARE_MODULE_TAG,
10502 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10503 .hal_api_version = HARDWARE_HAL_API_VERSION,
10504 .id = AUDIO_HARDWARE_MODULE_ID,
10505 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010506 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010507 .methods = &hal_module_methods,
10508 },
10509};