blob: 78f11828c2d44bc20504425ee24a4d9be5b09bc4 [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>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Song1f93fa52020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700151static unsigned int configured_low_latency_capture_period_size =
152 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
153
Haynes Mathew George16081042017-05-31 17:16:49 -0700154#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
155#define MMAP_PERIOD_COUNT_MIN 32
156#define MMAP_PERIOD_COUNT_MAX 512
157#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
158
Aalique Grahame22e49102018-12-18 14:23:57 -0800159/* This constant enables extended precision handling.
160 * TODO The flag is off until more testing is done.
161 */
162static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700163extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800164
Eric Laurentb23d5282013-05-14 15:27:20 -0700165struct pcm_config pcm_config_deep_buffer = {
166 .channels = 2,
167 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
168 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
169 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
172 .stop_threshold = INT_MAX,
173 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
174};
175
176struct pcm_config pcm_config_low_latency = {
177 .channels = 2,
178 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
179 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
180 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
183 .stop_threshold = INT_MAX,
184 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185};
186
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800187struct pcm_config pcm_config_haptics_audio = {
188 .channels = 1,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
191 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
194 .stop_threshold = INT_MAX,
195 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
196};
197
198struct pcm_config pcm_config_haptics = {
199 .channels = 1,
200 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
201 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
202 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
203 .format = PCM_FORMAT_S16_LE,
204 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .stop_threshold = INT_MAX,
206 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209static int af_period_multiplier = 4;
210struct pcm_config pcm_config_rt = {
211 .channels = 2,
212 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
213 .period_size = ULL_PERIOD_SIZE, //1 ms
214 .period_count = 512, //=> buffer size is 512ms
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
217 .stop_threshold = INT_MAX,
218 .silence_threshold = 0,
219 .silence_size = 0,
220 .avail_min = ULL_PERIOD_SIZE, //1 ms
221};
222
Eric Laurentb23d5282013-05-14 15:27:20 -0700223struct pcm_config pcm_config_hdmi_multi = {
224 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
225 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
226 .period_size = HDMI_MULTI_PERIOD_SIZE,
227 .period_count = HDMI_MULTI_PERIOD_COUNT,
228 .format = PCM_FORMAT_S16_LE,
229 .start_threshold = 0,
230 .stop_threshold = INT_MAX,
231 .avail_min = 0,
232};
233
Haynes Mathew George16081042017-05-31 17:16:49 -0700234struct pcm_config pcm_config_mmap_playback = {
235 .channels = 2,
236 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
237 .period_size = MMAP_PERIOD_SIZE,
238 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
239 .format = PCM_FORMAT_S16_LE,
240 .start_threshold = MMAP_PERIOD_SIZE*8,
241 .stop_threshold = INT32_MAX,
242 .silence_threshold = 0,
243 .silence_size = 0,
244 .avail_min = MMAP_PERIOD_SIZE, //1 ms
245};
246
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700247struct pcm_config pcm_config_hifi = {
248 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
249 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
250 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
251 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
252 .format = PCM_FORMAT_S24_3LE,
253 .start_threshold = 0,
254 .stop_threshold = INT_MAX,
255 .avail_min = 0,
256};
257
Eric Laurentb23d5282013-05-14 15:27:20 -0700258struct pcm_config pcm_config_audio_capture = {
259 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
261 .format = PCM_FORMAT_S16_LE,
262};
263
Haynes Mathew George16081042017-05-31 17:16:49 -0700264struct pcm_config pcm_config_mmap_capture = {
265 .channels = 2,
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
267 .period_size = MMAP_PERIOD_SIZE,
268 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
269 .format = PCM_FORMAT_S16_LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .silence_threshold = 0,
273 .silence_size = 0,
274 .avail_min = MMAP_PERIOD_SIZE, //1 ms
275};
276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700277#define AFE_PROXY_CHANNEL_COUNT 2
278#define AFE_PROXY_SAMPLING_RATE 48000
279
280#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
281#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
282
283struct pcm_config pcm_config_afe_proxy_playback = {
284 .channels = AFE_PROXY_CHANNEL_COUNT,
285 .rate = AFE_PROXY_SAMPLING_RATE,
286 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
287 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
288 .format = PCM_FORMAT_S16_LE,
289 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
290 .stop_threshold = INT_MAX,
291 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
292};
293
294#define AFE_PROXY_RECORD_PERIOD_SIZE 768
295#define AFE_PROXY_RECORD_PERIOD_COUNT 4
296
Aalique Grahame22e49102018-12-18 14:23:57 -0800297struct pcm_config pcm_config_audio_capture_rt = {
298 .channels = 2,
299 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
300 .period_size = ULL_PERIOD_SIZE,
301 .period_count = 512,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = 0,
304 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
305 .silence_threshold = 0,
306 .silence_size = 0,
307 .avail_min = ULL_PERIOD_SIZE, //1 ms
308};
309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700310struct pcm_config pcm_config_afe_proxy_record = {
311 .channels = AFE_PROXY_CHANNEL_COUNT,
312 .rate = AFE_PROXY_SAMPLING_RATE,
313 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
314 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
315 .format = PCM_FORMAT_S16_LE,
316 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
317 .stop_threshold = INT_MAX,
318 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
319};
320
Ashish Jainf1eaa582016-05-23 20:54:24 +0530321#define AUDIO_MAX_PCM_FORMATS 7
322
323const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
324 [AUDIO_FORMAT_DEFAULT] = 0,
325 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
326 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
327 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
329 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
330 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
331};
332
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800333const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700334 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
335 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800336 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800337 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700338 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
339 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700340 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700341 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
349 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700350 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
351 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700352 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800353 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700354
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700356 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530357 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
358 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
359 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530360 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
361 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700363 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700364 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700365 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700366
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800367 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800368 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400369 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
370 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700371
Derek Chenf7092792017-05-23 12:23:53 -0400372 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700373 [USECASE_VOICE2_CALL] = "voice2-call",
374 [USECASE_VOLTE_CALL] = "volte-call",
375 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800376 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800377 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
378 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800379 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700380 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
381 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
382 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800383 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
384 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
385 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
386
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700387 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
388 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700389 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
390 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700391
392 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
393 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800394 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530395 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700396
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530397 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
399 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700400
401 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
402 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700424};
425
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426static const audio_usecase_t offload_usecases[] = {
427 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437
Varun Balaraje49253e2017-07-06 19:48:56 +0530438static const audio_usecase_t interactive_usecases[] = {
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
447};
448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449#define STRING_TO_ENUM(string) { #string, string }
450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451struct string_to_enum {
452 const char *name;
453 uint32_t value;
454};
455
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476};
477
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700478static const struct string_to_enum formats_name_to_enum_table[] = {
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700485 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800486 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
487 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800489};
490
491//list of all supported sample rates by HDMI specification.
492static const int out_hdmi_sample_rates[] = {
493 32000, 44100, 48000, 88200, 96000, 176400, 192000,
494};
495
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700496static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800497 STRING_TO_ENUM(32000),
498 STRING_TO_ENUM(44100),
499 STRING_TO_ENUM(48000),
500 STRING_TO_ENUM(88200),
501 STRING_TO_ENUM(96000),
502 STRING_TO_ENUM(176400),
503 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800504 STRING_TO_ENUM(352800),
505 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700506};
507
Carter Hsu2e429db2019-05-14 18:50:52 +0800508struct in_effect_list {
509 struct listnode list;
510 effect_handle_t handle;
511};
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700514static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700515static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700516//cache last MBDRC cal step level
517static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530519static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700520static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800521static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530522static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530523
Derek Chen6f293672019-04-01 01:40:24 -0700524static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
525static void in_snd_mon_cb(void * stream, struct str_parms * parms);
526static void out_snd_mon_cb(void * stream, struct str_parms * parms);
527
Zhou Song331c8e52019-08-26 14:16:12 +0800528static int configure_btsco_sample_rate(snd_device_t snd_device);
529
Vatsal Buchac09ae062018-11-14 13:25:08 +0530530#ifdef AUDIO_FEATURE_ENABLED_GCOV
531extern void __gcov_flush();
532static void enable_gcov()
533{
534 __gcov_flush();
535}
536#else
537static void enable_gcov()
538{
539}
540#endif
541
justinweng20fb6d82019-02-21 18:49:00 -0700542static int in_set_microphone_direction(const struct audio_stream_in *stream,
543 audio_microphone_direction_t dir);
544static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
545
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700546static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
547 int flags __unused)
548{
549 int dir = 0;
550 switch (uc_id) {
551 case USECASE_AUDIO_RECORD_LOW_LATENCY:
552 dir = 1;
553 case USECASE_AUDIO_PLAYBACK_ULL:
554 break;
555 default:
556 return false;
557 }
558
559 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
560 PCM_PLAYBACK : PCM_CAPTURE);
561 if (adev->adm_is_noirq_avail)
562 return adev->adm_is_noirq_avail(adev->adm_data,
563 adev->snd_card, dev_id, dir);
564 return false;
565}
566
567static void register_out_stream(struct stream_out *out)
568{
569 struct audio_device *adev = out->dev;
570 if (is_offload_usecase(out->usecase) ||
571 !adev->adm_register_output_stream)
572 return;
573
574 // register stream first for backward compatibility
575 adev->adm_register_output_stream(adev->adm_data,
576 out->handle,
577 out->flags);
578
579 if (!adev->adm_set_config)
580 return;
581
582 if (out->realtime)
583 adev->adm_set_config(adev->adm_data,
584 out->handle,
585 out->pcm, &out->config);
586}
587
588static void register_in_stream(struct stream_in *in)
589{
590 struct audio_device *adev = in->dev;
591 if (!adev->adm_register_input_stream)
592 return;
593
594 adev->adm_register_input_stream(adev->adm_data,
595 in->capture_handle,
596 in->flags);
597
598 if (!adev->adm_set_config)
599 return;
600
601 if (in->realtime)
602 adev->adm_set_config(adev->adm_data,
603 in->capture_handle,
604 in->pcm,
605 &in->config);
606}
607
608static void request_out_focus(struct stream_out *out, long ns)
609{
610 struct audio_device *adev = out->dev;
611
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700612 if (adev->adm_request_focus_v2)
613 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
614 else if (adev->adm_request_focus)
615 adev->adm_request_focus(adev->adm_data, out->handle);
616}
617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619{
620 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700621 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 if (adev->adm_request_focus_v2_1)
624 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
625 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus)
628 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629
630 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631}
632
633static void release_out_focus(struct stream_out *out)
634{
635 struct audio_device *adev = out->dev;
636
637 if (adev->adm_abandon_focus)
638 adev->adm_abandon_focus(adev->adm_data, out->handle);
639}
640
641static void release_in_focus(struct stream_in *in)
642{
643 struct audio_device *adev = in->dev;
644 if (adev->adm_abandon_focus)
645 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
646}
647
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530648static int parse_snd_card_status(struct str_parms *parms, int *card,
649 card_status_t *status)
650{
651 char value[32]={0};
652 char state[32]={0};
653
654 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
655 if (ret < 0)
656 return -1;
657
658 // sscanf should be okay as value is of max length 32.
659 // same as sizeof state.
660 if (sscanf(value, "%d,%s", card, state) < 2)
661 return -1;
662
663 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
664 CARD_STATUS_OFFLINE;
665 return 0;
666}
667
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668static inline void adjust_frames_for_device_delay(struct stream_out *out,
669 uint32_t *dsp_frames) {
670 // Adjustment accounts for A2dp encoder latency with offload usecases
671 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800672 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700673 unsigned long offset =
674 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
675 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
676 }
677}
678
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700679static inline bool free_entry(void *key __unused,
680 void *value, void *context __unused)
681{
682 free(value);
683 return true;
684}
685
686static inline void free_map(Hashmap *map)
687{
688 if (map) {
689 hashmapForEach(map, free_entry, (void *) NULL);
690 hashmapFree(map);
691 }
692}
693
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800694static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 audio_patch_handle_t patch_handle)
696{
697 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
698 return;
699
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700 struct audio_patch_info *p_info =
701 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
702 if (p_info) {
703 ALOGV("%s: Remove patch %d", __func__, patch_handle);
704 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
705 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700706 free(p_info);
707 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708}
709
710static inline int io_streams_map_insert(struct audio_device *adev,
711 struct audio_stream *stream,
712 audio_io_handle_t handle,
713 audio_patch_handle_t patch_handle)
714{
715 struct audio_stream_info *s_info =
716 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
717
718 if (s_info == NULL) {
719 ALOGE("%s: Could not allocate stream info", __func__);
720 return -ENOMEM;
721 }
722 s_info->stream = stream;
723 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724
725 pthread_mutex_lock(&adev->lock);
726 struct audio_stream_info *stream_info =
727 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700728 if (stream_info != NULL)
729 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800730 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700731 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
732 return 0;
733}
734
735static inline void io_streams_map_remove(struct audio_device *adev,
736 audio_io_handle_t handle)
737{
738 pthread_mutex_lock(&adev->lock);
739 struct audio_stream_info *s_info =
740 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700745 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746done:
747 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return;
749}
750
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 audio_patch_handle_t handle)
753{
754 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700755 p_info = (struct audio_patch_info *)
756 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return p_info;
758}
759
vivek mehtaa76401a2015-04-24 14:12:15 -0700760__attribute__ ((visibility ("default")))
761bool audio_hw_send_gain_dep_calibration(int level) {
762 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700763 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700764
765 pthread_mutex_lock(&adev_init_lock);
766
767 if (adev != NULL && adev->platform != NULL) {
768 pthread_mutex_lock(&adev->lock);
769 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700770
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530771 // cache level info for any of the use case which
772 // was not started.
773 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700774
vivek mehtaa76401a2015-04-24 14:12:15 -0700775 pthread_mutex_unlock(&adev->lock);
776 } else {
777 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
778 }
779
780 pthread_mutex_unlock(&adev_init_lock);
781
782 return ret_val;
783}
784
Ashish Jain5106d362016-05-11 19:23:33 +0530785static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
786{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787 bool gapless_enabled = false;
788 const char *mixer_ctl_name = "Compress Gapless Playback";
789 struct mixer_ctl *ctl;
790
791 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700792 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530793
794 /*Disable gapless if its AV playback*/
795 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796
797 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
798 if (!ctl) {
799 ALOGE("%s: Could not get ctl for mixer cmd - %s",
800 __func__, mixer_ctl_name);
801 return -EINVAL;
802 }
803
804 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
805 ALOGE("%s: Could not set gapless mode %d",
806 __func__, gapless_enabled);
807 return -EINVAL;
808 }
809 return 0;
810}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700811
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700812__attribute__ ((visibility ("default")))
813int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
814 int table_size) {
815 int ret_val = 0;
816 ALOGV("%s: enter ... ", __func__);
817
818 pthread_mutex_lock(&adev_init_lock);
819 if (adev == NULL) {
820 ALOGW("%s: adev is NULL .... ", __func__);
821 goto done;
822 }
823
824 pthread_mutex_lock(&adev->lock);
825 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
826 pthread_mutex_unlock(&adev->lock);
827done:
828 pthread_mutex_unlock(&adev_init_lock);
829 ALOGV("%s: exit ... ", __func__);
830 return ret_val;
831}
832
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800834{
835 bool ret = false;
836 ALOGV("%s: enter ...", __func__);
837
838 pthread_mutex_lock(&adev_init_lock);
839
840 if (adev != NULL && adev->platform != NULL) {
841 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800843 pthread_mutex_unlock(&adev->lock);
844 }
845
846 pthread_mutex_unlock(&adev_init_lock);
847
848 ALOGV("%s: exit with ret %d", __func__, ret);
849 return ret;
850}
Aalique Grahame22e49102018-12-18 14:23:57 -0800851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700852static bool is_supported_format(audio_format_t format)
853{
Eric Laurent86e17132013-09-12 17:49:30 -0700854 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530855 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530856 format == AUDIO_FORMAT_AAC_LC ||
857 format == AUDIO_FORMAT_AAC_HE_V1 ||
858 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530859 format == AUDIO_FORMAT_AAC_ADTS_LC ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
861 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530862 format == AUDIO_FORMAT_AAC_LATM_LC ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
864 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530865 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
866 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530867 format == AUDIO_FORMAT_PCM_FLOAT ||
868 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700869 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530870 format == AUDIO_FORMAT_AC3 ||
871 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700872 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530873 format == AUDIO_FORMAT_DTS ||
874 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530876 format == AUDIO_FORMAT_ALAC ||
877 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530878 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530879 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800880 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530881 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700882 format == AUDIO_FORMAT_APTX ||
883 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800884 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700885
886 return false;
887}
888
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700889static inline bool is_mmap_usecase(audio_usecase_t uc_id)
890{
891 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800892 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700893 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
894}
895
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700896static inline bool is_valid_volume(float left, float right)
897{
898 return ((left >= 0.0f && right >= 0.0f) ? true : false);
899}
900
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530901static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530902{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530903 ALOGV("%s", __func__);
904 audio_route_apply_and_update_path(adev->audio_route,
905 "asrc-mode");
906 adev->asrc_mode_enabled = true;
907}
908
909static void disable_asrc_mode(struct audio_device *adev)
910{
911 ALOGV("%s", __func__);
912 audio_route_reset_and_update_path(adev->audio_route,
913 "asrc-mode");
914 adev->asrc_mode_enabled = false;
915}
916
917/*
918 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
919 * 44.1 or Native DSD backends are enabled for any of current use case.
920 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
921 * - Disable current mix path use case(Headphone backend) and re-enable it with
922 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
923 * e.g. Naitve DSD or Headphone 44.1 -> + 48
924 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530925static void check_and_set_asrc_mode(struct audio_device *adev,
926 struct audio_usecase *uc_info,
927 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530928{
929 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530930 int i, num_new_devices = 0;
931 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
932 /*
933 *Split snd device for new combo use case
934 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
935 */
936 if (platform_split_snd_device(adev->platform,
937 snd_device,
938 &num_new_devices,
939 split_new_snd_devices) == 0) {
940 for (i = 0; i < num_new_devices; i++)
941 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
942 } else {
943 int new_backend_idx = platform_get_backend_index(snd_device);
944 if (((new_backend_idx == HEADPHONE_BACKEND) ||
945 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
946 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
947 !adev->asrc_mode_enabled) {
948 struct listnode *node = NULL;
949 struct audio_usecase *uc = NULL;
950 struct stream_out *curr_out = NULL;
951 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
952 int i, num_devices, ret = 0;
953 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530954
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530955 list_for_each(node, &adev->usecase_list) {
956 uc = node_to_item(node, struct audio_usecase, list);
957 curr_out = (struct stream_out*) uc->stream.out;
958 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
959 /*
960 *Split snd device for existing combo use case
961 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
962 */
963 ret = platform_split_snd_device(adev->platform,
964 uc->out_snd_device,
965 &num_devices,
966 split_snd_devices);
967 if (ret < 0 || num_devices == 0) {
968 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
969 split_snd_devices[0] = uc->out_snd_device;
970 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800971 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530972 for (i = 0; i < num_devices; i++) {
973 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
974 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
975 if((new_backend_idx == HEADPHONE_BACKEND) &&
976 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
977 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
978 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
979 __func__);
980 enable_asrc_mode(adev);
981 break;
982 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
983 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
984 (usecase_backend_idx == HEADPHONE_BACKEND)) {
985 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
986 __func__);
987 disable_audio_route(adev, uc);
988 disable_snd_device(adev, uc->out_snd_device);
989 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
990 if (new_backend_idx == DSD_NATIVE_BACKEND)
991 audio_route_apply_and_update_path(adev->audio_route,
992 "hph-true-highquality-mode");
993 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
994 (curr_out->bit_width >= 24))
995 audio_route_apply_and_update_path(adev->audio_route,
996 "hph-highquality-mode");
997 enable_asrc_mode(adev);
998 enable_snd_device(adev, uc->out_snd_device);
999 enable_audio_route(adev, uc);
1000 break;
1001 }
1002 }
1003 // reset split devices count
1004 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001005 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301006 if (adev->asrc_mode_enabled)
1007 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301008 }
1009 }
1010 }
1011}
1012
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001013static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1014 struct audio_effect_config effect_config,
1015 unsigned int param_value)
1016{
1017 char mixer_ctl_name[] = "Audio Effect";
1018 struct mixer_ctl *ctl;
1019 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001020 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001021
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001022 if (in == NULL) {
1023 ALOGE("%s: active input stream is NULL", __func__);
1024 return -EINVAL;
1025 }
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1028 if (!ctl) {
1029 ALOGE("%s: Could not get mixer ctl - %s",
1030 __func__, mixer_ctl_name);
1031 return -EINVAL;
1032 }
1033
1034 set_values[0] = 1; //0:Rx 1:Tx
1035 set_values[1] = in->app_type_cfg.app_type;
1036 set_values[2] = (long)effect_config.module_id;
1037 set_values[3] = (long)effect_config.instance_id;
1038 set_values[4] = (long)effect_config.param_id;
1039 set_values[5] = param_value;
1040
1041 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1042
1043 return 0;
1044
1045}
1046
1047static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1048 int effect_type, unsigned int *param_value)
1049{
1050 int ret = 0;
1051 struct audio_effect_config other_effect_config;
1052 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001053 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001054
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001055 if (in == NULL) {
1056 ALOGE("%s: active input stream is NULL", __func__);
1057 return -EINVAL;
1058 }
1059
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060 usecase = get_usecase_from_list(adev, in->usecase);
1061 if (!usecase)
1062 return -EINVAL;
1063
1064 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1065 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1066 if (ret < 0) {
1067 ALOGE("%s Failed to get effect params %d", __func__, ret);
1068 return ret;
1069 }
1070
1071 if (module_id == other_effect_config.module_id) {
1072 //Same module id for AEC/NS. Values need to be combined
1073 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1074 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1075 *param_value |= other_effect_config.param_value;
1076 }
1077 }
1078
1079 return ret;
1080}
1081
1082static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301083{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001084 struct audio_effect_config effect_config;
1085 struct audio_usecase *usecase = NULL;
1086 int ret = 0;
1087 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001088 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001089
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001090 if(!voice_extn_is_dynamic_ecns_enabled())
1091 return ENOSYS;
1092
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 if (!in) {
1094 ALOGE("%s: Invalid input stream", __func__);
1095 return -EINVAL;
1096 }
1097
1098 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1099
1100 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001101 if (usecase == NULL) {
1102 ALOGE("%s: Could not find the usecase (%d) in the list",
1103 __func__, in->usecase);
1104 return -EINVAL;
1105 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001106
1107 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1108 if (ret < 0) {
1109 ALOGE("%s Failed to get module id %d", __func__, ret);
1110 return ret;
1111 }
1112 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1113 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1114
1115 if(enable)
1116 param_value = effect_config.param_value;
1117
1118 /*Special handling for AEC & NS effects Param values need to be
1119 updated if module ids are same*/
1120
1121 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1122 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1123 if (ret < 0)
1124 return ret;
1125 }
1126
1127 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1128
1129 return ret;
1130}
1131
1132static void check_and_enable_effect(struct audio_device *adev)
1133{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001134 if(!voice_extn_is_dynamic_ecns_enabled())
1135 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001136
Eric Laurent637e2d42018-11-15 12:24:31 -08001137 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001138
Eric Laurent637e2d42018-11-15 12:24:31 -08001139 if (in != NULL && !in->standby) {
1140 if (in->enable_aec)
1141 enable_disable_effect(adev, EFFECT_AEC, true);
1142
1143 if (in->enable_ns &&
1144 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1145 enable_disable_effect(adev, EFFECT_NS, true);
1146 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147 }
1148}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001150int pcm_ioctl(struct pcm *pcm, int request, ...)
1151{
1152 va_list ap;
1153 void * arg;
1154 int pcm_fd = *(int*)pcm;
1155
1156 va_start(ap, request);
1157 arg = va_arg(ap, void *);
1158 va_end(ap);
1159
1160 return ioctl(pcm_fd, request, arg);
1161}
1162
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001163int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001164 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001167 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301168 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301169 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001170 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301171 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001172
1173 if (usecase == NULL)
1174 return -EINVAL;
1175
1176 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1177
Carter Hsu2e429db2019-05-14 18:50:52 +08001178 if (usecase->type == PCM_CAPTURE) {
1179 struct stream_in *in = usecase->stream.in;
1180 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001182
1183 if (in) {
1184 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001185 list_init(&out_devices);
1186 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 struct listnode *node;
1188 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1189 USECASE_AUDIO_PLAYBACK_VOIP);
1190 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001191 assign_devices(&out_devices,
1192 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001193 } else if (adev->primary_output &&
1194 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001195 assign_devices(&out_devices,
1196 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001197 } else {
1198 list_for_each(node, &adev->usecase_list) {
1199 uinfo = node_to_item(node, struct audio_usecase, list);
1200 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001201 assign_devices(&out_devices,
1202 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001203 break;
1204 }
1205 }
1206 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001207
1208 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001209 in->ec_opened = true;
1210 }
1211 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001212 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1213 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1214 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001215 snd_device = usecase->in_snd_device;
1216 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001219
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001220#ifdef DS1_DOLBY_DAP_ENABLED
1221 audio_extn_dolby_set_dmid(adev);
1222 audio_extn_dolby_set_endpoint(adev);
1223#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001224 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001225 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301226 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001227 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001228 if (audio_extn_is_maxx_audio_enabled())
1229 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301230 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Song1f93fa52020-11-20 13:57:39 +08001231 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1232 out = usecase->stream.out;
1233 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301234 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1235 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301236
1237 if (usecase->type == PCM_CAPTURE) {
1238 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001239 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301240 ALOGD("%s: set custom mtmx params v1", __func__);
1241 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1242 }
1243 } else {
1244 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1245 }
Manish Dewangan58229382017-02-02 15:48:41 +05301246
Andy Hung756ecc12018-10-19 17:47:12 -07001247 // we shouldn't truncate mixer_path
1248 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1249 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1250 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001251 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001252 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301253 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1254 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1255 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1256 if (parms) {
1257 audio_extn_fm_set_parameters(adev, parms);
1258 str_parms_destroy(parms);
1259 }
1260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 ALOGV("%s: exit", __func__);
1262 return 0;
1263}
1264
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001265int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001266 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001268 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001269 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301270 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001271
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301272 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001273 return -EINVAL;
1274
1275 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301276 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device = usecase->in_snd_device;
1278 else
1279 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001280
1281 /* disable island and power mode on supported device for voice call */
1282 if (usecase->type == VOICE_CALL) {
1283 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1284 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1285 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1286 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1287 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1288 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1289 ALOGD("%s: disable island cfg and power mode in voice tx path",
1290 __func__);
1291 }
1292 }
1293 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1294 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1295 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1296 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1297 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1298 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1299 ALOGD("%s: disable island cfg and power mode in voice rx path",
1300 __func__);
1301 }
1302 }
1303 }
1304
Andy Hung756ecc12018-10-19 17:47:12 -07001305 // we shouldn't truncate mixer_path
1306 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1307 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1308 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001309 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001310 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001311 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001312 if (usecase->type == PCM_CAPTURE) {
1313 struct stream_in *in = usecase->stream.in;
1314 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001315 struct listnode out_devices;
1316 list_init(&out_devices);
1317 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001318 in->ec_opened = false;
1319 }
1320 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001321 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301322 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301323
1324 if (usecase->type == PCM_CAPTURE) {
1325 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001326 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327 ALOGD("%s: reset custom mtmx params v1", __func__);
1328 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1329 }
1330 } else {
1331 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1332 }
1333
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001334 if ((usecase->type == PCM_PLAYBACK) &&
1335 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301336 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001338 ALOGV("%s: exit", __func__);
1339 return 0;
1340}
1341
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001342int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001343 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301345 int i, num_devices = 0;
1346 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001347 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1348
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001349 if (snd_device < SND_DEVICE_MIN ||
1350 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001351 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001352 return -EINVAL;
1353 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001355 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001356 ALOGE("%s: Invalid sound device returned", __func__);
1357 return -EINVAL;
1358 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001359
1360 adev->snd_dev_ref_cnt[snd_device]++;
1361
1362 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1363 (platform_split_snd_device(adev->platform,
1364 snd_device,
1365 &num_devices,
1366 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001367 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001368 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001369 /* Set backend config for A2DP to ensure slimbus configuration
1370 is correct if A2DP is already active and backend is closed
1371 and re-opened */
1372 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1373 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374 return 0;
1375 }
1376
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001377 if (audio_extn_spkr_prot_is_enabled())
1378 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001379
Aalique Grahame22e49102018-12-18 14:23:57 -08001380 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1381
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001382 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1383 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1385 goto err;
1386 }
1387 audio_extn_dev_arbi_acquire(snd_device);
1388 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001389 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001390 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001391 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001392 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001393 } else if (platform_split_snd_device(adev->platform,
1394 snd_device,
1395 &num_devices,
1396 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301397 for (i = 0; i < num_devices; i++) {
1398 enable_snd_device(adev, new_snd_devices[i]);
1399 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001400 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001402 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301403
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001404 /* enable island and power mode on supported device */
1405 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1406 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1407 platform_set_island_cfg_on_device(adev, snd_device, true);
1408 platform_set_power_mode_on_device(adev, snd_device, true);
1409 ALOGD("%s: enable island cfg and power mode on: %s",
1410 __func__, device_name);
1411 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301412
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301413 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1414 if (audio_extn_a2dp_start_playback() < 0) {
1415 ALOGE(" fail to configure A2dp Source control path ");
1416 goto err;
1417 } else {
1418 adev->a2dp_started = true;
1419 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001420 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001421
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1423 (audio_extn_a2dp_start_capture() < 0)) {
1424 ALOGE(" fail to configure A2dp Sink control path ");
1425 goto err;
1426 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301427
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001428 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1429 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1430 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1431 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1432 ALOGE(" fail to configure sco control path ");
1433 goto err;
1434 }
Zhou Song12c29502019-03-16 10:37:18 +08001435 }
1436
Zhou Song331c8e52019-08-26 14:16:12 +08001437 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001438 /* due to the possibility of calibration overwrite between listen
1439 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001440 audio_extn_sound_trigger_update_device_status(snd_device,
1441 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301442 audio_extn_listen_update_device_status(snd_device,
1443 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001444 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001445 audio_extn_sound_trigger_update_device_status(snd_device,
1446 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301447 audio_extn_listen_update_device_status(snd_device,
1448 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001449 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001450 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001451 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001452 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301453
1454 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1455 !adev->native_playback_enabled &&
1456 audio_is_true_native_stream_active(adev)) {
1457 ALOGD("%s: %d: napb: enabling native mode in hardware",
1458 __func__, __LINE__);
1459 audio_route_apply_and_update_path(adev->audio_route,
1460 "true-native-mode");
1461 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301462 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301463 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1464 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001465 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001466 ALOGD("%s: init ec ref loopback", __func__);
1467 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001471err:
1472 adev->snd_dev_ref_cnt[snd_device]--;
1473 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474}
1475
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001476int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001477 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301479 int i, num_devices = 0;
1480 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001483 if (snd_device < SND_DEVICE_MIN ||
1484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001486 return -EINVAL;
1487 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001488
1489 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1490 ALOGE("%s: Invalid sound device returned", __func__);
1491 return -EINVAL;
1492 }
1493
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1495 ALOGE("%s: device ref cnt is already 0", __func__);
1496 return -EINVAL;
1497 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001498
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001500
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001501
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001503 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301504
Aalique Grahame22e49102018-12-18 14:23:57 -08001505 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1506
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001507 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1508 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001509 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001510
1511 // when speaker device is disabled, reset swap.
1512 // will be renabled on usecase start
1513 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001514 } else if (platform_split_snd_device(adev->platform,
1515 snd_device,
1516 &num_devices,
1517 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301518 for (i = 0; i < num_devices; i++) {
1519 disable_snd_device(adev, new_snd_devices[i]);
1520 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001521 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001522 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001523 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001524 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001525
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301526 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301527 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301528 adev->a2dp_started = false;
1529 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001530 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001531 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301533 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301535 adev->native_playback_enabled) {
1536 ALOGD("%s: %d: napb: disabling native mode in hardware",
1537 __func__, __LINE__);
1538 audio_route_reset_and_update_path(adev->audio_route,
1539 "true-native-mode");
1540 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001541 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301542 adev->asrc_mode_enabled) {
1543 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301544 disable_asrc_mode(adev);
1545 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301547 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001548 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001549 ALOGD("%s: deinit ec ref loopback", __func__);
1550 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1551 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001552
1553 audio_extn_utils_release_snd_device(snd_device);
1554 } else {
1555 if (platform_split_snd_device(adev->platform,
1556 snd_device,
1557 &num_devices,
1558 new_snd_devices) == 0) {
1559 for (i = 0; i < num_devices; i++) {
1560 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1561 }
1562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 return 0;
1566}
1567
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001568/*
1569 legend:
1570 uc - existing usecase
1571 new_uc - new usecase
1572 d1, d11, d2 - SND_DEVICE enums
1573 a1, a2 - corresponding ANDROID device enums
1574 B1, B2 - backend strings
1575
1576case 1
1577 uc->dev d1 (a1) B1
1578 new_uc->dev d1 (a1), d2 (a2) B1, B2
1579
1580 resolution: disable and enable uc->dev on d1
1581
1582case 2
1583 uc->dev d1 (a1) B1
1584 new_uc->dev d11 (a1) B1
1585
1586 resolution: need to switch uc since d1 and d11 are related
1587 (e.g. speaker and voice-speaker)
1588 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1589
1590case 3
1591 uc->dev d1 (a1) B1
1592 new_uc->dev d2 (a2) B2
1593
1594 resolution: no need to switch uc
1595
1596case 4
1597 uc->dev d1 (a1) B1
1598 new_uc->dev d2 (a2) B1
1599
1600 resolution: disable enable uc-dev on d2 since backends match
1601 we cannot enable two streams on two different devices if they
1602 share the same backend. e.g. if offload is on speaker device using
1603 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1604 using the same backend, offload must also be switched to voice-handset.
1605
1606case 5
1607 uc->dev d1 (a1) B1
1608 new_uc->dev d1 (a1), d2 (a2) B1
1609
1610 resolution: disable enable uc-dev on d2 since backends match
1611 we cannot enable two streams on two different devices if they
1612 share the same backend.
1613
1614case 6
1615 uc->dev d1 (a1) B1
1616 new_uc->dev d2 (a1) B2
1617
1618 resolution: no need to switch
1619
1620case 7
1621 uc->dev d1 (a1), d2 (a2) B1, B2
1622 new_uc->dev d1 (a1) B1
1623
1624 resolution: no need to switch
1625
Zhou Song4ba65882018-07-09 14:48:07 +08001626case 8
1627 uc->dev d1 (a1) B1
1628 new_uc->dev d11 (a1), d2 (a2) B1, B2
1629 resolution: compared to case 1, for this case, d1 and d11 are related
1630 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301631
1632case 9
1633 uc->dev d1 (a1), d2(a2) B1 B2
1634 new_uc->dev d1 (a1), d22 (a2) B1, B2
1635 resolution: disable enable uc-dev on d2 since backends match
1636 we cannot enable two streams on two different devices if they
1637 share the same backend. This is special case for combo use case
1638 with a2dp and sco devices which uses same backend.
1639 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001640*/
1641static snd_device_t derive_playback_snd_device(void * platform,
1642 struct audio_usecase *uc,
1643 struct audio_usecase *new_uc,
1644 snd_device_t new_snd_device)
1645{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001646 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001647
1648 snd_device_t d1 = uc->out_snd_device;
1649 snd_device_t d2 = new_snd_device;
1650
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001651 list_init(&a1);
1652 list_init(&a2);
1653
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301654 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301655 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1657 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 break;
1659 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001660 assign_devices(&a1, &uc->stream.out->device_list);
1661 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301662 break;
1663 }
1664
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001665 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001666 if (!compare_devices(&a1, &a2) &&
1667 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001668 snd_device_t d3[2];
1669 int num_devices = 0;
1670 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001671 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001672 &num_devices,
1673 d3);
1674 if (ret < 0) {
1675 if (ret != -ENOSYS) {
1676 ALOGW("%s failed to split snd_device %d",
1677 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001679 }
1680 goto end;
1681 }
1682
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001683 if (platform_check_backends_match(d3[0], d3[1])) {
1684 return d2; // case 5
1685 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301686 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1687 platform_check_backends_match(d1, d2))
1688 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001689 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301690 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001691 // check if d1 is related to any of d3's
1692 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001693 return d1; // case 1
1694 else
1695 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001696 }
1697 } else {
1698 if (platform_check_backends_match(d1, d2)) {
1699 return d2; // case 2, 4
1700 } else {
1701 return d1; // case 6, 3
1702 }
1703 }
1704
1705end:
1706 return d2; // return whatever was calculated before.
1707}
1708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301710 struct audio_usecase *uc_info,
1711 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712{
1713 struct listnode *node;
1714 struct audio_usecase *usecase;
1715 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301716 snd_device_t uc_derive_snd_device;
1717 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001718 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1719 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001720 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301721 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001722 /*
1723 * This function is to make sure that all the usecases that are active on
1724 * the hardware codec backend are always routed to any one device that is
1725 * handled by the hardware codec.
1726 * For example, if low-latency and deep-buffer usecases are currently active
1727 * on speaker and out_set_parameters(headset) is received on low-latency
1728 * output, then we have to make sure deep-buffer is also switched to headset,
1729 * because of the limitation that both the devices cannot be enabled
1730 * at the same time as they share the same backend.
1731 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001732 /*
1733 * This call is to check if we need to force routing for a particular stream
1734 * If there is a backend configuration change for the device when a
1735 * new stream starts, then ADM needs to be closed and re-opened with the new
1736 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001737 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001738 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001739 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1740 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301741 /* For a2dp device reconfigure all active sessions
1742 * with new AFE encoder format based on a2dp state
1743 */
1744 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301745 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1746 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301747 audio_extn_a2dp_is_force_device_switch()) {
1748 force_routing = true;
1749 force_restart_session = true;
1750 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001751
1752 /*
1753 * Island cfg and power mode config needs to set before AFE port start.
1754 * Set force routing in case of voice device was enable before.
1755 */
1756 if (uc_info->type == VOICE_CALL &&
1757 voice_extn_is_voice_power_mode_supported() &&
1758 platform_check_and_update_island_power_status(adev->platform,
1759 uc_info,
1760 snd_device)) {
1761 force_routing = true;
1762 ALOGD("%s:becf: force routing %d for power mode supported device",
1763 __func__, force_routing);
1764 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301765 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1766
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001768 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001769 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1771 switch_device[i] = false;
1772
1773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001775
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301776 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1777 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301778 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301779 platform_get_snd_device_name(usecase->out_snd_device),
1780 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301781 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1782 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301783 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1784 usecase, uc_info, snd_device);
1785 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001786 (is_codec_backend_out_device_type(&usecase->device_list) ||
1787 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1788 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1789 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1790 is_a2dp_out_device_type(&usecase->device_list) ||
1791 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301792 ((force_restart_session) ||
1793 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301794 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1795 __func__, use_case_table[usecase->id],
1796 platform_get_snd_device_name(usecase->out_snd_device));
1797 disable_audio_route(adev, usecase);
1798 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301799 /* Enable existing usecase on derived playback device */
1800 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301801 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301802 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803 }
1804 }
1805
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301806 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1807 num_uc_to_switch);
1808
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001809 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001810 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301812 /* Make sure the previous devices to be disabled first and then enable the
1813 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 list_for_each(node, &adev->usecase_list) {
1815 usecase = node_to_item(node, struct audio_usecase, list);
1816 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001817 /* Check if output sound device to be switched can be split and if any
1818 of the split devices match with derived sound device */
1819 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1820 &num_devices, split_snd_devices) == 0) {
1821 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1822 for (i = 0; i < num_devices; i++) {
1823 /* Disable devices that do not match with derived sound device */
1824 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1825 disable_snd_device(adev, split_snd_devices[i]);
1826 }
1827 } else {
1828 disable_snd_device(adev, usecase->out_snd_device);
1829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 }
1831 }
1832
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001833 list_for_each(node, &adev->usecase_list) {
1834 usecase = node_to_item(node, struct audio_usecase, list);
1835 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001836 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1837 &num_devices, split_snd_devices) == 0) {
1838 /* Enable derived sound device only if it does not match with
1839 one of the split sound devices. This is because the matching
1840 sound device was not disabled */
1841 bool should_enable = true;
1842 for (i = 0; i < num_devices; i++) {
1843 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1844 should_enable = false;
1845 break;
1846 }
1847 }
1848 if (should_enable)
1849 enable_snd_device(adev, derive_snd_device[usecase->id]);
1850 } else {
1851 enable_snd_device(adev, derive_snd_device[usecase->id]);
1852 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001853 }
1854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 /* Re-route all the usecases on the shared backend other than the
1857 specified usecase to new snd devices */
1858 list_for_each(node, &adev->usecase_list) {
1859 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301860 /* Update the out_snd_device only before enabling the audio route */
1861 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301862 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301863 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1864 use_case_table[usecase->id],
1865 platform_get_snd_device_name(usecase->out_snd_device));
1866 /* Update voc calibration before enabling Voice/VoIP route */
1867 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1868 status = platform_switch_voice_call_device_post(adev->platform,
1869 usecase->out_snd_device,
1870 platform_get_input_snd_device(
1871 adev->platform, NULL,
1872 &uc_info->device_list,
1873 usecase->type));
1874 enable_audio_route(adev, usecase);
1875 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1876 out_set_voip_volume(&usecase->stream.out->stream,
1877 usecase->stream.out->volume_l,
1878 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880 }
1881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 }
1883}
1884
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301885static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001886 struct audio_usecase *uc_info,
1887 snd_device_t snd_device)
1888{
1889 struct listnode *node;
1890 struct audio_usecase *usecase;
1891 bool switch_device[AUDIO_USECASE_MAX];
1892 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001893 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001894 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001895
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301896 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1897 snd_device);
1898 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301899
1900 /*
1901 * Make sure out devices is checked against out codec backend device and
1902 * also in devices against in codec backend. Checking out device against in
1903 * codec backend or vice versa causes issues.
1904 */
1905 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001906 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001907
1908 /*
1909 * Island cfg and power mode config needs to set before AFE port start.
1910 * Set force routing in case of voice device was enable before.
1911 */
1912
1913 if (uc_info->type == VOICE_CALL &&
1914 voice_extn_is_voice_power_mode_supported() &&
1915 platform_check_and_update_island_power_status(adev->platform,
1916 uc_info,
1917 snd_device)) {
1918 force_routing = true;
1919 ALOGD("%s:becf: force routing %d for power mode supported device",
1920 __func__, force_routing);
1921 }
1922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 /*
1924 * This function is to make sure that all the active capture usecases
1925 * are always routed to the same input sound device.
1926 * For example, if audio-record and voice-call usecases are currently
1927 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1928 * is received for voice call then we have to make sure that audio-record
1929 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1930 * because of the limitation that two devices cannot be enabled
1931 * at the same time if they share the same backend.
1932 */
1933 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1934 switch_device[i] = false;
1935
1936 list_for_each(node, &adev->usecase_list) {
1937 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301938 /*
1939 * TODO: Enhance below condition to handle BT sco/USB multi recording
1940 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301941
1942 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1943 (usecase->in_snd_device != snd_device || force_routing));
1944 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1945 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1946 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001947 ((backend_check_cond &&
1948 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001949 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001950 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001951 is_single_device_type_equal(&usecase->device_list,
1952 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001953 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001954 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001955 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301956 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001957 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001958 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001959 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001960 switch_device[usecase->id] = true;
1961 num_uc_to_switch++;
1962 }
1963 }
1964
1965 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001966 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001967
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301968 /* Make sure the previous devices to be disabled first and then enable the
1969 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001970 list_for_each(node, &adev->usecase_list) {
1971 usecase = node_to_item(node, struct audio_usecase, list);
1972 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001973 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001974 }
1975 }
1976
1977 list_for_each(node, &adev->usecase_list) {
1978 usecase = node_to_item(node, struct audio_usecase, list);
1979 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001981 }
1982 }
1983
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001984 /* Re-route all the usecases on the shared backend other than the
1985 specified usecase to new snd devices */
1986 list_for_each(node, &adev->usecase_list) {
1987 usecase = node_to_item(node, struct audio_usecase, list);
1988 /* Update the in_snd_device only before enabling the audio route */
1989 if (switch_device[usecase->id] ) {
1990 usecase->in_snd_device = snd_device;
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301991 /* Update voc calibration before enabling Voice/VoIP route */
1992 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1993 snd_device_t voip_snd_device;
1994 voip_snd_device = platform_get_output_snd_device(adev->platform,
1995 usecase->stream.out,
1996 usecase->type);
1997 status = platform_switch_voice_call_device_post(adev->platform,
1998 voip_snd_device,
1999 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002000 }
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302001 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002002 }
2003 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002004 }
2005}
2006
Mingming Yin3a941d42016-02-17 18:08:05 -08002007static void reset_hdmi_sink_caps(struct stream_out *out) {
2008 int i = 0;
2009
2010 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2011 out->supported_channel_masks[i] = 0;
2012 }
2013 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2014 out->supported_formats[i] = 0;
2015 }
2016 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2017 out->supported_sample_rates[i] = 0;
2018 }
2019}
2020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002022static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023{
Mingming Yin3a941d42016-02-17 18:08:05 -08002024 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002025 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2026 out->extconn.cs.controller,
2027 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028
Mingming Yin3a941d42016-02-17 18:08:05 -08002029 reset_hdmi_sink_caps(out);
2030
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002031 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002032 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002033 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002034 out->extconn.cs.stream);
2035 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002036 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002037 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002038 }
2039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002042 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002043 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002044 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2045 case 6:
2046 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2047 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2048 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2049 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2050 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2051 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 break;
2053 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002054 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002055 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 break;
2057 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002058
2059 // check channel format caps
2060 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002061 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2062 out->extconn.cs.controller,
2063 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002064 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2065 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2066 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2067 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2068 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2069 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2070 }
2071
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002072 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2073 out->extconn.cs.controller,
2074 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002075 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2076 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2077 }
2078
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002079 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2080 out->extconn.cs.controller,
2081 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002082 ALOGV(":%s HDMI supports DTS format", __func__);
2083 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2084 }
2085
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002086 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2087 out->extconn.cs.controller,
2088 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002089 ALOGV(":%s HDMI supports DTS HD format", __func__);
2090 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2091 }
2092
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002093 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2094 out->extconn.cs.controller,
2095 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002096 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2097 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2098 }
2099
Mingming Yin3a941d42016-02-17 18:08:05 -08002100
2101 // check sample rate caps
2102 i = 0;
2103 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002104 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2105 out->extconn.cs.controller,
2106 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002107 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2108 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2109 }
2110 }
2111
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002112 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113}
2114
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002115static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2116 uint32_t *supported_sample_rates __unused,
2117 uint32_t max_rates __unused)
2118{
2119 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2120 supported_sample_rates,
2121 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302122 ssize_t i = 0;
2123
2124 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002125 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2126 supported_sample_rates[i]);
2127 }
2128 return count;
2129}
2130
2131static inline int read_usb_sup_channel_masks(bool is_playback,
2132 audio_channel_mask_t *supported_channel_masks,
2133 uint32_t max_masks)
2134{
2135 int channels = audio_extn_usb_get_max_channels(is_playback);
2136 int channel_count;
2137 uint32_t num_masks = 0;
2138 if (channels > MAX_HIFI_CHANNEL_COUNT)
2139 channels = MAX_HIFI_CHANNEL_COUNT;
2140
2141 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002142 // start from 2 channels as framework currently doesn't support mono.
2143 if (channels >= FCC_2) {
2144 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2145 }
2146 for (channel_count = FCC_2;
2147 channel_count <= channels && num_masks < max_masks;
2148 ++channel_count) {
2149 supported_channel_masks[num_masks++] =
2150 audio_channel_mask_for_index_assignment_from_count(channel_count);
2151 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002152 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002153 // For capture we report all supported channel masks from 1 channel up.
2154 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002155 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2156 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002157 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2158 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2159 if (channel_count <= FCC_2) {
2160 mask = audio_channel_in_mask_from_count(channel_count);
2161 supported_channel_masks[num_masks++] = mask;
2162 }
2163 const audio_channel_mask_t index_mask =
2164 audio_channel_mask_for_index_assignment_from_count(channel_count);
2165 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2166 supported_channel_masks[num_masks++] = index_mask;
2167 }
2168 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002169 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302170
vincenttewf51c94e2019-05-07 10:28:53 +08002171 for (size_t i = 0; i < num_masks; ++i) {
2172 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2173 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302174 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002175 return num_masks;
2176}
2177
2178static inline int read_usb_sup_formats(bool is_playback __unused,
2179 audio_format_t *supported_formats,
2180 uint32_t max_formats __unused)
2181{
2182 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2183 switch (bitwidth) {
2184 case 24:
2185 // XXX : usb.c returns 24 for s24 and s24_le?
2186 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2187 break;
2188 case 32:
2189 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2190 break;
2191 case 16:
2192 default :
2193 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2194 break;
2195 }
2196 ALOGV("%s: %s supported format %d", __func__,
2197 is_playback ? "P" : "C", bitwidth);
2198 return 1;
2199}
2200
2201static inline int read_usb_sup_params_and_compare(bool is_playback,
2202 audio_format_t *format,
2203 audio_format_t *supported_formats,
2204 uint32_t max_formats,
2205 audio_channel_mask_t *mask,
2206 audio_channel_mask_t *supported_channel_masks,
2207 uint32_t max_masks,
2208 uint32_t *rate,
2209 uint32_t *supported_sample_rates,
2210 uint32_t max_rates) {
2211 int ret = 0;
2212 int num_formats;
2213 int num_masks;
2214 int num_rates;
2215 int i;
2216
2217 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2218 max_formats);
2219 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2220 max_masks);
2221
2222 num_rates = read_usb_sup_sample_rates(is_playback,
2223 supported_sample_rates, max_rates);
2224
2225#define LUT(table, len, what, dflt) \
2226 for (i=0; i<len && (table[i] != what); i++); \
2227 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2228
2229 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2230 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2231 LUT(supported_sample_rates, num_rates, *rate, 0);
2232
2233#undef LUT
2234 return ret < 0 ? -EINVAL : 0; // HACK TBD
2235}
2236
Alexy Josephb1379942016-01-29 15:49:38 -08002237audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002238 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002239{
2240 struct audio_usecase *usecase;
2241 struct listnode *node;
2242
2243 list_for_each(node, &adev->usecase_list) {
2244 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002245 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002246 ALOGV("%s: usecase id %d", __func__, usecase->id);
2247 return usecase->id;
2248 }
2249 }
2250 return USECASE_INVALID;
2251}
2252
Alexy Josephb1379942016-01-29 15:49:38 -08002253struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002254 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255{
2256 struct audio_usecase *usecase;
2257 struct listnode *node;
2258
2259 list_for_each(node, &adev->usecase_list) {
2260 usecase = node_to_item(node, struct audio_usecase, list);
2261 if (usecase->id == uc_id)
2262 return usecase;
2263 }
2264 return NULL;
2265}
2266
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302267/*
2268 * is a true native playback active
2269 */
2270bool audio_is_true_native_stream_active(struct audio_device *adev)
2271{
2272 bool active = false;
2273 int i = 0;
2274 struct listnode *node;
2275
2276 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2277 ALOGV("%s:napb: not in true mode or non hdphones device",
2278 __func__);
2279 active = false;
2280 goto exit;
2281 }
2282
2283 list_for_each(node, &adev->usecase_list) {
2284 struct audio_usecase *uc;
2285 uc = node_to_item(node, struct audio_usecase, list);
2286 struct stream_out *curr_out =
2287 (struct stream_out*) uc->stream.out;
2288
2289 if (curr_out && PCM_PLAYBACK == uc->type) {
2290 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2291 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2292 uc->id, curr_out->sample_rate,
2293 curr_out->bit_width,
2294 platform_get_snd_device_name(uc->out_snd_device));
2295
2296 if (is_offload_usecase(uc->id) &&
2297 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2298 active = true;
2299 ALOGD("%s:napb:native stream detected", __func__);
2300 }
2301 }
2302 }
2303exit:
2304 return active;
2305}
2306
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002307uint32_t adev_get_dsp_bit_width_enforce_mode()
2308{
2309 if (adev == NULL) {
2310 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2311 return 0;
2312 }
2313 return adev->dsp_bit_width_enforce_mode;
2314}
2315
2316static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2317{
2318 char value[PROPERTY_VALUE_MAX];
2319 int trial;
2320 uint32_t dsp_bit_width_enforce_mode = 0;
2321
2322 if (!mixer) {
2323 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2324 __func__);
2325 return 0;
2326 }
2327
2328 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2329 value, NULL) > 0) {
2330 trial = atoi(value);
2331 switch (trial) {
2332 case 16:
2333 dsp_bit_width_enforce_mode = 16;
2334 break;
2335 case 24:
2336 dsp_bit_width_enforce_mode = 24;
2337 break;
2338 case 32:
2339 dsp_bit_width_enforce_mode = 32;
2340 break;
2341 default:
2342 dsp_bit_width_enforce_mode = 0;
2343 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2344 break;
2345 }
2346 }
2347
2348 return dsp_bit_width_enforce_mode;
2349}
2350
2351static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2352 uint32_t enforce_mode,
2353 bool enable)
2354{
2355 struct mixer_ctl *ctl = NULL;
2356 const char *mixer_ctl_name = "ASM Bit Width";
2357 uint32_t asm_bit_width_mode = 0;
2358
2359 if (enforce_mode == 0) {
2360 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2361 return;
2362 }
2363
2364 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2365 if (!ctl) {
2366 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2367 __func__, mixer_ctl_name);
2368 return;
2369 }
2370
2371 if (enable)
2372 asm_bit_width_mode = enforce_mode;
2373 else
2374 asm_bit_width_mode = 0;
2375
2376 ALOGV("%s DSP bit width feature status is %d width=%d",
2377 __func__, enable, asm_bit_width_mode);
2378 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2379 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2380 asm_bit_width_mode);
2381
2382 return;
2383}
2384
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302385/*
2386 * if native DSD playback active
2387 */
2388bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2389{
2390 bool active = false;
2391 struct listnode *node = NULL;
2392 struct audio_usecase *uc = NULL;
2393 struct stream_out *curr_out = NULL;
2394
2395 list_for_each(node, &adev->usecase_list) {
2396 uc = node_to_item(node, struct audio_usecase, list);
2397 curr_out = (struct stream_out*) uc->stream.out;
2398
2399 if (curr_out && PCM_PLAYBACK == uc->type &&
2400 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2401 active = true;
2402 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302403 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302404 }
2405 }
2406 return active;
2407}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302408
2409static bool force_device_switch(struct audio_usecase *usecase)
2410{
2411 bool ret = false;
2412 bool is_it_true_mode = false;
2413
Zhou Song30f2c3e2018-02-08 14:02:15 +08002414 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302415 usecase->type == TRANSCODE_LOOPBACK_RX ||
2416 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002417 return false;
2418 }
2419
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002420 if(usecase->stream.out == NULL) {
2421 ALOGE("%s: stream.out is NULL", __func__);
2422 return false;
2423 }
2424
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302425 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002426 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002427 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2428 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302429 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2430 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2431 (!is_it_true_mode && adev->native_playback_enabled)){
2432 ret = true;
2433 ALOGD("napb: time to toggle native mode");
2434 }
2435 }
2436
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302437 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302438 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2439 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002440 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302441 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302442 ALOGD("Force a2dp device switch to update new encoder config");
2443 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002444 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302445
Florian Pfister1a84f312018-07-19 14:38:18 +02002446 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302447 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2448 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002449 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302450 return ret;
2451}
2452
Aalique Grahame22e49102018-12-18 14:23:57 -08002453static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2454{
2455 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2456}
2457
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302458bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2459{
2460 bool ret=false;
2461 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002462 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2463 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302464 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2465 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002466 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002468 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2469 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302470 ret = true;
2471
2472 return ret;
2473}
2474
2475bool is_a2dp_device(snd_device_t out_snd_device)
2476{
2477 bool ret=false;
2478 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2479 ret = true;
2480
2481 return ret;
2482}
2483
2484bool is_bt_soc_on(struct audio_device *adev)
2485{
2486 struct mixer_ctl *ctl;
2487 char *mixer_ctl_name = "BT SOC status";
2488 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2489 bool bt_soc_status = true;
2490 if (!ctl) {
2491 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2492 __func__, mixer_ctl_name);
2493 /*This is to ensure we dont break targets which dont have the kernel change*/
2494 return true;
2495 }
2496 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2497 ALOGD("BT SOC status: %d",bt_soc_status);
2498 return bt_soc_status;
2499}
2500
Zhou Song331c8e52019-08-26 14:16:12 +08002501static int configure_btsco_sample_rate(snd_device_t snd_device)
2502{
2503 struct mixer_ctl *ctl = NULL;
2504 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2505 char *rate_str = NULL;
2506 bool is_rx_dev = true;
2507
2508 if (is_btsco_device(snd_device, snd_device)) {
2509 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2510 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2511 if (!ctl_sr_tx || !ctl_sr_rx) {
2512 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2513 if (!ctl_sr)
2514 return -ENOSYS;
2515 }
2516
2517 switch (snd_device) {
2518 case SND_DEVICE_OUT_BT_SCO:
2519 rate_str = "KHZ_8";
2520 break;
2521 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2522 case SND_DEVICE_IN_BT_SCO_MIC:
2523 rate_str = "KHZ_8";
2524 is_rx_dev = false;
2525 break;
2526 case SND_DEVICE_OUT_BT_SCO_WB:
2527 rate_str = "KHZ_16";
2528 break;
2529 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2530 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2531 rate_str = "KHZ_16";
2532 is_rx_dev = false;
2533 break;
2534 default:
2535 return 0;
2536 }
2537
2538 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2539 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2540 return -ENOSYS;
2541 }
2542 return 0;
2543}
2544
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302545int out_standby_l(struct audio_stream *stream);
2546
Eric Laurent637e2d42018-11-15 12:24:31 -08002547struct stream_in *adev_get_active_input(const struct audio_device *adev)
2548{
2549 struct listnode *node;
2550 struct stream_in *last_active_in = NULL;
2551
2552 /* Get last added active input.
2553 * TODO: We may use a priority mechanism to pick highest priority active source */
2554 list_for_each(node, &adev->usecase_list)
2555 {
2556 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2557 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2558 last_active_in = usecase->stream.in;
2559 }
2560
2561 return last_active_in;
2562}
2563
2564struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2565{
2566 struct listnode *node;
2567
2568 /* First check active inputs with voice communication source and then
2569 * any input if audio mode is in communication */
2570 list_for_each(node, &adev->usecase_list)
2571 {
2572 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2573 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2574 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2575 return usecase->stream.in;
2576 }
2577 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2578 return adev_get_active_input(adev);
2579
2580 return NULL;
2581}
2582
Carter Hsu2e429db2019-05-14 18:50:52 +08002583/*
2584 * Aligned with policy.h
2585 */
2586static inline int source_priority(int inputSource)
2587{
2588 switch (inputSource) {
2589 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2590 return 9;
2591 case AUDIO_SOURCE_CAMCORDER:
2592 return 8;
2593 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2594 return 7;
2595 case AUDIO_SOURCE_UNPROCESSED:
2596 return 6;
2597 case AUDIO_SOURCE_MIC:
2598 return 5;
2599 case AUDIO_SOURCE_ECHO_REFERENCE:
2600 return 4;
2601 case AUDIO_SOURCE_FM_TUNER:
2602 return 3;
2603 case AUDIO_SOURCE_VOICE_RECOGNITION:
2604 return 2;
2605 case AUDIO_SOURCE_HOTWORD:
2606 return 1;
2607 default:
2608 break;
2609 }
2610 return 0;
2611}
2612
2613static struct stream_in *get_priority_input(struct audio_device *adev)
2614{
2615 struct listnode *node;
2616 struct audio_usecase *usecase;
2617 int last_priority = 0, priority;
2618 struct stream_in *priority_in = NULL;
2619 struct stream_in *in;
2620
2621 list_for_each(node, &adev->usecase_list) {
2622 usecase = node_to_item(node, struct audio_usecase, list);
2623 if (usecase->type == PCM_CAPTURE) {
2624 in = usecase->stream.in;
2625 if (!in)
2626 continue;
2627 priority = source_priority(in->source);
2628
2629 if (priority > last_priority) {
2630 last_priority = priority;
2631 priority_in = in;
2632 }
2633 }
2634 }
2635 return priority_in;
2636}
2637
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002638int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002640 snd_device_t out_snd_device = SND_DEVICE_NONE;
2641 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642 struct audio_usecase *usecase = NULL;
2643 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002644 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002645 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302646 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002647 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002648 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302650 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002652 usecase = get_usecase_from_list(adev, uc_id);
2653 if (usecase == NULL) {
2654 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2655 return -EINVAL;
2656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002658 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002659 (usecase->type == VOIP_CALL) ||
2660 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302661 if(usecase->stream.out == NULL) {
2662 ALOGE("%s: stream.out is NULL", __func__);
2663 return -EINVAL;
2664 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002665 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002666 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2667 uc_id);
2668 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2669 uc_id);
2670 } else {
2671 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302672 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002673 in_snd_device = platform_get_input_snd_device(adev->platform,
2674 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302675 &usecase->stream.out->device_list,
2676 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002677 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002678 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302679 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302680 if (usecase->stream.inout == NULL) {
2681 ALOGE("%s: stream.inout is NULL", __func__);
2682 return -EINVAL;
2683 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002684 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302685 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2686 stream_out.format = usecase->stream.inout->out_config.format;
2687 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302688 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002689 assign_devices(&usecase->device_list,
2690 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302691 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2692 if (usecase->stream.inout == NULL) {
2693 ALOGE("%s: stream.inout is NULL", __func__);
2694 return -EINVAL;
2695 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302696 struct listnode out_devices;
2697 list_init(&out_devices);
2698 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2699 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002700 assign_devices(&usecase->device_list,
2701 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 } else {
2703 /*
2704 * If the voice call is active, use the sound devices of voice call usecase
2705 * so that it would not result any device switch. All the usecases will
2706 * be switched to new device when select_devices() is called for voice call
2707 * usecase. This is to avoid switching devices for voice call when
2708 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002709 * choose voice call device only if the use case device is
2710 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002712 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002713 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002714 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002715 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2716 is_codec_backend_out_device_type(&usecase->device_list)) ||
2717 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2718 is_codec_backend_in_device_type(&usecase->device_list)) ||
2719 is_single_device_type_equal(&vc_usecase->device_list,
2720 AUDIO_DEVICE_OUT_HEARING_AID) ||
2721 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002722 AUDIO_DEVICE_IN_VOICE_CALL) ||
2723 (is_single_device_type_equal(&usecase->device_list,
2724 AUDIO_DEVICE_IN_USB_HEADSET) &&
2725 is_single_device_type_equal(&vc_usecase->device_list,
2726 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 in_snd_device = vc_usecase->in_snd_device;
2728 out_snd_device = vc_usecase->out_snd_device;
2729 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002730 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002731 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002732 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002733 if ((voip_usecase != NULL) &&
2734 (usecase->type == PCM_PLAYBACK) &&
2735 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002736 out_snd_device_backend_match = platform_check_backends_match(
2737 voip_usecase->out_snd_device,
2738 platform_get_output_snd_device(
2739 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302740 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002741 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002742 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2743 (is_codec_backend_out_device_type(&usecase->device_list) ||
2744 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002745 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002746 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002747 in_snd_device = voip_usecase->in_snd_device;
2748 out_snd_device = voip_usecase->out_snd_device;
2749 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002750 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002751 hfp_ucid = audio_extn_hfp_get_usecase();
2752 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002753 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002754 in_snd_device = hfp_usecase->in_snd_device;
2755 out_snd_device = hfp_usecase->out_snd_device;
2756 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002757 }
2758 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302759 if (usecase->stream.out == NULL) {
2760 ALOGE("%s: stream.out is NULL", __func__);
2761 return -EINVAL;
2762 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002763 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002765 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002766 struct stream_out *voip_out = adev->primary_output;
2767 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002768 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002769 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2770 else
2771 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 usecase->stream.out,
2773 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002774 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002775
Eric Laurent637e2d42018-11-15 12:24:31 -08002776 if (voip_usecase)
2777 voip_out = voip_usecase->stream.out;
2778
2779 if (usecase->stream.out == voip_out && voip_in != NULL)
2780 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002782 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302783 if (usecase->stream.in == NULL) {
2784 ALOGE("%s: stream.in is NULL", __func__);
2785 return -EINVAL;
2786 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002787 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002788 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002789 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002791 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002792 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002793
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002794 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002795 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002796 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2797 USECASE_AUDIO_PLAYBACK_VOIP);
2798
Carter Hsu2e429db2019-05-14 18:50:52 +08002799 usecase->stream.in->enable_ec_port = false;
2800
Zhou Song62ea0282020-03-22 19:53:01 +08002801 bool is_ha_usecase = adev->ha_proxy_enable ?
2802 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2803 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2804 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002805 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002806 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002808 } else if (adev->primary_output &&
2809 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002810 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002811 } else {
2812 /* forcing speaker o/p device to get matching i/p pair
2813 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002816 priority_in = voip_in;
2817 } else {
2818 /* get the input with the highest priority source*/
2819 priority_in = get_priority_input(adev);
2820
2821 if (!priority_in)
2822 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002823 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002824
Eric Laurent637e2d42018-11-15 12:24:31 -08002825 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002826 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302827 &out_devices,
2828 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002830 }
2831 }
2832
2833 if (out_snd_device == usecase->out_snd_device &&
2834 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302835
2836 if (!force_device_switch(usecase))
2837 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
2839
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002840 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002841 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002842 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002843 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2844 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302845 }
2846
Aalique Grahame22e49102018-12-18 14:23:57 -08002847 if (out_snd_device != SND_DEVICE_NONE &&
2848 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2849 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2850 __func__,
2851 use_case_table[uc_id],
2852 adev->last_logged_snd_device[uc_id][0],
2853 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2854 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2855 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2856 -1,
2857 out_snd_device,
2858 platform_get_snd_device_name(out_snd_device),
2859 platform_get_snd_device_acdb_id(out_snd_device));
2860 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2861 }
2862 if (in_snd_device != SND_DEVICE_NONE &&
2863 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2864 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2865 __func__,
2866 use_case_table[uc_id],
2867 adev->last_logged_snd_device[uc_id][1],
2868 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2869 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2870 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2871 -1,
2872 in_snd_device,
2873 platform_get_snd_device_name(in_snd_device),
2874 platform_get_snd_device_acdb_id(in_snd_device));
2875 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2876 }
2877
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 /*
2880 * Limitation: While in call, to do a device switch we need to disable
2881 * and enable both RX and TX devices though one of them is same as current
2882 * device.
2883 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002884 if ((usecase->type == VOICE_CALL) &&
2885 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2886 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002887 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002888 }
2889
2890 if (((usecase->type == VOICE_CALL) ||
2891 (usecase->type == VOIP_CALL)) &&
2892 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2893 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302894 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002895 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002896 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002897
2898 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302899 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002900 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002901 }
2902
Aalique Grahame22e49102018-12-18 14:23:57 -08002903 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2904 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002905 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302906 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002907 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2908 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2909 else
2910 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302911 }
2912
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002913 /* Disable current sound devices */
2914 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002915 disable_audio_route(adev, usecase);
2916 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 }
2918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002919 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002920 disable_audio_route(adev, usecase);
2921 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 }
2923
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002924 /* Applicable only on the targets that has external modem.
2925 * New device information should be sent to modem before enabling
2926 * the devices to reduce in-call device switch time.
2927 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002928 if ((usecase->type == VOICE_CALL) &&
2929 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2930 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002931 status = platform_switch_voice_call_enable_device_config(adev->platform,
2932 out_snd_device,
2933 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002934 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 /* Enable new sound devices */
2937 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002938 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302939 if (platform_check_codec_asrc_support(adev->platform))
2940 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002941 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002944 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302945 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002946 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002948
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302949 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07002950 status = platform_switch_voice_call_device_post(adev->platform,
2951 out_snd_device,
2952 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002953
sangwoo170731f2013-06-08 15:36:36 +09002954 usecase->in_snd_device = in_snd_device;
2955 usecase->out_snd_device = out_snd_device;
2956
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302957 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2958 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302959 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002960 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002961 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002962 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2963 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2964 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2965 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2966 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2967 /*
2968 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2969 * configured device sample rate, if not update the COPP rate to be equal to the
2970 * device sample rate, else open COPP at stream sample rate
2971 */
2972 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2973 usecase->stream.out->sample_rate,
2974 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302975 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302976 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2977 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302978 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002979 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2980 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2981 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2982 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002983 }
2984 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002985
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002986 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002987
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002988 /* If input stream is already running then effect needs to be
2989 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002990 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002991 check_and_enable_effect(adev);
2992
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002993 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002994 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302995 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002996 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2997
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002998 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302999 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003000 voice_extn_compress_voip_is_started(adev))
3001 voice_set_sidetone(adev, out_snd_device, true);
3002 }
3003
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003004 /* Applicable only on the targets that has external modem.
3005 * Enable device command should be sent to modem only after
3006 * enabling voice call mixer controls
3007 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003008 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003009 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3010 out_snd_device,
3011 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303012
3013 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003014 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303015 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003016 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303017 if (is_bt_soc_on(adev) == false){
3018 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003019 if (in->pcm != NULL)
3020 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303021 }
3022 }
3023 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3024 && usecase->stream.out->started) {
3025 if (is_bt_soc_on(adev) == false) {
3026 ALOGD("BT SCO/A2DP disconnected while in connection");
3027 out_standby_l(&usecase->stream.out->stream.common);
3028 }
3029 }
3030 } else if ((usecase->stream.out != NULL) &&
3031 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303032 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3033 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003034 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303035 usecase->stream.out->started) {
3036 if (is_bt_soc_on(adev) == false) {
3037 ALOGD("BT SCO/A2dp disconnected while in connection");
3038 out_standby_l(&usecase->stream.out->stream.common);
3039 }
3040 }
3041 }
3042
Yung Ti Su70cb8242018-06-22 17:38:47 +08003043 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003044 struct stream_out *voip_out = voip_usecase->stream.out;
3045 audio_extn_utils_send_app_type_gain(adev,
3046 voip_out->app_type_cfg.app_type,
3047 &voip_out->app_type_cfg.gain[0]);
3048 }
3049
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303050 ALOGD("%s: done",__func__);
3051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 return status;
3053}
3054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055static int stop_input_stream(struct stream_in *in)
3056{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303057 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303059
3060 if (in == NULL) {
3061 ALOGE("%s: stream_in ptr is NULL", __func__);
3062 return -EINVAL;
3063 }
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003066 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067
Eric Laurent994a6932013-07-17 11:51:42 -07003068 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003069 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 uc_info = get_usecase_from_list(adev, in->usecase);
3071 if (uc_info == NULL) {
3072 ALOGE("%s: Could not find the usecase (%d) in the list",
3073 __func__, in->usecase);
3074 return -EINVAL;
3075 }
3076
Carter Hsu2e429db2019-05-14 18:50:52 +08003077 priority_in = get_priority_input(adev);
3078
Derek Chenea197282019-01-07 17:35:01 -08003079 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3080 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003081
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003082 /* Close in-call recording streams */
3083 voice_check_and_stop_incall_rec_usecase(adev, in);
3084
Eric Laurent150dbfe2013-02-27 14:31:02 -08003085 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003086 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003087
3088 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003089 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003091 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303092 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3093
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003094 list_remove(&uc_info->list);
3095 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096
Carter Hsu2e429db2019-05-14 18:50:52 +08003097 if (priority_in == in) {
3098 priority_in = get_priority_input(adev);
3099 if (priority_in)
3100 select_devices(adev, priority_in->usecase);
3101 }
3102
Vatsal Buchac09ae062018-11-14 13:25:08 +05303103 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003104 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 return ret;
3106}
3107
3108int start_input_stream(struct stream_in *in)
3109{
3110 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003111 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303113
3114 if (in == NULL) {
3115 ALOGE("%s: stream_in ptr is NULL", __func__);
3116 return -EINVAL;
3117 }
3118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003120 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003121 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122
Mingming Yin2664a5b2015-09-03 10:53:11 -07003123 if (get_usecase_from_list(adev, usecase) == NULL)
3124 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303125 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3126 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003127
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303128 if (CARD_STATUS_OFFLINE == in->card_status||
3129 CARD_STATUS_OFFLINE == adev->card_status) {
3130 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303131 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132 goto error_config;
3133 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303134
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003135 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303136 if (!adev->bt_sco_on) {
3137 ALOGE("%s: SCO profile is not ready, return error", __func__);
3138 ret = -EIO;
3139 goto error_config;
3140 }
3141 }
3142
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003143 /* Check if source matches incall recording usecase criteria */
3144 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3145 if (ret)
3146 goto error_config;
3147 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003148 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3149
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303150 if (audio_extn_cin_attached_usecase(in))
3151 audio_extn_cin_acquire_usecase(in);
3152
Mingming Yin2664a5b2015-09-03 10:53:11 -07003153 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3154 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3155 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003156 ret = -EINVAL;
3157 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003158 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003159
Eric Laurentb23d5282013-05-14 15:27:20 -07003160 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 if (in->pcm_device_id < 0) {
3162 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3163 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003164 ret = -EINVAL;
3165 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003169
3170 if (!uc_info) {
3171 ret = -ENOMEM;
3172 goto error_config;
3173 }
3174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 uc_info->id = in->usecase;
3176 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003177 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003178 list_init(&uc_info->device_list);
3179 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003180 uc_info->in_snd_device = SND_DEVICE_NONE;
3181 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003183 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003184 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303185 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3186 adev->perf_lock_opts,
3187 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003188 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189
Derek Chenea197282019-01-07 17:35:01 -08003190 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3191 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003192
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303193 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3194
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303195 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303196 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303197 if (ret)
3198 goto error_open;
3199 else
3200 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003201 }
3202
Haynes Mathew George16081042017-05-31 17:16:49 -07003203 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003204 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003205 ALOGE("%s: pcm stream not ready", __func__);
3206 goto error_open;
3207 }
3208 ret = pcm_start(in->pcm);
3209 if (ret < 0) {
3210 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3211 goto error_open;
3212 }
3213 } else {
3214 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3215 unsigned int pcm_open_retry_count = 0;
3216
Zhou Song62ea0282020-03-22 19:53:01 +08003217 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3218 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003219 flags |= PCM_MMAP | PCM_NOIRQ;
3220 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3221 } else if (in->realtime) {
3222 flags |= PCM_MMAP | PCM_NOIRQ;
3223 }
3224
Garmond Leunge2433c32017-09-28 21:51:22 -07003225 if (audio_extn_ffv_get_stream() == in) {
3226 ALOGD("%s: ffv stream, update pcm config", __func__);
3227 audio_extn_ffv_update_pcm_config(&config);
3228 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3230 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3231
3232 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003233 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003234 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003235 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003236 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303237 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303238 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3239 adev->card_status = CARD_STATUS_OFFLINE;
3240 in->card_status = CARD_STATUS_OFFLINE;
3241 ret = -EIO;
3242 goto error_open;
3243 }
3244
Haynes Mathew George16081042017-05-31 17:16:49 -07003245 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3246 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3247 if (in->pcm != NULL) {
3248 pcm_close(in->pcm);
3249 in->pcm = NULL;
3250 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003251 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003252 ret = -EIO;
3253 goto error_open;
3254 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003255 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003256 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3257 continue;
3258 }
3259 break;
3260 }
3261
3262 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003263 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003264 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003265 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003266 if (ret < 0) {
3267 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3268 pcm_close(in->pcm);
3269 in->pcm = NULL;
3270 goto error_open;
3271 }
3272 register_in_stream(in);
3273 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003274 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003275 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003276 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003277 if (ret < 0) {
3278 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003279 pcm_close(in->pcm);
3280 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003281 goto error_open;
3282 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003283 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003284 }
3285
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003286 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003287 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3288 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003289
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003290 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303291 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3292
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303293done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003294 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303295 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003296 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303297 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003298 return ret;
3299
3300error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003301 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303302 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003304
Eric Laurentc8400632013-02-14 19:04:54 -08003305error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003306 if (audio_extn_cin_attached_usecase(in))
3307 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303308 /*
3309 * sleep 50ms to allow sufficient time for kernel
3310 * drivers to recover incases like SSR.
3311 */
3312 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003313 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303314 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003315 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316}
3317
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003318void lock_input_stream(struct stream_in *in)
3319{
3320 pthread_mutex_lock(&in->pre_lock);
3321 pthread_mutex_lock(&in->lock);
3322 pthread_mutex_unlock(&in->pre_lock);
3323}
3324
3325void lock_output_stream(struct stream_out *out)
3326{
3327 pthread_mutex_lock(&out->pre_lock);
3328 pthread_mutex_lock(&out->lock);
3329 pthread_mutex_unlock(&out->pre_lock);
3330}
3331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332/* must be called with out->lock locked */
3333static int send_offload_cmd_l(struct stream_out* out, int command)
3334{
3335 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3336
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003337 if (!cmd) {
3338 ALOGE("failed to allocate mem for command 0x%x", command);
3339 return -ENOMEM;
3340 }
3341
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 ALOGVV("%s %d", __func__, command);
3343
3344 cmd->cmd = command;
3345 list_add_tail(&out->offload_cmd_list, &cmd->node);
3346 pthread_cond_signal(&out->offload_cond);
3347 return 0;
3348}
3349
Gautam Manamfeeb1162020-12-24 14:08:04 +05303350/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351static void stop_compressed_output_l(struct stream_out *out)
3352{
Gautam Manamfeeb1162020-12-24 14:08:04 +05303353 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manamfeeb1162020-12-24 14:08:04 +05303355 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003357 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 if (out->compr != NULL) {
3359 compress_stop(out->compr);
3360 while (out->offload_thread_blocked) {
3361 pthread_cond_wait(&out->cond, &out->lock);
3362 }
3363 }
3364}
3365
Varun Balaraje49253e2017-07-06 19:48:56 +05303366bool is_interactive_usecase(audio_usecase_t uc_id)
3367{
3368 unsigned int i;
3369 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3370 if (uc_id == interactive_usecases[i])
3371 return true;
3372 }
3373 return false;
3374}
3375
3376static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3377{
3378 audio_usecase_t ret_uc = USECASE_INVALID;
3379 unsigned int intract_uc_index;
3380 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3381
3382 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3383 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3384 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3385 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3386 ret_uc = interactive_usecases[intract_uc_index];
3387 break;
3388 }
3389 }
3390
3391 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3392 return ret_uc;
3393}
3394
3395static void free_interactive_usecase(struct audio_device *adev,
3396 audio_usecase_t uc_id)
3397{
3398 unsigned int interact_uc_index;
3399 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3400
3401 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3402 if (interactive_usecases[interact_uc_index] == uc_id) {
3403 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3404 break;
3405 }
3406 }
3407 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3408}
3409
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003410bool is_offload_usecase(audio_usecase_t uc_id)
3411{
3412 unsigned int i;
3413 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3414 if (uc_id == offload_usecases[i])
3415 return true;
3416 }
3417 return false;
3418}
3419
Dhananjay Kumarac341582017-02-23 23:42:25 +05303420static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003421{
vivek mehta446c3962015-09-14 10:57:35 -07003422 audio_usecase_t ret_uc = USECASE_INVALID;
3423 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003424 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003425 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303426 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003427 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3428 else
3429 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003430
vivek mehta446c3962015-09-14 10:57:35 -07003431 pthread_mutex_lock(&adev->lock);
3432 if (get_usecase_from_list(adev, ret_uc) != NULL)
3433 ret_uc = USECASE_INVALID;
3434 pthread_mutex_unlock(&adev->lock);
3435
3436 return ret_uc;
3437 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003438
3439 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003440 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3441 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3442 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3443 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003444 break;
3445 }
3446 }
vivek mehta446c3962015-09-14 10:57:35 -07003447
3448 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3449 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003450}
3451
3452static void free_offload_usecase(struct audio_device *adev,
3453 audio_usecase_t uc_id)
3454{
vivek mehta446c3962015-09-14 10:57:35 -07003455 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003456 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003457
3458 if (!adev->multi_offload_enable)
3459 return;
3460
3461 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3462 if (offload_usecases[offload_uc_index] == uc_id) {
3463 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464 break;
3465 }
3466 }
3467 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3468}
3469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470static void *offload_thread_loop(void *context)
3471{
3472 struct stream_out *out = (struct stream_out *) context;
3473 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003474 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003477 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003478 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3479
3480 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003481 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003482 out->offload_state = OFFLOAD_STATE_IDLE;
3483 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 for (;;) {
3485 struct offload_cmd *cmd = NULL;
3486 stream_callback_event_t event;
3487 bool send_callback = false;
3488
3489 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3490 __func__, list_empty(&out->offload_cmd_list),
3491 out->offload_state);
3492 if (list_empty(&out->offload_cmd_list)) {
3493 ALOGV("%s SLEEPING", __func__);
3494 pthread_cond_wait(&out->offload_cond, &out->lock);
3495 ALOGV("%s RUNNING", __func__);
3496 continue;
3497 }
3498
3499 item = list_head(&out->offload_cmd_list);
3500 cmd = node_to_item(item, struct offload_cmd, node);
3501 list_remove(item);
3502
3503 ALOGVV("%s STATE %d CMD %d out->compr %p",
3504 __func__, out->offload_state, cmd->cmd, out->compr);
3505
3506 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3507 free(cmd);
3508 break;
3509 }
3510
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003511 // allow OFFLOAD_CMD_ERROR reporting during standby
3512 // this is needed to handle failures during compress_open
3513 // Note however that on a pause timeout, the stream is closed
3514 // and no offload usecase will be active. Therefore this
3515 // special case is needed for compress_open failures alone
3516 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3517 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003519 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003520 pthread_cond_signal(&out->cond);
3521 continue;
3522 }
3523 out->offload_thread_blocked = true;
3524 pthread_mutex_unlock(&out->lock);
3525 send_callback = false;
3526 switch(cmd->cmd) {
3527 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003528 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003529 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003530 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003531 send_callback = true;
3532 event = STREAM_CBK_EVENT_WRITE_READY;
3533 break;
3534 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003535 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303536 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003537 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303538 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003539 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303540 if (ret < 0)
3541 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303542 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303543 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003544 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003545 else
3546 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003547 if (-ENETRESET != ret && !(-EINTR == ret &&
3548 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303549 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303550 pthread_mutex_lock(&out->lock);
3551 out->send_new_metadata = 1;
3552 out->send_next_track_params = true;
3553 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303554 event = STREAM_CBK_EVENT_DRAIN_READY;
3555 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3556 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303557 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 break;
3559 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003560 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003561 ret = compress_drain(out->compr);
3562 ALOGD("copl(%p):out of compress_drain", out);
3563 // EINTR check avoids drain interruption due to SSR
3564 if (-ENETRESET != ret && !(-EINTR == ret &&
3565 CARD_STATUS_OFFLINE == out->card_status)) {
3566 send_callback = true;
3567 event = STREAM_CBK_EVENT_DRAIN_READY;
3568 } else
3569 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303571 case OFFLOAD_CMD_ERROR:
3572 ALOGD("copl(%p): sending error callback to AF", out);
3573 send_callback = true;
3574 event = STREAM_CBK_EVENT_ERROR;
3575 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003576 default:
3577 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3578 break;
3579 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003580 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003581 out->offload_thread_blocked = false;
3582 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003583 if (send_callback && out->client_callback) {
3584 ALOGVV("%s: sending client_callback event %d", __func__, event);
3585 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003586 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 free(cmd);
3588 }
3589
3590 pthread_cond_signal(&out->cond);
3591 while (!list_empty(&out->offload_cmd_list)) {
3592 item = list_head(&out->offload_cmd_list);
3593 list_remove(item);
3594 free(node_to_item(item, struct offload_cmd, node));
3595 }
3596 pthread_mutex_unlock(&out->lock);
3597
3598 return NULL;
3599}
3600
3601static int create_offload_callback_thread(struct stream_out *out)
3602{
3603 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3604 list_init(&out->offload_cmd_list);
3605 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3606 offload_thread_loop, out);
3607 return 0;
3608}
3609
3610static int destroy_offload_callback_thread(struct stream_out *out)
3611{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003612 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003613 stop_compressed_output_l(out);
3614 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3615
3616 pthread_mutex_unlock(&out->lock);
3617 pthread_join(out->offload_thread, (void **) NULL);
3618 pthread_cond_destroy(&out->offload_cond);
3619
3620 return 0;
3621}
3622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623static int stop_output_stream(struct stream_out *out)
3624{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303625 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 struct audio_usecase *uc_info;
3627 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003628 bool has_voip_usecase =
3629 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630
Eric Laurent994a6932013-07-17 11:51:42 -07003631 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003632 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 uc_info = get_usecase_from_list(adev, out->usecase);
3634 if (uc_info == NULL) {
3635 ALOGE("%s: Could not find the usecase (%d) in the list",
3636 __func__, out->usecase);
3637 return -EINVAL;
3638 }
3639
Zhou Song1f93fa52020-11-20 13:57:39 +08003640 out->a2dp_muted = false;
3641
Derek Chenea197282019-01-07 17:35:01 -08003642 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3643 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003644
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003645 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303646 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003647 if (adev->visualizer_stop_output != NULL)
3648 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003649
3650 audio_extn_dts_remove_state_notifier_node(out->usecase);
3651
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003652 if (adev->offload_effects_stop_output != NULL)
3653 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003654 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3655 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3656 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003657 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003658
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003659 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3660 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003661 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003662 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003663
Eric Laurent150dbfe2013-02-27 14:31:02 -08003664 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003665 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003666
3667 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003668 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669
Aalique Grahame22e49102018-12-18 14:23:57 -08003670 audio_extn_extspk_update(adev->extspk);
3671
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003672 if (is_offload_usecase(out->usecase)) {
3673 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3674 adev->dsp_bit_width_enforce_mode,
3675 false);
3676 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003677 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003678 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3679 false);
3680
3681 if (ret != 0)
3682 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3683 /* default service interval was successfully updated,
3684 reopen USB backend with new service interval */
3685 ret = 0;
3686 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003687
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003688 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303689 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003690 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303691 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003692 ALOGV("Disable passthrough , reset mixer to pcm");
3693 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003694#ifdef AUDIO_GKI_ENABLED
3695 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3696 out->compr_config.codec->reserved[0] = 0;
3697#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003698 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003699#endif
Mingming Yin21854652016-04-13 11:54:02 -07003700 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003701 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3702 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003703
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303704 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003705 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303706 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303707
Manish Dewangan21a850a2017-08-14 12:03:55 +05303708 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003709 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3710 if (ret < 0)
3711 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3712 }
3713
juyuchen2d415992018-11-16 14:15:16 +08003714 /* 1) media + voip output routing to handset must route media back to
3715 speaker when voip stops.
3716 2) trigger voip input to reroute when voip output changes to
3717 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003718 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003719 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003720 struct listnode *node;
3721 struct audio_usecase *usecase;
3722 list_for_each(node, &adev->usecase_list) {
3723 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003724 if ((usecase->type == PCM_CAPTURE &&
3725 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3726 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003727 continue;
3728
3729 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3730 __func__, usecase->id, use_case_table[usecase->id],
3731 out->usecase, use_case_table[out->usecase]);
3732 select_devices(adev, usecase->id);
3733 }
3734 }
3735
Garmond Leung5fd0b552018-04-17 11:56:12 -07003736 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003737 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 return ret;
3739}
3740
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003741struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3742 unsigned int flags, unsigned int pcm_open_retry_count,
3743 struct pcm_config *config)
3744{
3745 struct pcm* pcm = NULL;
3746
3747 while (1) {
3748 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3749 if (pcm == NULL || !pcm_is_ready(pcm)) {
3750 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3751 if (pcm != NULL) {
3752 pcm_close(pcm);
3753 pcm = NULL;
3754 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003755 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003756 return NULL;
3757
Weiyin Jiang72197252019-10-09 11:49:32 +08003758 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003759 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3760 continue;
3761 }
3762 break;
3763 }
3764
3765 if (pcm_is_ready(pcm)) {
3766 int ret = pcm_prepare(pcm);
3767 if (ret < 0) {
3768 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3769 pcm_close(pcm);
3770 pcm = NULL;
3771 }
3772 }
3773
3774 return pcm;
3775}
3776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777int start_output_stream(struct stream_out *out)
3778{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 struct audio_usecase *uc_info;
3781 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003782 char mixer_ctl_name[128];
3783 struct mixer_ctl *ctl = NULL;
3784 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303785 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003786 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787
Haynes Mathew George380745d2017-10-04 15:27:45 -07003788 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003789 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3790 ret = -EINVAL;
3791 goto error_config;
3792 }
3793
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003794 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303795 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003796 get_device_types(&out->device_list), is_haptic_usecase);
3797
3798 bool is_speaker_active = compare_device_type(&out->device_list,
3799 AUDIO_DEVICE_OUT_SPEAKER);
3800 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3801 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303802
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303803 if (CARD_STATUS_OFFLINE == out->card_status ||
3804 CARD_STATUS_OFFLINE == adev->card_status) {
3805 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303806 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003807 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303808 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303809
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003810 //Update incall music usecase to reflect correct voice session
3811 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3812 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3813 if (ret != 0) {
3814 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3815 __func__, ret);
3816 goto error_config;
3817 }
3818 }
3819
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003820 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003821 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003822 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303823 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303824 } else {
Zhou Song9ebf6792020-09-23 22:49:01 +08003825 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303826 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3827 ret = -EAGAIN;
3828 goto error_config;
3829 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303830 }
3831 }
3832 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003833 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303834 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003835 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303836 //combo usecase just by pass a2dp
3837 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003838 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303839 } else {
3840 ALOGE("%s: SCO profile is not ready, return error", __func__);
3841 ret = -EAGAIN;
3842 goto error_config;
3843 }
3844 }
3845 }
3846
Eric Laurentb23d5282013-05-14 15:27:20 -07003847 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 if (out->pcm_device_id < 0) {
3849 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3850 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003851 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003852 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 }
3854
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003855 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003856 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3857 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003858 if (adev->haptic_pcm_device_id < 0) {
3859 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3860 __func__, adev->haptic_pcm_device_id, out->usecase);
3861 ret = -EINVAL;
3862 goto error_config;
3863 }
3864 }
3865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003867
3868 if (!uc_info) {
3869 ret = -ENOMEM;
3870 goto error_config;
3871 }
3872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873 uc_info->id = out->usecase;
3874 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003875 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003876 list_init(&uc_info->device_list);
3877 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003878 uc_info->in_snd_device = SND_DEVICE_NONE;
3879 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003880
3881 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003882 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003883 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3884 /* USB backend is not reopened immediately.
3885 This is eventually done as part of select_devices */
3886 }
3887
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003888 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889
Wei Wangf7ca6c92017-11-21 14:51:20 -08003890 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303891 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3892 adev->perf_lock_opts,
3893 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303894
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003895 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303896 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303897 if (audio_extn_passthru_is_enabled() &&
3898 audio_extn_passthru_is_passthrough_stream(out)) {
3899 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303900 }
3901 }
3902
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003903 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003904 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303905 if (!a2dp_combo) {
3906 check_a2dp_restore_l(adev, out, false);
3907 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003908 struct listnode dev;
3909 list_init(&dev);
3910 assign_devices(&dev, &out->device_list);
3911 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3912 reassign_device_list(&out->device_list,
3913 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003914 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003915 reassign_device_list(&out->device_list,
3916 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303917 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003918 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303919 }
3920 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303921 select_devices(adev, out->usecase);
3922 if (is_a2dp_out_device_type(&out->device_list) &&
3923 !adev->a2dp_started) {
3924 if (is_speaker_active || is_speaker_safe_active) {
3925 struct listnode dev;
3926 list_init(&dev);
3927 assign_devices(&dev, &out->device_list);
3928 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3929 reassign_device_list(&out->device_list,
3930 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3931 else
3932 reassign_device_list(&out->device_list,
3933 AUDIO_DEVICE_OUT_SPEAKER, "");
3934 select_devices(adev, out->usecase);
3935 assign_devices(&out->device_list, &dev);
3936 } else {
3937 ret = -EINVAL;
3938 goto error_open;
3939 }
3940 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303941 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003942
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003943 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3944 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003945 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003946 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003947
Derek Chenea197282019-01-07 17:35:01 -08003948 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3949 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003950
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003951 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3952 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003953
3954 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003955 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003956 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3957 ALOGE("%s: pcm stream not ready", __func__);
3958 goto error_open;
3959 }
3960 ret = pcm_start(out->pcm);
3961 if (ret < 0) {
3962 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3963 goto error_open;
3964 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003965 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003966 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003967 unsigned int flags = PCM_OUT;
3968 unsigned int pcm_open_retry_count = 0;
3969 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3970 flags |= PCM_MMAP | PCM_NOIRQ;
3971 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003972 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003973 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003974 } else
3975 flags |= PCM_MONOTONIC;
3976
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003977 if ((adev->vr_audio_mode_enabled) &&
3978 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3979 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3980 "PCM_Dev %d Topology", out->pcm_device_id);
3981 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3982 if (!ctl) {
3983 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3984 __func__, mixer_ctl_name);
3985 } else {
3986 //if success use ULLPP
3987 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3988 __func__, mixer_ctl_name, out->pcm_device_id);
3989 //There is a still a possibility that some sessions
3990 // that request for FAST|RAW when 3D audio is active
3991 //can go through ULLPP. Ideally we expects apps to
3992 //listen to audio focus and stop concurrent playback
3993 //Also, we will look for mode flag (voice_in_communication)
3994 //before enabling the realtime flag.
3995 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3996 }
3997 }
3998
Surendar Karka91fa3682018-07-02 18:12:12 +05303999 if (out->realtime)
4000 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4001 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4002
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004003 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4004 flags, pcm_open_retry_count,
4005 &(out->config));
4006 if (out->pcm == NULL) {
4007 ret = -EIO;
4008 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004009 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004010
4011 if (is_haptic_usecase) {
4012 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4013 adev->haptic_pcm_device_id,
4014 flags, pcm_open_retry_count,
4015 &(adev->haptics_config));
4016 // failure to open haptics pcm shouldnt stop audio,
4017 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004018
4019 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4020 ALOGD("%s: enable haptic audio synchronization", __func__);
4021 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4022 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004023 }
4024
Surendar Karka91fa3682018-07-02 18:12:12 +05304025 if (!out->realtime)
4026 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304027 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004028
Zhou Song2b8f28f2017-09-11 10:51:38 +08004029 // apply volume for voip playback after path is set up
4030 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4031 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304032 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4033 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304034 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4035 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004036 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4037 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304038 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004039 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004040 /*
4041 * set custom channel map if:
4042 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4043 * 2. custom channel map has been set by client
4044 * else default channel map of FC/FR/FL can always be set to DSP
4045 */
4046 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4047 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4048 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004049 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4050 adev->dsp_bit_width_enforce_mode,
4051 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004053 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004054 out->compr = compress_open(adev->snd_card,
4055 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004056 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004057 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304058 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304059 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4060 adev->card_status = CARD_STATUS_OFFLINE;
4061 out->card_status = CARD_STATUS_OFFLINE;
4062 ret = -EIO;
4063 goto error_open;
4064 }
4065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004067 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004068 compress_close(out->compr);
4069 out->compr = NULL;
4070 ret = -EIO;
4071 goto error_open;
4072 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304073 /* compress_open sends params of the track, so reset the flag here */
4074 out->is_compr_metadata_avail = false;
4075
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004076 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004078
Fred Oh3f43e742015-03-04 18:42:34 -08004079 /* Since small bufs uses blocking writes, a write will be blocked
4080 for the default max poll time (20s) in the event of an SSR.
4081 Reduce the poll time to observe and deal with SSR faster.
4082 */
Ashish Jain5106d362016-05-11 19:23:33 +05304083 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004084 compress_set_max_poll_wait(out->compr, 1000);
4085 }
4086
Manish Dewangan69426c82017-01-30 17:35:36 +05304087 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304088 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304089
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004090 audio_extn_dts_create_state_notifier_node(out->usecase);
4091 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4092 popcount(out->channel_mask),
4093 out->playback_started);
4094
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004095#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304096 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004097 audio_extn_dolby_send_ddp_endp_params(adev);
4098#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304099 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4100 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004101 if (adev->visualizer_start_output != NULL)
4102 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4103 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304104 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004105 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004106 }
Derek Chenf13dd492018-11-13 14:53:51 -08004107
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004108 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004109 /* Update cached volume from media to offload/direct stream */
4110 struct listnode *node = NULL;
4111 list_for_each(node, &adev->active_outputs_list) {
4112 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4113 streams_output_ctxt_t,
4114 list);
4115 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4116 out->volume_l = out_ctxt->output->volume_l;
4117 out->volume_r = out_ctxt->output->volume_r;
4118 }
4119 }
4120 out_set_compr_volume(&out->stream,
4121 out->volume_l, out->volume_r);
4122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004124
4125 if (ret == 0) {
4126 register_out_stream(out);
4127 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004128 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4129 ALOGE("%s: pcm stream not ready", __func__);
4130 goto error_open;
4131 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004132 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004133 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004134 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004135 if (ret < 0)
4136 goto error_open;
4137 }
4138 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004139 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304140 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004141 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004142
vivek mehtad15d2bf2019-05-17 13:35:10 -07004143 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4144 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4145 audio_low_latency_hint_start();
4146 }
4147
Manish Dewangan21a850a2017-08-14 12:03:55 +05304148 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004149 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004150 if (ret < 0)
4151 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4152 }
4153
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004154 // consider a scenario where on pause lower layers are tear down.
4155 // so on resume, swap mixer control need to be sent only when
4156 // backend is active, hence rather than sending from enable device
4157 // sending it from start of streamtream
4158
4159 platform_set_swap_channels(adev, true);
4160
Haynes Mathew George380745d2017-10-04 15:27:45 -07004161 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304162 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004163 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004164error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004165 if (adev->haptic_pcm) {
4166 pcm_close(adev->haptic_pcm);
4167 adev->haptic_pcm = NULL;
4168 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004169 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304170 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004172error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304173 /*
4174 * sleep 50ms to allow sufficient time for kernel
4175 * drivers to recover incases like SSR.
4176 */
4177 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004178error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004179 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304180 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004181 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182}
4183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184static int check_input_parameters(uint32_t sample_rate,
4185 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004186 int channel_count,
4187 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004189 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304191 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4192 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4193 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004194 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004195 !audio_extn_compr_cap_format_supported(format) &&
4196 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004197 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004198
Aalique Grahame22e49102018-12-18 14:23:57 -08004199 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4200 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4201 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4202 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4203 return -EINVAL;
4204 }
4205
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004206 switch (channel_count) {
4207 case 1:
4208 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304209 case 3:
4210 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004211 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004212 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304213 case 10:
4214 case 12:
4215 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004216 break;
4217 default:
4218 ret = -EINVAL;
4219 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220
4221 switch (sample_rate) {
4222 case 8000:
4223 case 11025:
4224 case 12000:
4225 case 16000:
4226 case 22050:
4227 case 24000:
4228 case 32000:
4229 case 44100:
4230 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004231 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304232 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004233 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304234 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 break;
4236 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004237 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 }
4239
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004240 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241}
4242
Naresh Tanniru04f71882018-06-26 17:46:22 +05304243
4244/** Add a value in a list if not already present.
4245 * @return true if value was successfully inserted or already present,
4246 * false if the list is full and does not contain the value.
4247 */
4248static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4249 for (size_t i = 0; i < list_length; i++) {
4250 if (list[i] == value) return true; // value is already present
4251 if (list[i] == 0) { // no values in this slot
4252 list[i] = value;
4253 return true; // value inserted
4254 }
4255 }
4256 return false; // could not insert value
4257}
4258
4259/** Add channel_mask in supported_channel_masks if not already present.
4260 * @return true if channel_mask was successfully inserted or already present,
4261 * false if supported_channel_masks is full and does not contain channel_mask.
4262 */
4263static void register_channel_mask(audio_channel_mask_t channel_mask,
4264 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4265 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4266 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4267}
4268
4269/** Add format in supported_formats if not already present.
4270 * @return true if format was successfully inserted or already present,
4271 * false if supported_formats is full and does not contain format.
4272 */
4273static void register_format(audio_format_t format,
4274 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4275 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4276 "%s: stream can not declare supporting its format %x", __func__, format);
4277}
4278/** Add sample_rate in supported_sample_rates if not already present.
4279 * @return true if sample_rate was successfully inserted or already present,
4280 * false if supported_sample_rates is full and does not contain sample_rate.
4281 */
4282static void register_sample_rate(uint32_t sample_rate,
4283 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4284 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4285 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4286}
4287
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004288static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4289{
4290 uint32_t high = num1, low = num2, temp = 0;
4291
4292 if (!num1 || !num2)
4293 return 0;
4294
4295 if (num1 < num2) {
4296 high = num2;
4297 low = num1;
4298 }
4299
4300 while (low != 0) {
4301 temp = low;
4302 low = high % low;
4303 high = temp;
4304 }
4305 return (num1 * num2)/high;
4306}
4307
4308static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4309{
4310 uint32_t remainder = 0;
4311
4312 if (!multiplier)
4313 return num;
4314
4315 remainder = num % multiplier;
4316 if (remainder)
4317 num += (multiplier - remainder);
4318
4319 return num;
4320}
4321
Aalique Grahame22e49102018-12-18 14:23:57 -08004322static size_t get_stream_buffer_size(size_t duration_ms,
4323 uint32_t sample_rate,
4324 audio_format_t format,
4325 int channel_count,
4326 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327{
4328 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004329 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330
Aalique Grahame22e49102018-12-18 14:23:57 -08004331 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004332 if (is_low_latency)
4333 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304334
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004335 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004336 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337
Ralf Herzbd08d632018-09-28 15:50:49 +02004338 /* make sure the size is multiple of 32 bytes and additionally multiple of
4339 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004340 * At 48 kHz mono 16-bit PCM:
4341 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4342 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004343 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004344 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004345 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004346
4347 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348}
4349
Aalique Grahame22e49102018-12-18 14:23:57 -08004350static size_t get_input_buffer_size(uint32_t sample_rate,
4351 audio_format_t format,
4352 int channel_count,
4353 bool is_low_latency)
4354{
4355 /* Don't know if USB HIFI in this context so use true to be conservative */
4356 if (check_input_parameters(sample_rate, format, channel_count,
4357 true /*is_usb_hifi */) != 0)
4358 return 0;
4359
4360 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4361 sample_rate,
4362 format,
4363 channel_count,
4364 is_low_latency);
4365}
4366
Derek Chenf6318be2017-06-12 17:16:24 -04004367size_t get_output_period_size(uint32_t sample_rate,
4368 audio_format_t format,
4369 int channel_count,
4370 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304371{
4372 size_t size = 0;
4373 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4374
4375 if ((duration == 0) || (sample_rate == 0) ||
4376 (bytes_per_sample == 0) || (channel_count == 0)) {
4377 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4378 bytes_per_sample, channel_count);
4379 return -EINVAL;
4380 }
4381
4382 size = (sample_rate *
4383 duration *
4384 bytes_per_sample *
4385 channel_count) / 1000;
4386 /*
4387 * To have same PCM samples for all channels, the buffer size requires to
4388 * be multiple of (number of channels * bytes per sample)
4389 * For writes to succeed, the buffer must be written at address which is multiple of 32
4390 */
4391 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4392
4393 return (size/(channel_count * bytes_per_sample));
4394}
4395
Zhou Song48453a02018-01-10 17:50:59 +08004396static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304397{
4398 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004399 uint64_t written_frames = 0;
4400 uint64_t kernel_frames = 0;
4401 uint64_t dsp_frames = 0;
4402 uint64_t signed_frames = 0;
4403 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304404
4405 /* This adjustment accounts for buffering after app processor.
4406 * It is based on estimated DSP latency per use case, rather than exact.
4407 */
George Gao9ba8a142020-07-23 14:30:03 -07004408 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004409 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304410
Zhou Song48453a02018-01-10 17:50:59 +08004411 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004412 written_frames = out->written /
4413 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4414
Ashish Jain5106d362016-05-11 19:23:33 +05304415 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4416 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4417 * hence only estimate.
4418 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004419 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4420 kernel_frames = kernel_buffer_size /
4421 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304422
Weiyin Jiang4813da12020-05-28 00:37:28 +08004423 if (written_frames >= (kernel_frames + dsp_frames))
4424 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304425
Zhou Song48453a02018-01-10 17:50:59 +08004426 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304427 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004428 if (timestamp != NULL )
4429 *timestamp = out->writeAt;
4430 } else if (timestamp != NULL) {
4431 clock_gettime(CLOCK_MONOTONIC, timestamp);
4432 }
4433 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304434
Weiyin Jiang4813da12020-05-28 00:37:28 +08004435 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4436 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304437
4438 return actual_frames_rendered;
4439}
4440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4442{
4443 struct stream_out *out = (struct stream_out *)stream;
4444
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004445 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446}
4447
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004448static int out_set_sample_rate(struct audio_stream *stream __unused,
4449 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450{
4451 return -ENOSYS;
4452}
4453
4454static size_t out_get_buffer_size(const struct audio_stream *stream)
4455{
4456 struct stream_out *out = (struct stream_out *)stream;
4457
Varun Balaraje49253e2017-07-06 19:48:56 +05304458 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304459 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304460 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304461 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4462 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4463 else
4464 return out->compr_config.fragment_size;
4465 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004466 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304467 else if (is_offload_usecase(out->usecase) &&
4468 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304469 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004470
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004471 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004472 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473}
4474
4475static uint32_t out_get_channels(const struct audio_stream *stream)
4476{
4477 struct stream_out *out = (struct stream_out *)stream;
4478
4479 return out->channel_mask;
4480}
4481
4482static audio_format_t out_get_format(const struct audio_stream *stream)
4483{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004484 struct stream_out *out = (struct stream_out *)stream;
4485
4486 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487}
4488
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004489static int out_set_format(struct audio_stream *stream __unused,
4490 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491{
4492 return -ENOSYS;
4493}
4494
4495static int out_standby(struct audio_stream *stream)
4496{
4497 struct stream_out *out = (struct stream_out *)stream;
4498 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004499 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004500
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304501 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4502 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004504 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004505 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004506 if (adev->adm_deregister_stream)
4507 adev->adm_deregister_stream(adev->adm_data, out->handle);
4508
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004509 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004510 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004511 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004512
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004513 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004515 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4516 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304517 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004518 pthread_mutex_unlock(&adev->lock);
4519 pthread_mutex_unlock(&out->lock);
4520 ALOGD("VOIP output entered standby");
4521 return 0;
4522 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004523 if (out->pcm) {
4524 pcm_close(out->pcm);
4525 out->pcm = NULL;
4526 }
Meng Wanga09da002020-04-20 12:56:04 +08004527 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4528 if (adev->haptic_pcm) {
4529 pcm_close(adev->haptic_pcm);
4530 adev->haptic_pcm = NULL;
4531 }
4532
4533 if (adev->haptic_buffer != NULL) {
4534 free(adev->haptic_buffer);
4535 adev->haptic_buffer = NULL;
4536 adev->haptic_buffer_size = 0;
4537 }
4538 adev->haptic_pcm_device_id = 0;
4539 }
4540
Haynes Mathew George16081042017-05-31 17:16:49 -07004541 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4542 do_stop = out->playback_started;
4543 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004544
4545 if (out->mmap_shared_memory_fd >= 0) {
4546 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4547 __func__, out->mmap_shared_memory_fd);
4548 close(out->mmap_shared_memory_fd);
4549 out->mmap_shared_memory_fd = -1;
4550 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004551 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004552 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004553 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304554 out->send_next_track_params = false;
4555 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004556 out->gapless_mdata.encoder_delay = 0;
4557 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004558 if (out->compr != NULL) {
4559 compress_close(out->compr);
4560 out->compr = NULL;
4561 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004562 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004563 if (do_stop) {
4564 stop_output_stream(out);
4565 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304566 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004567 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004568 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569 }
4570 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304571 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 return 0;
4573}
4574
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304575static int out_on_error(struct audio_stream *stream)
4576{
4577 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004578 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304579
4580 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004581 // always send CMD_ERROR for offload streams, this
4582 // is needed e.g. when SSR happens within compress_open
4583 // since the stream is active, offload_callback_thread is also active.
4584 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4585 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004586 }
4587 pthread_mutex_unlock(&out->lock);
4588
4589 status = out_standby(&out->stream.common);
4590
4591 lock_output_stream(out);
4592 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004593 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304594 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304595
4596 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4597 ALOGD("Setting previous card status if offline");
4598 out->prev_card_status_offline = true;
4599 }
4600
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304601 pthread_mutex_unlock(&out->lock);
4602
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004603 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304604}
4605
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304606/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004607 * standby implementation without locks, assumes that the callee already
4608 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304609 */
4610int out_standby_l(struct audio_stream *stream)
4611{
4612 struct stream_out *out = (struct stream_out *)stream;
4613 struct audio_device *adev = out->dev;
4614
4615 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4616 stream, out->usecase, use_case_table[out->usecase]);
4617
4618 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004619 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304620 if (adev->adm_deregister_stream)
4621 adev->adm_deregister_stream(adev->adm_data, out->handle);
4622
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004623 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304624 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004625 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304626
4627 out->standby = true;
4628 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4629 voice_extn_compress_voip_close_output_stream(stream);
4630 out->started = 0;
4631 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004632 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304633 return 0;
4634 } else if (!is_offload_usecase(out->usecase)) {
4635 if (out->pcm) {
4636 pcm_close(out->pcm);
4637 out->pcm = NULL;
4638 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004639 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4640 if (adev->haptic_pcm) {
4641 pcm_close(adev->haptic_pcm);
4642 adev->haptic_pcm = NULL;
4643 }
4644
4645 if (adev->haptic_buffer != NULL) {
4646 free(adev->haptic_buffer);
4647 adev->haptic_buffer = NULL;
4648 adev->haptic_buffer_size = 0;
4649 }
4650 adev->haptic_pcm_device_id = 0;
4651 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304652 } else {
4653 ALOGD("copl(%p):standby", out);
4654 out->send_next_track_params = false;
4655 out->is_compr_metadata_avail = false;
4656 out->gapless_mdata.encoder_delay = 0;
4657 out->gapless_mdata.encoder_padding = 0;
4658 if (out->compr != NULL) {
4659 compress_close(out->compr);
4660 out->compr = NULL;
4661 }
4662 }
4663 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004664 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304665 }
4666 ALOGD("%s: exit", __func__);
4667 return 0;
4668}
4669
Aalique Grahame22e49102018-12-18 14:23:57 -08004670static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671{
Aalique Grahame22e49102018-12-18 14:23:57 -08004672 struct stream_out *out = (struct stream_out *)stream;
4673
4674 // We try to get the lock for consistency,
4675 // but it isn't necessary for these variables.
4676 // If we're not in standby, we may be blocked on a write.
4677 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4678 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4679 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4680
Andy Hunga1f48fa2019-07-01 18:14:53 -07004681 char buffer[256]; // for statistics formatting
4682 if (!is_offload_usecase(out->usecase)) {
4683 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4684 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4685 }
4686
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004687 if (out->start_latency_ms.n > 0) {
4688 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4689 dprintf(fd, " Start latency ms: %s\n", buffer);
4690 }
4691
Aalique Grahame22e49102018-12-18 14:23:57 -08004692 if (locked) {
4693 pthread_mutex_unlock(&out->lock);
4694 }
4695
4696 // dump error info
4697 (void)error_log_dump(
4698 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 return 0;
4701}
4702
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004703static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4704{
4705 int ret = 0;
4706 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004707
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004708 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004709 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004710 return -EINVAL;
4711 }
4712
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304713 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004714
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004715 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4716 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304717 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004718 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004719 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4720 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304721 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004722 }
4723
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004724 ALOGV("%s new encoder delay %u and padding %u", __func__,
4725 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4726
4727 return 0;
4728}
4729
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004730static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4731{
4732 return out == adev->primary_output || out == adev->voice_tx_output;
4733}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004734
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304735// note: this call is safe only if the stream_cb is
4736// removed first in close_output_stream (as is done now).
4737static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4738{
4739 if (!stream || !parms)
4740 return;
4741
4742 struct stream_out *out = (struct stream_out *)stream;
4743 struct audio_device *adev = out->dev;
4744
4745 card_status_t status;
4746 int card;
4747 if (parse_snd_card_status(parms, &card, &status) < 0)
4748 return;
4749
4750 pthread_mutex_lock(&adev->lock);
4751 bool valid_cb = (card == adev->snd_card);
4752 pthread_mutex_unlock(&adev->lock);
4753
4754 if (!valid_cb)
4755 return;
4756
4757 lock_output_stream(out);
4758 if (out->card_status != status)
4759 out->card_status = status;
4760 pthread_mutex_unlock(&out->lock);
4761
4762 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4763 use_case_table[out->usecase],
4764 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4765
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304766 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304767 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304768 if (voice_is_call_state_active(adev) &&
4769 out == adev->primary_output) {
4770 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4771 pthread_mutex_lock(&adev->lock);
4772 voice_stop_call(adev);
4773 adev->mode = AUDIO_MODE_NORMAL;
4774 pthread_mutex_unlock(&adev->lock);
4775 }
4776 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304777 return;
4778}
4779
Kevin Rocardfce19002017-08-07 19:21:36 -07004780static int get_alive_usb_card(struct str_parms* parms) {
4781 int card;
4782 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4783 !audio_extn_usb_alive(card)) {
4784 return card;
4785 }
4786 return -ENODEV;
4787}
4788
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004789int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004790 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004791{
4792 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004793 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004794 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004795 bool bypass_a2dp = false;
4796 bool reconfig = false;
4797 unsigned long service_interval = 0;
4798
4799 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004800 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4801
4802 list_init(&new_devices);
4803 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004804
4805 lock_output_stream(out);
4806 pthread_mutex_lock(&adev->lock);
4807
4808 /*
4809 * When HDMI cable is unplugged the music playback is paused and
4810 * the policy manager sends routing=0. But the audioflinger continues
4811 * to write data until standby time (3sec). As the HDMI core is
4812 * turned off, the write gets blocked.
4813 * Avoid this by routing audio to speaker until standby.
4814 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004815 if (is_single_device_type_equal(&out->device_list,
4816 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004817 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004818 !audio_extn_passthru_is_passthrough_stream(out) &&
4819 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004820 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004821 }
4822 /*
4823 * When A2DP is disconnected the
4824 * music playback is paused and the policy manager sends routing=0
4825 * But the audioflinger continues to write data until standby time
4826 * (3sec). As BT is turned off, the write gets blocked.
4827 * Avoid this by routing audio to speaker until standby.
4828 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004829 if (is_a2dp_out_device_type(&out->device_list) &&
4830 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004831 !audio_extn_a2dp_source_is_ready() &&
4832 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004833 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004834 }
4835 /*
4836 * When USB headset is disconnected the music platback paused
4837 * and the policy manager send routing=0. But if the USB is connected
4838 * back before the standby time, AFE is not closed and opened
4839 * when USB is connected back. So routing to speker will guarantee
4840 * AFE reconfiguration and AFE will be opend once USB is connected again
4841 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004842 if (is_usb_out_device_type(&out->device_list) &&
4843 list_empty(&new_devices) &&
4844 !audio_extn_usb_connected(NULL)) {
4845 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4846 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004847 /* To avoid a2dp to sco overlapping / BT device improper state
4848 * check with BT lib about a2dp streaming support before routing
4849 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004850 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004851 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004852 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4853 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854 //combo usecase just by pass a2dp
4855 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4856 bypass_a2dp = true;
4857 } else {
4858 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4859 /* update device to a2dp and don't route as BT returned error
4860 * However it is still possible a2dp routing called because
4861 * of current active device disconnection (like wired headset)
4862 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004863 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004864 pthread_mutex_unlock(&adev->lock);
4865 pthread_mutex_unlock(&out->lock);
4866 goto error;
4867 }
4868 }
4869 }
4870
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004871 // Workaround: If routing to an non existing usb device, fail gracefully
4872 // The routing request will otherwise block during 10 second
4873 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004874 if (is_usb_out_device_type(&new_devices)) {
4875 struct str_parms *parms =
4876 str_parms_create_str(get_usb_device_address(&new_devices));
4877 if (!parms)
4878 goto error;
4879 if ((card = get_alive_usb_card(parms)) >= 0) {
4880 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4881 pthread_mutex_unlock(&adev->lock);
4882 pthread_mutex_unlock(&out->lock);
4883 str_parms_destroy(parms);
4884 ret = -ENOSYS;
4885 goto error;
4886 }
4887 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004888 }
4889
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004890 // Workaround: If routing to an non existing hdmi device, fail gracefully
4891 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4892 (platform_get_edid_info_v2(adev->platform,
4893 out->extconn.cs.controller,
4894 out->extconn.cs.stream) != 0)) {
4895 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4896 pthread_mutex_unlock(&adev->lock);
4897 pthread_mutex_unlock(&out->lock);
4898 ret = -ENOSYS;
4899 goto error;
4900 }
4901
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004902 /*
4903 * select_devices() call below switches all the usecases on the same
4904 * backend to the new device. Refer to check_usecases_codec_backend() in
4905 * the select_devices(). But how do we undo this?
4906 *
4907 * For example, music playback is active on headset (deep-buffer usecase)
4908 * and if we go to ringtones and select a ringtone, low-latency usecase
4909 * will be started on headset+speaker. As we can't enable headset+speaker
4910 * and headset devices at the same time, select_devices() switches the music
4911 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4912 * So when the ringtone playback is completed, how do we undo the same?
4913 *
4914 * We are relying on the out_set_parameters() call on deep-buffer output,
4915 * once the ringtone playback is ended.
4916 * NOTE: We should not check if the current devices are same as new devices.
4917 * Because select_devices() must be called to switch back the music
4918 * playback to headset.
4919 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004920 if (!list_empty(&new_devices)) {
4921 bool same_dev = compare_devices(&out->device_list, &new_devices);
4922 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004923
4924 if (output_drives_call(adev, out)) {
4925 if (!voice_is_call_state_active(adev)) {
4926 if (adev->mode == AUDIO_MODE_IN_CALL) {
4927 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004928 ret = voice_start_call(adev);
4929 }
4930 } else {
4931 adev->current_call_output = out;
4932 voice_update_devices_for_all_voice_usecases(adev);
4933 }
4934 }
4935
Mingshu Pang60536d72020-09-09 15:28:22 +08004936 if (is_usb_out_device_type(&out->device_list)) {
4937 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4938 audio_extn_usb_set_service_interval(true /*playback*/,
4939 service_interval,
4940 &reconfig);
4941 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4942 }
4943
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004944 if (!out->standby) {
4945 if (!same_dev) {
4946 ALOGV("update routing change");
4947 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4948 adev->perf_lock_opts,
4949 adev->perf_lock_opts_size);
4950 if (adev->adm_on_routing_change)
4951 adev->adm_on_routing_change(adev->adm_data,
4952 out->handle);
4953 }
4954 if (!bypass_a2dp) {
4955 select_devices(adev, out->usecase);
4956 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004957 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4958 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004959 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004960 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004961 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004962 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004963 }
4964
4965 if (!same_dev) {
4966 // on device switch force swap, lower functions will make sure
4967 // to check if swap is allowed or not.
4968 platform_set_swap_channels(adev, true);
4969 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4970 }
Zhou Song1f93fa52020-11-20 13:57:39 +08004971 pthread_mutex_lock(&out->latch_lock);
4972 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
4973 if (out->a2dp_muted) {
4974 out->a2dp_muted = false;
4975 if (is_offload_usecase(out->usecase))
4976 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4977 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
4978 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004979 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004980 }
Zhou Song1f93fa52020-11-20 13:57:39 +08004981 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
4982 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4983 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004984 }
4985 }
4986
4987 pthread_mutex_unlock(&adev->lock);
4988 pthread_mutex_unlock(&out->lock);
4989
4990 /*handles device and call state changes*/
4991 audio_extn_extspk_update(adev->extspk);
4992
4993error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004994 ALOGV("%s: exit: code(%d)", __func__, ret);
4995 return ret;
4996}
4997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004998static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4999{
5000 struct stream_out *out = (struct stream_out *)stream;
5001 struct audio_device *adev = out->dev;
5002 struct str_parms *parms;
5003 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005004 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005005 int ext_controller = -1;
5006 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007
sangwoobc677242013-08-08 16:53:43 +09005008 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005009 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305011 if (!parms)
5012 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005013
5014 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5015 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005016 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005017 out->extconn.cs.controller = ext_controller;
5018 out->extconn.cs.stream = ext_stream;
5019 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5020 use_case_table[out->usecase], out->extconn.cs.controller,
5021 out->extconn.cs.stream);
5022 }
5023
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005024 if (out == adev->primary_output) {
5025 pthread_mutex_lock(&adev->lock);
5026 audio_extn_set_parameters(adev, parms);
5027 pthread_mutex_unlock(&adev->lock);
5028 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005029 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005030 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005031 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005032
5033 audio_extn_dts_create_state_notifier_node(out->usecase);
5034 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5035 popcount(out->channel_mask),
5036 out->playback_started);
5037
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005038 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005039 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005040
Surendar Karkaf51b5842018-04-26 11:28:38 +05305041 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5042 sizeof(value));
5043 if (err >= 0) {
5044 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5045 audio_extn_send_dual_mono_mixing_coefficients(out);
5046 }
5047
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305048 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5049 if (err >= 0) {
5050 strlcpy(out->profile, value, sizeof(out->profile));
5051 ALOGV("updating stream profile with value '%s'", out->profile);
5052 lock_output_stream(out);
5053 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5054 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005055 &out->device_list, out->flags,
5056 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305057 out->sample_rate, out->bit_width,
5058 out->channel_mask, out->profile,
5059 &out->app_type_cfg);
5060 pthread_mutex_unlock(&out->lock);
5061 }
5062
Alexy Joseph98988832017-01-13 14:56:59 -08005063 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005064 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5065 // and vendor.audio.hal.output.suspend.supported is set to true
5066 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005067 //check suspend parameter only for low latency and if the property
5068 //is enabled
5069 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5070 ALOGI("%s: got suspend_playback %s", __func__, value);
5071 lock_output_stream(out);
5072 if (!strncmp(value, "false", 5)) {
5073 //suspend_playback=false is supposed to set QOS value back to 75%
5074 //the mixer control sent with value Enable will achieve that
5075 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5076 } else if (!strncmp (value, "true", 4)) {
5077 //suspend_playback=true is supposed to remove QOS value
5078 //resetting the mixer control will set the default value
5079 //for the mixer control which is Disable and this removes the QOS vote
5080 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5081 } else {
5082 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5083 " got %s", __func__, value);
5084 ret = -1;
5085 }
5086
5087 if (ret != 0) {
5088 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5089 __func__, out->pm_qos_mixer_path, ret);
5090 }
5091
5092 pthread_mutex_unlock(&out->lock);
5093 }
5094 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005095
Alexy Joseph98988832017-01-13 14:56:59 -08005096 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005097 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305098error:
Eric Laurent994a6932013-07-17 11:51:42 -07005099 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100 return ret;
5101}
5102
Paul McLeana50b7332018-12-17 08:24:21 -07005103static int in_set_microphone_direction(const struct audio_stream_in *stream,
5104 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005105 struct stream_in *in = (struct stream_in *)stream;
5106
5107 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5108
5109 in->direction = dir;
5110
5111 if (in->standby)
5112 return 0;
5113
5114 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005115}
5116
5117static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005118 struct stream_in *in = (struct stream_in *)stream;
5119
5120 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5121
5122 if (zoom > 1.0 || zoom < -1.0)
5123 return -EINVAL;
5124
5125 in->zoom = zoom;
5126
5127 if (in->standby)
5128 return 0;
5129
5130 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005131}
5132
5133
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005134static bool stream_get_parameter_channels(struct str_parms *query,
5135 struct str_parms *reply,
5136 audio_channel_mask_t *supported_channel_masks) {
5137 int ret = -1;
5138 char value[512];
5139 bool first = true;
5140 size_t i, j;
5141
5142 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5143 ret = 0;
5144 value[0] = '\0';
5145 i = 0;
5146 while (supported_channel_masks[i] != 0) {
5147 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5148 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5149 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305150 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005151
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305152 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005153 first = false;
5154 break;
5155 }
5156 }
5157 i++;
5158 }
5159 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5160 }
5161 return ret == 0;
5162}
5163
5164static bool stream_get_parameter_formats(struct str_parms *query,
5165 struct str_parms *reply,
5166 audio_format_t *supported_formats) {
5167 int ret = -1;
5168 char value[256];
5169 size_t i, j;
5170 bool first = true;
5171
5172 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5173 ret = 0;
5174 value[0] = '\0';
5175 i = 0;
5176 while (supported_formats[i] != 0) {
5177 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5178 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5179 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305180 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005181 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305182 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005183 first = false;
5184 break;
5185 }
5186 }
5187 i++;
5188 }
5189 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5190 }
5191 return ret == 0;
5192}
5193
5194static bool stream_get_parameter_rates(struct str_parms *query,
5195 struct str_parms *reply,
5196 uint32_t *supported_sample_rates) {
5197
5198 int i;
5199 char value[256];
5200 int ret = -1;
5201 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5202 ret = 0;
5203 value[0] = '\0';
5204 i=0;
5205 int cursor = 0;
5206 while (supported_sample_rates[i]) {
5207 int avail = sizeof(value) - cursor;
5208 ret = snprintf(value + cursor, avail, "%s%d",
5209 cursor > 0 ? "|" : "",
5210 supported_sample_rates[i]);
5211 if (ret < 0 || ret >= avail) {
5212 // if cursor is at the last element of the array
5213 // overwrite with \0 is duplicate work as
5214 // snprintf already put a \0 in place.
5215 // else
5216 // we had space to write the '|' at value[cursor]
5217 // (which will be overwritten) or no space to fill
5218 // the first element (=> cursor == 0)
5219 value[cursor] = '\0';
5220 break;
5221 }
5222 cursor += ret;
5223 ++i;
5224 }
5225 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5226 value);
5227 }
5228 return ret >= 0;
5229}
5230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5232{
5233 struct stream_out *out = (struct stream_out *)stream;
5234 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005235 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236 char value[256];
5237 struct str_parms *reply = str_parms_create();
5238 size_t i, j;
5239 int ret;
5240 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005241
5242 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005243 if (reply) {
5244 str_parms_destroy(reply);
5245 }
5246 if (query) {
5247 str_parms_destroy(query);
5248 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005249 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5250 return NULL;
5251 }
5252
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005253 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5255 if (ret >= 0) {
5256 value[0] = '\0';
5257 i = 0;
5258 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005259 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5260 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005262 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005264 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265 first = false;
5266 break;
5267 }
5268 }
5269 i++;
5270 }
5271 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5272 str = str_parms_to_str(reply);
5273 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005274 voice_extn_out_get_parameters(out, query, reply);
5275 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005276 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005277
Alexy Joseph62142aa2015-11-16 15:10:34 -08005278
5279 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5280 if (ret >= 0) {
5281 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305282 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5283 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005284 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305285 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005286 } else {
5287 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305288 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005289 }
5290 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005291 if (str)
5292 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005293 str = str_parms_to_str(reply);
5294 }
5295
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005296 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5297 if (ret >= 0) {
5298 value[0] = '\0';
5299 i = 0;
5300 first = true;
5301 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005302 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5303 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005304 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005305 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005306 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005307 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005308 first = false;
5309 break;
5310 }
5311 }
5312 i++;
5313 }
5314 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005315 if (str)
5316 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005317 str = str_parms_to_str(reply);
5318 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005319
5320 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5321 if (ret >= 0) {
5322 value[0] = '\0';
5323 i = 0;
5324 first = true;
5325 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005326 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5327 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005328 if (!first) {
5329 strlcat(value, "|", sizeof(value));
5330 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005331 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005332 first = false;
5333 break;
5334 }
5335 }
5336 i++;
5337 }
5338 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5339 if (str)
5340 free(str);
5341 str = str_parms_to_str(reply);
5342 }
5343
Alexy Joseph98988832017-01-13 14:56:59 -08005344 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5345 //only low latency track supports suspend_resume
5346 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005347 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005348 if (str)
5349 free(str);
5350 str = str_parms_to_str(reply);
5351 }
5352
5353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005354 str_parms_destroy(query);
5355 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005356 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005357 return str;
5358}
5359
5360static uint32_t out_get_latency(const struct audio_stream_out *stream)
5361{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005362 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005364 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005365
Alexy Josephaa54c872014-12-03 02:46:47 -08005366 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305367 lock_output_stream(out);
5368 latency = audio_extn_utils_compress_get_dsp_latency(out);
5369 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005370 } else if ((out->realtime) ||
5371 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005372 // since the buffer won't be filled up faster than realtime,
5373 // return a smaller number
5374 if (out->config.rate)
5375 period_ms = (out->af_period_multiplier * out->config.period_size *
5376 1000) / (out->config.rate);
5377 else
5378 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005379 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005380 } else {
5381 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005382 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005383 }
5384
Zhou Songd2537a02020-06-11 22:04:46 +08005385 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005386 latency += audio_extn_a2dp_get_encoder_latency();
5387
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305388 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005389 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005390}
5391
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305392static float AmpToDb(float amplification)
5393{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305394 float db = DSD_VOLUME_MIN_DB;
5395 if (amplification > 0) {
5396 db = 20 * log10(amplification);
5397 if(db < DSD_VOLUME_MIN_DB)
5398 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305399 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305400 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305401}
5402
Arun Mirpuri5d170872019-03-26 13:21:31 -07005403static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5404 float right)
5405{
5406 struct stream_out *out = (struct stream_out *)stream;
5407 long volume = 0;
5408 char mixer_ctl_name[128] = "";
5409 struct audio_device *adev = out->dev;
5410 struct mixer_ctl *ctl = NULL;
5411 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5412 PCM_PLAYBACK);
5413
5414 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5415 "Playback %d Volume", pcm_device_id);
5416 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5417 if (!ctl) {
5418 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5419 __func__, mixer_ctl_name);
5420 return -EINVAL;
5421 }
5422 if (left != right)
5423 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5424 __func__, left, right);
5425 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5426 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5427 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5428 __func__, mixer_ctl_name, volume);
5429 return -EINVAL;
5430 }
5431 return 0;
5432}
5433
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305434static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5435 float right)
5436{
5437 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305438 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305439 char mixer_ctl_name[128];
5440 struct audio_device *adev = out->dev;
5441 struct mixer_ctl *ctl;
5442 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5443 PCM_PLAYBACK);
5444
5445 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5446 "Compress Playback %d Volume", pcm_device_id);
5447 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5448 if (!ctl) {
5449 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5450 __func__, mixer_ctl_name);
5451 return -EINVAL;
5452 }
5453 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5454 __func__, mixer_ctl_name, left, right);
5455 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5456 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5457 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5458
5459 return 0;
5460}
5461
Zhou Song2b8f28f2017-09-11 10:51:38 +08005462static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5463 float right)
5464{
5465 struct stream_out *out = (struct stream_out *)stream;
5466 char mixer_ctl_name[] = "App Type Gain";
5467 struct audio_device *adev = out->dev;
5468 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305469 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005470
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005471 if (!is_valid_volume(left, right)) {
5472 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5473 __func__, left, right);
5474 return -EINVAL;
5475 }
5476
Zhou Song2b8f28f2017-09-11 10:51:38 +08005477 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5478 if (!ctl) {
5479 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5480 __func__, mixer_ctl_name);
5481 return -EINVAL;
5482 }
5483
5484 set_values[0] = 0; //0: Rx Session 1:Tx Session
5485 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305486 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5487 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005488
5489 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5490 return 0;
5491}
5492
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305493static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5494 float right)
5495{
5496 struct stream_out *out = (struct stream_out *)stream;
5497 /* Volume control for pcm playback */
5498 if (left != right) {
5499 return -EINVAL;
5500 } else {
5501 char mixer_ctl_name[128];
5502 struct audio_device *adev = out->dev;
5503 struct mixer_ctl *ctl;
5504 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5505 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5507 if (!ctl) {
5508 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5509 return -EINVAL;
5510 }
5511
5512 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5513 int ret = mixer_ctl_set_value(ctl, 0, volume);
5514 if (ret < 0) {
5515 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5516 return -EINVAL;
5517 }
5518
5519 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5520
5521 return 0;
5522 }
5523}
5524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005525static int out_set_volume(struct audio_stream_out *stream, float left,
5526 float right)
5527{
Eric Laurenta9024de2013-04-04 09:19:12 -07005528 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005529 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305530 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005531
Arun Mirpuri5d170872019-03-26 13:21:31 -07005532 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005533 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5534 /* only take left channel into account: the API is for stereo anyway */
5535 out->muted = (left == 0.0f);
5536 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005537 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305538 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005539 /*
5540 * Set mute or umute on HDMI passthrough stream.
5541 * Only take left channel into account.
5542 * Mute is 0 and unmute 1
5543 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305544 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305545 } else if (out->format == AUDIO_FORMAT_DSD){
5546 char mixer_ctl_name[128] = "DSD Volume";
5547 struct audio_device *adev = out->dev;
5548 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5549
5550 if (!ctl) {
5551 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5552 __func__, mixer_ctl_name);
5553 return -EINVAL;
5554 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305555 volume[0] = (long)(AmpToDb(left));
5556 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305557 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5558 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005559 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005560 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005561 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5562 struct listnode *node = NULL;
5563 list_for_each(node, &adev->active_outputs_list) {
5564 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5565 streams_output_ctxt_t,
5566 list);
5567 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5568 out->volume_l = out_ctxt->output->volume_l;
5569 out->volume_r = out_ctxt->output->volume_r;
5570 }
5571 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005572 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005573 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005574 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5575 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005576 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005577 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005578 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005579 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005580 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5581 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305582 ret = out_set_compr_volume(stream, left, right);
5583 out->volume_l = left;
5584 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005585 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305586 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005587 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005588 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005589 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5590 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song1f93fa52020-11-20 13:57:39 +08005591 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005592 if (!out->standby) {
5593 audio_extn_utils_send_app_type_gain(out->dev,
5594 out->app_type_cfg.app_type,
5595 &out->app_type_cfg.gain[0]);
Zhou Song1f93fa52020-11-20 13:57:39 +08005596 if (!out->a2dp_muted)
5597 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005598 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005599 out->volume_l = left;
5600 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005601 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005602 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005603 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5604 ALOGV("%s: MMAP set volume called", __func__);
5605 if (!out->standby)
5606 ret = out_set_mmap_volume(stream, left, right);
5607 out->volume_l = left;
5608 out->volume_r = right;
5609 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305610 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305611 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5612 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Song1f93fa52020-11-20 13:57:39 +08005613 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305614 /* Volume control for pcm playback */
Zhou Song1f93fa52020-11-20 13:57:39 +08005615 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305616 ret = out_set_pcm_volume(stream, left, right);
5617 else
5618 out->apply_volume = true;
5619
5620 out->volume_l = left;
5621 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005622 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305623 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005624 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5625 ALOGV("%s: bus device set volume called", __func__);
Zhou Song1f93fa52020-11-20 13:57:39 +08005626 pthread_mutex_lock(&out->latch_lock);
5627 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005628 ret = out_set_pcm_volume(stream, left, right);
5629 out->volume_l = left;
5630 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005631 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005632 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005633 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005635 return -ENOSYS;
5636}
5637
Zhou Songc9672822017-08-16 16:01:39 +08005638static void update_frames_written(struct stream_out *out, size_t bytes)
5639{
5640 size_t bpf = 0;
5641
5642 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5643 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5644 bpf = 1;
5645 else if (!is_offload_usecase(out->usecase))
5646 bpf = audio_bytes_per_sample(out->format) *
5647 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005648
5649 pthread_mutex_lock(&out->position_query_lock);
5650 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005651 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005652 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5653 }
5654 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005655}
5656
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005657int split_and_write_audio_haptic_data(struct stream_out *out,
5658 const void *buffer, size_t bytes_to_write)
5659{
5660 struct audio_device *adev = out->dev;
5661
5662 int ret = 0;
5663 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5664 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5665 size_t frame_size = channel_count * bytes_per_sample;
5666 size_t frame_count = bytes_to_write / frame_size;
5667
5668 bool force_haptic_path =
5669 property_get_bool("vendor.audio.test_haptic", false);
5670
5671 // extract Haptics data from Audio buffer
5672 bool alloc_haptic_buffer = false;
5673 int haptic_channel_count = adev->haptics_config.channels;
5674 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5675 size_t audio_frame_size = frame_size - haptic_frame_size;
5676 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5677
5678 if (adev->haptic_buffer == NULL) {
5679 alloc_haptic_buffer = true;
5680 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5681 free(adev->haptic_buffer);
5682 adev->haptic_buffer_size = 0;
5683 alloc_haptic_buffer = true;
5684 }
5685
5686 if (alloc_haptic_buffer) {
5687 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005688 if(adev->haptic_buffer == NULL) {
5689 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5690 return -ENOMEM;
5691 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005692 adev->haptic_buffer_size = total_haptic_buffer_size;
5693 }
5694
5695 size_t src_index = 0, aud_index = 0, hap_index = 0;
5696 uint8_t *audio_buffer = (uint8_t *)buffer;
5697 uint8_t *haptic_buffer = adev->haptic_buffer;
5698
5699 // This is required for testing only. This works for stereo data only.
5700 // One channel is fed to audio stream and other to haptic stream for testing.
5701 if (force_haptic_path)
5702 audio_frame_size = haptic_frame_size = bytes_per_sample;
5703
5704 for (size_t i = 0; i < frame_count; i++) {
5705 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5706 audio_frame_size);
5707 aud_index += audio_frame_size;
5708 src_index += audio_frame_size;
5709
5710 if (adev->haptic_pcm)
5711 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5712 haptic_frame_size);
5713 hap_index += haptic_frame_size;
5714 src_index += haptic_frame_size;
5715
5716 // This is required for testing only.
5717 // Discard haptic channel data.
5718 if (force_haptic_path)
5719 src_index += haptic_frame_size;
5720 }
5721
5722 // write to audio pipeline
5723 ret = pcm_write(out->pcm, (void *)audio_buffer,
5724 frame_count * audio_frame_size);
5725
5726 // write to haptics pipeline
5727 if (adev->haptic_pcm)
5728 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5729 frame_count * haptic_frame_size);
5730
5731 return ret;
5732}
5733
Aalique Grahame22e49102018-12-18 14:23:57 -08005734#ifdef NO_AUDIO_OUT
5735static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5736 const void *buffer __unused, size_t bytes)
5737{
5738 struct stream_out *out = (struct stream_out *)stream;
5739
5740 /* No Output device supported other than BT for playback.
5741 * Sleep for the amount of buffer duration
5742 */
5743 lock_output_stream(out);
5744 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5745 (const struct audio_stream_out *)&out->stream) /
5746 out_get_sample_rate(&out->stream.common));
5747 pthread_mutex_unlock(&out->lock);
5748 return bytes;
5749}
5750#endif
5751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005752static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5753 size_t bytes)
5754{
5755 struct stream_out *out = (struct stream_out *)stream;
5756 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005757 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305758 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005759 const size_t frame_size = audio_stream_out_frame_size(stream);
5760 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305761 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005762 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005763
Haynes Mathew George380745d2017-10-04 15:27:45 -07005764 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005765 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305766
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305767 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005768
Dhananjay Kumarac341582017-02-23 23:42:25 +05305769 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305770 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305771 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5772 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005773 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305774 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305775 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305776 ALOGD(" %s: sound card is not active/SSR state", __func__);
5777 ret= -EIO;
5778 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305779 }
5780 }
5781
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305782 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305783 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305784 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305785 goto exit;
5786 }
5787
Haynes Mathew George16081042017-05-31 17:16:49 -07005788 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5789 ret = -EINVAL;
5790 goto exit;
5791 }
5792
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005793 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305794 !out->is_iec61937_info_available) {
5795
5796 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5797 out->is_iec61937_info_available = true;
5798 } else if (audio_extn_passthru_is_enabled()) {
5799 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305800 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305801
5802 if((out->format == AUDIO_FORMAT_DTS) ||
5803 (out->format == AUDIO_FORMAT_DTS_HD)) {
5804 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5805 buffer, bytes);
5806 if (ret) {
5807 if (ret != -ENOSYS) {
5808 out->is_iec61937_info_available = false;
5809 ALOGD("iec61937 transmission info not yet updated retry");
5810 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305811 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305812 /* if stream has started and after that there is
5813 * stream config change (iec transmission config)
5814 * then trigger select_device to update backend configuration.
5815 */
5816 out->stream_config_changed = true;
5817 pthread_mutex_lock(&adev->lock);
5818 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305819 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005820 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305821 ret = -EINVAL;
5822 goto exit;
5823 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305824 pthread_mutex_unlock(&adev->lock);
5825 out->stream_config_changed = false;
5826 out->is_iec61937_info_available = true;
5827 }
5828 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305829
Meng Wang4c32fb42020-01-16 17:57:11 +08005830#ifdef AUDIO_GKI_ENABLED
5831 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5832 compr_passthr = out->compr_config.codec->reserved[0];
5833#else
5834 compr_passthr = out->compr_config.codec->compr_passthr;
5835#endif
5836
Garmond Leung317cbf12017-09-13 16:20:50 -07005837 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005838 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305839 (out->is_iec61937_info_available == true)) {
5840 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5841 ret = -EINVAL;
5842 goto exit;
5843 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305844 }
5845 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305846
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005847 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005848 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005849 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5850 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Song9ebf6792020-09-23 22:49:01 +08005851 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305852 ret = -EIO;
5853 goto exit;
5854 }
5855 }
5856 }
5857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005858 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005859 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005860 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5861
Eric Laurent150dbfe2013-02-27 14:31:02 -08005862 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005863 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5864 ret = voice_extn_compress_voip_start_output_stream(out);
5865 else
5866 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005867 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005869 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005870 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005871 goto exit;
5872 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305873 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005874 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005875
5876 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005877 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005878 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305879 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005880 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005881 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305882
5883 if ((out->is_iec61937_info_available == true) &&
5884 (audio_extn_passthru_is_passthrough_stream(out))&&
5885 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5886 ret = -EINVAL;
5887 goto exit;
5888 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305889 if (out->set_dual_mono)
5890 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005891
5892 // log startup time in ms.
5893 simple_stats_log(
5894 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005895 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005896
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005897 if (adev->is_channel_status_set == false &&
5898 compare_device_type(&out->device_list,
5899 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005900 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305901 adev->is_channel_status_set = true;
5902 }
5903
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305904 if ((adev->use_old_pspd_mix_ctrl == true) &&
5905 (out->pspd_coeff_sent == false)) {
5906 /*
5907 * Need to resend pspd coefficients after stream started for
5908 * older kernel version as it does not save the coefficients
5909 * and also stream has to be started for coeff to apply.
5910 */
5911 usecase = get_usecase_from_list(adev, out->usecase);
5912 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305913 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305914 out->pspd_coeff_sent = true;
5915 }
5916 }
5917
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005918 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005919 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005920 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005921 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005922 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5923 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305924 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5925 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005926 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305927 out->send_next_track_params = false;
5928 out->is_compr_metadata_avail = false;
5929 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005930 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305931 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305932 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005933
Ashish Jain83a6cc22016-06-28 14:34:17 +05305934 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305935 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305936 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305937 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005938 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305939 return -EINVAL;
5940 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305941 audio_format_t dst_format = out->hal_op_format;
5942 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305943
Dieter Luecking5d57def2018-09-07 14:23:37 +02005944 /* prevent division-by-zero */
5945 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5946 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5947 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5948 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305949 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005950 ATRACE_END();
5951 return -EINVAL;
5952 }
5953
Ashish Jainf1eaa582016-05-23 20:54:24 +05305954 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5955 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5956
Ashish Jain83a6cc22016-06-28 14:34:17 +05305957 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305958 dst_format,
5959 buffer,
5960 src_format,
5961 frames);
5962
Ashish Jain83a6cc22016-06-28 14:34:17 +05305963 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305964 bytes_to_write);
5965
5966 /*Convert written bytes in audio flinger format*/
5967 if (ret > 0)
5968 ret = ((ret * format_to_bitwidth_table[out->format]) /
5969 format_to_bitwidth_table[dst_format]);
5970 }
5971 } else
5972 ret = compress_write(out->compr, buffer, bytes);
5973
Zhou Songc9672822017-08-16 16:01:39 +08005974 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5975 update_frames_written(out, bytes);
5976
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305977 if (ret < 0)
5978 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005979 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305980 /*msg to cb thread only if non blocking write is enabled*/
5981 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305982 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005983 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305984 } else if (-ENETRESET == ret) {
5985 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305986 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305987 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305988 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005989 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305990 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005991 }
Ashish Jain5106d362016-05-11 19:23:33 +05305992
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305993 /* Call compr start only when non-zero bytes of data is there to be rendered */
5994 if (!out->playback_started && ret > 0) {
5995 int status = compress_start(out->compr);
5996 if (status < 0) {
5997 ret = status;
5998 ALOGE("%s: compr start failed with err %d", __func__, errno);
5999 goto exit;
6000 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006001 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006002 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006003 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006004 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006005 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006006
6007 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6008 popcount(out->channel_mask),
6009 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006010 }
6011 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006012 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013 return ret;
6014 } else {
6015 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006016 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006017 if (out->muted)
6018 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006019 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6020 __func__, frames, frame_size, bytes_to_write);
6021
Aalique Grahame22e49102018-12-18 14:23:57 -08006022 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006023 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6024 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6025 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006026 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6027 int16_t *src = (int16_t *)buffer;
6028 int16_t *dst = (int16_t *)buffer;
6029
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006030 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006031 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006032 "out_write called for %s use case with wrong properties",
6033 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006034
6035 /*
6036 * FIXME: this can be removed once audio flinger mixer supports
6037 * mono output
6038 */
6039
6040 /*
6041 * Code below goes over each frame in the buffer and adds both
6042 * L and R samples and then divides by 2 to convert to mono
6043 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006044 if (channel_count == 2) {
6045 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6046 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6047 }
6048 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006049 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006050 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006051
6052 // Note: since out_get_presentation_position() is called alternating with out_write()
6053 // by AudioFlinger, we can check underruns using the prior timestamp read.
6054 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6055 if (out->last_fifo_valid) {
6056 // compute drain to see if there is an underrun.
6057 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306058 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6059 int64_t frames_by_time =
6060 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6061 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006062 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6063
6064 if (underrun > 0) {
6065 simple_stats_log(&out->fifo_underruns, underrun);
6066
6067 ALOGW("%s: underrun(%lld) "
6068 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6069 __func__,
6070 (long long)out->fifo_underruns.n,
6071 (long long)frames_by_time,
6072 (long long)out->last_fifo_frames_remaining);
6073 }
6074 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6075 }
6076
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306077 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006078
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006079 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006080
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006081 if (out->config.rate)
6082 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6083 out->config.rate;
6084
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006085 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006086 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6087
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006088 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006089 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006090 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306091 out->convert_buffer != NULL) {
6092
6093 memcpy_by_audio_format(out->convert_buffer,
6094 out->hal_op_format,
6095 buffer,
6096 out->hal_ip_format,
6097 out->config.period_size * out->config.channels);
6098
6099 ret = pcm_write(out->pcm, out->convert_buffer,
6100 (out->config.period_size *
6101 out->config.channels *
6102 format_to_bitwidth_table[out->hal_op_format]));
6103 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306104 /*
6105 * To avoid underrun in DSP when the application is not pumping
6106 * data at required rate, check for the no. of bytes and ignore
6107 * pcm_write if it is less than actual buffer size.
6108 * It is a work around to a change in compress VOIP driver.
6109 */
6110 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6111 bytes < (out->config.period_size * out->config.channels *
6112 audio_bytes_per_sample(out->format))) {
6113 size_t voip_buf_size =
6114 out->config.period_size * out->config.channels *
6115 audio_bytes_per_sample(out->format);
6116 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6117 __func__, bytes, voip_buf_size);
6118 usleep(((uint64_t)voip_buf_size - bytes) *
6119 1000000 / audio_stream_out_frame_size(stream) /
6120 out_get_sample_rate(&out->stream.common));
6121 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006122 } else {
6123 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6124 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6125 else
6126 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6127 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306128 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006129
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006130 release_out_focus(out);
6131
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306132 if (ret < 0)
6133 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006134 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306135 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006137 }
6138
6139exit:
Zhou Songc9672822017-08-16 16:01:39 +08006140 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306141 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306142 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006144 pthread_mutex_unlock(&out->lock);
6145
6146 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006147 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006148 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306149 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306150 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306151 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306152 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306153 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306154 out->standby = true;
6155 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306156 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006157 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6158 /* prevent division-by-zero */
6159 uint32_t stream_size = audio_stream_out_frame_size(stream);
6160 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006161
Dieter Luecking5d57def2018-09-07 14:23:37 +02006162 if ((stream_size == 0) || (srate == 0)) {
6163 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6164 ATRACE_END();
6165 return -EINVAL;
6166 }
6167 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6168 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006169 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306170 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006171 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006172 return ret;
6173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006174 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006175 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006176 return bytes;
6177}
6178
6179static int out_get_render_position(const struct audio_stream_out *stream,
6180 uint32_t *dsp_frames)
6181{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006182 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006183
6184 if (dsp_frames == NULL)
6185 return -EINVAL;
6186
6187 *dsp_frames = 0;
6188 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006189 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306190
6191 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6192 * this operation and adev_close_output_stream(where out gets reset).
6193 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306194 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006195 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306196 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006197 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306198 return 0;
6199 }
6200
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006201 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306202 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306203 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006204 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306205 if (ret < 0)
6206 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006207 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306208 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006209 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306210 if (-ENETRESET == ret) {
6211 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306212 out->card_status = CARD_STATUS_OFFLINE;
6213 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306214 } else if(ret < 0) {
6215 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306216 ret = -EINVAL;
6217 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306218 /*
6219 * Handle corner case where compress session is closed during SSR
6220 * and timestamp is queried
6221 */
6222 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306223 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306224 } else if (out->prev_card_status_offline) {
6225 ALOGE("ERROR: previously sound card was offline,return error");
6226 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306227 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306228 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006229 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306230 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306231 pthread_mutex_unlock(&out->lock);
6232 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006233 } else if (audio_is_linear_pcm(out->format)) {
6234 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006235 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006236 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006237 } else
6238 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006239}
6240
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006241static int out_add_audio_effect(const struct audio_stream *stream __unused,
6242 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006243{
6244 return 0;
6245}
6246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006247static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6248 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006249{
6250 return 0;
6251}
6252
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006253static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6254 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306256 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257}
6258
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006259static int out_get_presentation_position(const struct audio_stream_out *stream,
6260 uint64_t *frames, struct timespec *timestamp)
6261{
6262 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306263 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006264 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006265
Ashish Jain5106d362016-05-11 19:23:33 +05306266 /* below piece of code is not guarded against any lock because audioFliner serializes
6267 * this operation and adev_close_output_stream( where out gets reset).
6268 */
6269 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306270 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006271 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306272 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6273 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6274 return 0;
6275 }
6276
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006277 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006278
Ashish Jain5106d362016-05-11 19:23:33 +05306279 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6280 ret = compress_get_tstamp(out->compr, &dsp_frames,
6281 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006282 // Adjustment accounts for A2dp encoder latency with offload usecases
6283 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006284 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006285 unsigned long offset =
6286 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6287 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6288 }
Ashish Jain5106d362016-05-11 19:23:33 +05306289 ALOGVV("%s rendered frames %ld sample_rate %d",
6290 __func__, dsp_frames, out->sample_rate);
6291 *frames = dsp_frames;
6292 if (ret < 0)
6293 ret = -errno;
6294 if (-ENETRESET == ret) {
6295 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306296 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306297 ret = -EINVAL;
6298 } else
6299 ret = 0;
6300 /* this is the best we can do */
6301 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006302 } else {
6303 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006304 unsigned int avail;
6305 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006306 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006307 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006308
Andy Hunga1f48fa2019-07-01 18:14:53 -07006309 if (out->kernel_buffer_size > avail) {
6310 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6311 } else {
6312 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6313 __func__, avail, out->kernel_buffer_size);
6314 avail = out->kernel_buffer_size;
6315 frames_temp = out->last_fifo_frames_remaining = 0;
6316 }
6317 out->last_fifo_valid = true;
6318 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6319
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006320 if (out->written >= frames_temp)
6321 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006322
Andy Hunga1f48fa2019-07-01 18:14:53 -07006323 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6324 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6325
Weiyin Jiangd4633762018-03-16 12:05:03 +08006326 // This adjustment accounts for buffering after app processor.
6327 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006328 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006329 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006330 if (signed_frames >= frames_temp)
6331 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006332
Weiyin Jiangd4633762018-03-16 12:05:03 +08006333 // Adjustment accounts for A2dp encoder latency with non offload usecases
6334 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006335 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006336 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6337 if (signed_frames >= frames_temp)
6338 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006339 }
6340
6341 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006342 *frames = signed_frames;
6343 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006344 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006345 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6346 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006347 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306348 *frames = out->written;
6349 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306350 if (is_offload_usecase(out->usecase))
6351 ret = -EINVAL;
6352 else
6353 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006354 }
6355 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006356 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006357 return ret;
6358}
6359
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006360static int out_set_callback(struct audio_stream_out *stream,
6361 stream_callback_t callback, void *cookie)
6362{
6363 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006364 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006365
6366 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006367 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006368 out->client_callback = callback;
6369 out->client_cookie = cookie;
6370 if (out->adsp_hdlr_stream_handle) {
6371 ret = audio_extn_adsp_hdlr_stream_set_callback(
6372 out->adsp_hdlr_stream_handle,
6373 callback,
6374 cookie);
6375 if (ret)
6376 ALOGW("%s:adsp hdlr callback registration failed %d",
6377 __func__, ret);
6378 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006379 pthread_mutex_unlock(&out->lock);
6380 return 0;
6381}
6382
6383static int out_pause(struct audio_stream_out* stream)
6384{
6385 struct stream_out *out = (struct stream_out *)stream;
6386 int status = -ENOSYS;
6387 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006388 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006389 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306390 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006391 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006392 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006393 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306394 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306395 status = compress_pause(out->compr);
6396
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006397 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006398
Mingming Yin21854652016-04-13 11:54:02 -07006399 if (audio_extn_passthru_is_active()) {
6400 ALOGV("offload use case, pause passthru");
6401 audio_extn_passthru_on_pause(out);
6402 }
6403
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306404 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006405 audio_extn_dts_notify_playback_state(out->usecase, 0,
6406 out->sample_rate, popcount(out->channel_mask),
6407 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006408 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006409 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006410 pthread_mutex_unlock(&out->lock);
6411 }
6412 return status;
6413}
6414
6415static int out_resume(struct audio_stream_out* stream)
6416{
6417 struct stream_out *out = (struct stream_out *)stream;
6418 int status = -ENOSYS;
6419 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006420 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006421 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306422 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006423 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006424 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006425 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306426 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306427 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006428 }
6429 if (!status) {
6430 out->offload_state = OFFLOAD_STATE_PLAYING;
6431 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306432 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006433 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6434 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006435 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006436 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006437 pthread_mutex_unlock(&out->lock);
6438 }
6439 return status;
6440}
6441
6442static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6443{
6444 struct stream_out *out = (struct stream_out *)stream;
6445 int status = -ENOSYS;
6446 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006447 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006448 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006449 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6450 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6451 else
6452 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6453 pthread_mutex_unlock(&out->lock);
6454 }
6455 return status;
6456}
6457
6458static int out_flush(struct audio_stream_out* stream)
6459{
6460 struct stream_out *out = (struct stream_out *)stream;
6461 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006462 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006463 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006464 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006465 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006466 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manamfeeb1162020-12-24 14:08:04 +05306467 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006468 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006469 } else {
6470 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manamfeeb1162020-12-24 14:08:04 +05306471 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006472 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006473 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006474 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006475 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006476 return 0;
6477 }
6478 return -ENOSYS;
6479}
6480
Haynes Mathew George16081042017-05-31 17:16:49 -07006481static int out_stop(const struct audio_stream_out* stream)
6482{
6483 struct stream_out *out = (struct stream_out *)stream;
6484 struct audio_device *adev = out->dev;
6485 int ret = -ENOSYS;
6486
6487 ALOGV("%s", __func__);
6488 pthread_mutex_lock(&adev->lock);
6489 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6490 out->playback_started && out->pcm != NULL) {
6491 pcm_stop(out->pcm);
6492 ret = stop_output_stream(out);
6493 out->playback_started = false;
6494 }
6495 pthread_mutex_unlock(&adev->lock);
6496 return ret;
6497}
6498
6499static int out_start(const struct audio_stream_out* stream)
6500{
6501 struct stream_out *out = (struct stream_out *)stream;
6502 struct audio_device *adev = out->dev;
6503 int ret = -ENOSYS;
6504
6505 ALOGV("%s", __func__);
6506 pthread_mutex_lock(&adev->lock);
6507 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6508 !out->playback_started && out->pcm != NULL) {
6509 ret = start_output_stream(out);
6510 if (ret == 0) {
6511 out->playback_started = true;
6512 }
6513 }
6514 pthread_mutex_unlock(&adev->lock);
6515 return ret;
6516}
6517
6518/*
6519 * Modify config->period_count based on min_size_frames
6520 */
6521static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6522{
6523 int periodCountRequested = (min_size_frames + config->period_size - 1)
6524 / config->period_size;
6525 int periodCount = MMAP_PERIOD_COUNT_MIN;
6526
6527 ALOGV("%s original config.period_size = %d config.period_count = %d",
6528 __func__, config->period_size, config->period_count);
6529
6530 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6531 periodCount *= 2;
6532 }
6533 config->period_count = periodCount;
6534
6535 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6536}
6537
Phil Burkfe17efd2019-03-25 10:23:35 -07006538// Read offset for the positional timestamp from a persistent vendor property.
6539// This is to workaround apparent inaccuracies in the timing information that
6540// is used by the AAudio timing model. The inaccuracies can cause glitches.
6541static int64_t get_mmap_out_time_offset() {
6542 const int32_t kDefaultOffsetMicros = 0;
6543 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006544 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006545 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6546 return mmap_time_offset_micros * (int64_t)1000;
6547}
6548
Haynes Mathew George16081042017-05-31 17:16:49 -07006549static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6550 int32_t min_size_frames,
6551 struct audio_mmap_buffer_info *info)
6552{
6553 struct stream_out *out = (struct stream_out *)stream;
6554 struct audio_device *adev = out->dev;
6555 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006556 unsigned int offset1 = 0;
6557 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006558 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006559 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006560 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006561
Arun Mirpuri5d170872019-03-26 13:21:31 -07006562 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306563 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006564 pthread_mutex_lock(&adev->lock);
6565
Sharad Sanglec6f32552018-05-04 16:15:38 +05306566 if (CARD_STATUS_OFFLINE == out->card_status ||
6567 CARD_STATUS_OFFLINE == adev->card_status) {
6568 ALOGW("out->card_status or adev->card_status offline, try again");
6569 ret = -EIO;
6570 goto exit;
6571 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306572 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006573 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6574 ret = -EINVAL;
6575 goto exit;
6576 }
6577 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6578 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6579 ret = -ENOSYS;
6580 goto exit;
6581 }
6582 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6583 if (out->pcm_device_id < 0) {
6584 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6585 __func__, out->pcm_device_id, out->usecase);
6586 ret = -EINVAL;
6587 goto exit;
6588 }
6589
6590 adjust_mmap_period_count(&out->config, min_size_frames);
6591
Arun Mirpuri5d170872019-03-26 13:21:31 -07006592 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006593 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6594 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6595 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306596 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306597 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6598 out->card_status = CARD_STATUS_OFFLINE;
6599 adev->card_status = CARD_STATUS_OFFLINE;
6600 ret = -EIO;
6601 goto exit;
6602 }
6603
Haynes Mathew George16081042017-05-31 17:16:49 -07006604 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6605 step = "open";
6606 ret = -ENODEV;
6607 goto exit;
6608 }
6609 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6610 if (ret < 0) {
6611 step = "begin";
6612 goto exit;
6613 }
juyuchen626833d2019-06-04 16:48:02 +08006614
6615 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006616 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006617 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006618 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006619 ret = platform_get_mmap_data_fd(adev->platform,
6620 out->pcm_device_id, 0 /*playback*/,
6621 &info->shared_memory_fd,
6622 &mmap_size);
6623 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006624 // Fall back to non exclusive mode
6625 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6626 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006627 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6628 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6629
Arun Mirpuri5d170872019-03-26 13:21:31 -07006630 if (mmap_size < buffer_size) {
6631 step = "mmap";
6632 goto exit;
6633 }
juyuchen626833d2019-06-04 16:48:02 +08006634 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006635 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006636 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006637 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006638
6639 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6640 if (ret < 0) {
6641 step = "commit";
6642 goto exit;
6643 }
6644
Phil Burkfe17efd2019-03-25 10:23:35 -07006645 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6646
Haynes Mathew George16081042017-05-31 17:16:49 -07006647 out->standby = false;
6648 ret = 0;
6649
Arun Mirpuri5d170872019-03-26 13:21:31 -07006650 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006651 __func__, info->shared_memory_address, info->buffer_size_frames);
6652
6653exit:
6654 if (ret != 0) {
6655 if (out->pcm == NULL) {
6656 ALOGE("%s: %s - %d", __func__, step, ret);
6657 } else {
6658 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6659 pcm_close(out->pcm);
6660 out->pcm = NULL;
6661 }
6662 }
6663 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306664 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006665 return ret;
6666}
6667
6668static int out_get_mmap_position(const struct audio_stream_out *stream,
6669 struct audio_mmap_position *position)
6670{
6671 struct stream_out *out = (struct stream_out *)stream;
6672 ALOGVV("%s", __func__);
6673 if (position == NULL) {
6674 return -EINVAL;
6675 }
6676 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006677 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006678 return -ENOSYS;
6679 }
6680 if (out->pcm == NULL) {
6681 return -ENOSYS;
6682 }
6683
6684 struct timespec ts = { 0, 0 };
6685 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6686 if (ret < 0) {
6687 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6688 return ret;
6689 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006690 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6691 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006692 return 0;
6693}
6694
6695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006696/** audio_stream_in implementation **/
6697static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6698{
6699 struct stream_in *in = (struct stream_in *)stream;
6700
6701 return in->config.rate;
6702}
6703
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006704static int in_set_sample_rate(struct audio_stream *stream __unused,
6705 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006706{
6707 return -ENOSYS;
6708}
6709
6710static size_t in_get_buffer_size(const struct audio_stream *stream)
6711{
6712 struct stream_in *in = (struct stream_in *)stream;
6713
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006714 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6715 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006716 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6717 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306718 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306719 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006720
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006721 return in->config.period_size * in->af_period_multiplier *
6722 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723}
6724
6725static uint32_t in_get_channels(const struct audio_stream *stream)
6726{
6727 struct stream_in *in = (struct stream_in *)stream;
6728
6729 return in->channel_mask;
6730}
6731
6732static audio_format_t in_get_format(const struct audio_stream *stream)
6733{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006734 struct stream_in *in = (struct stream_in *)stream;
6735
6736 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006737}
6738
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006739static int in_set_format(struct audio_stream *stream __unused,
6740 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006741{
6742 return -ENOSYS;
6743}
6744
6745static int in_standby(struct audio_stream *stream)
6746{
6747 struct stream_in *in = (struct stream_in *)stream;
6748 struct audio_device *adev = in->dev;
6749 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306750 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6751 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006752 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306753
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006754 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006755 if (!in->standby && in->is_st_session) {
6756 ALOGD("%s: sound trigger pcm stop lab", __func__);
6757 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006758 if (adev->num_va_sessions > 0)
6759 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006760 in->standby = 1;
6761 }
6762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006763 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006764 if (adev->adm_deregister_stream)
6765 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6766
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006767 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006768 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006769 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006770 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006771 voice_extn_compress_voip_close_input_stream(stream);
6772 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006773 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6774 do_stop = in->capture_started;
6775 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006776 if (in->mmap_shared_memory_fd >= 0) {
6777 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6778 __func__, in->mmap_shared_memory_fd);
6779 close(in->mmap_shared_memory_fd);
6780 in->mmap_shared_memory_fd = -1;
6781 }
Zhou Songa8895042016-07-05 17:54:22 +08006782 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306783 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306784 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006785 }
6786
Arun Mirpuri5d170872019-03-26 13:21:31 -07006787 if (in->pcm) {
6788 ATRACE_BEGIN("pcm_in_close");
6789 pcm_close(in->pcm);
6790 ATRACE_END();
6791 in->pcm = NULL;
6792 }
6793
Carter Hsu2e429db2019-05-14 18:50:52 +08006794 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006795 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006796
George Gao3018ede2019-10-23 13:23:00 -07006797 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6798 if (adev->num_va_sessions > 0)
6799 adev->num_va_sessions--;
6800 }
Quinn Malef6050362019-01-30 15:55:40 -08006801
Eric Laurent150dbfe2013-02-27 14:31:02 -08006802 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006803 }
6804 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006805 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006806 return status;
6807}
6808
Aalique Grahame22e49102018-12-18 14:23:57 -08006809static int in_dump(const struct audio_stream *stream,
6810 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006811{
Aalique Grahame22e49102018-12-18 14:23:57 -08006812 struct stream_in *in = (struct stream_in *)stream;
6813
6814 // We try to get the lock for consistency,
6815 // but it isn't necessary for these variables.
6816 // If we're not in standby, we may be blocked on a read.
6817 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6818 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6819 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6820 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6821
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006822 char buffer[256]; // for statistics formatting
6823 if (in->start_latency_ms.n > 0) {
6824 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6825 dprintf(fd, " Start latency ms: %s\n", buffer);
6826 }
6827
Aalique Grahame22e49102018-12-18 14:23:57 -08006828 if (locked) {
6829 pthread_mutex_unlock(&in->lock);
6830 }
6831
6832 // dump error info
6833 (void)error_log_dump(
6834 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 return 0;
6837}
6838
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306839static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6840{
6841 if (!stream || !parms)
6842 return;
6843
6844 struct stream_in *in = (struct stream_in *)stream;
6845 struct audio_device *adev = in->dev;
6846
6847 card_status_t status;
6848 int card;
6849 if (parse_snd_card_status(parms, &card, &status) < 0)
6850 return;
6851
6852 pthread_mutex_lock(&adev->lock);
6853 bool valid_cb = (card == adev->snd_card);
6854 pthread_mutex_unlock(&adev->lock);
6855
6856 if (!valid_cb)
6857 return;
6858
6859 lock_input_stream(in);
6860 if (in->card_status != status)
6861 in->card_status = status;
6862 pthread_mutex_unlock(&in->lock);
6863
6864 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6865 use_case_table[in->usecase],
6866 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6867
6868 // a better solution would be to report error back to AF and let
6869 // it put the stream to standby
6870 if (status == CARD_STATUS_OFFLINE)
6871 in_standby(&in->stream.common);
6872
6873 return;
6874}
6875
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006876int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006877 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006878 audio_source_t source)
6879{
6880 struct audio_device *adev = in->dev;
6881 int ret = 0;
6882
6883 lock_input_stream(in);
6884 pthread_mutex_lock(&adev->lock);
6885
6886 /* no audio source uses val == 0 */
6887 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6888 in->source = source;
6889 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6890 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6891 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6892 (in->config.rate == 8000 || in->config.rate == 16000 ||
6893 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6894 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6895 ret = voice_extn_compress_voip_open_input_stream(in);
6896 if (ret != 0) {
6897 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6898 __func__, ret);
6899 }
6900 }
6901 }
6902
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006903 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6904 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006905 // Workaround: If routing to an non existing usb device, fail gracefully
6906 // The routing request will otherwise block during 10 second
6907 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006908 struct str_parms *usb_addr =
6909 str_parms_create_str(get_usb_device_address(devices));
6910 if (is_usb_in_device_type(devices) && usb_addr &&
6911 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006912 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6913 ret = -ENOSYS;
6914 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006915 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006916 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006917 if (!in->standby && !in->is_st_session) {
6918 ALOGV("update input routing change");
6919 // inform adm before actual routing to prevent glitches.
6920 if (adev->adm_on_routing_change) {
6921 adev->adm_on_routing_change(adev->adm_data,
6922 in->capture_handle);
6923 ret = select_devices(adev, in->usecase);
6924 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6925 adev->adm_routing_changed = true;
6926 }
6927 }
6928 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006929 if (usb_addr)
6930 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006931 }
6932 pthread_mutex_unlock(&adev->lock);
6933 pthread_mutex_unlock(&in->lock);
6934
6935 ALOGD("%s: exit: status(%d)", __func__, ret);
6936 return ret;
6937}
6938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006939static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6940{
6941 struct stream_in *in = (struct stream_in *)stream;
6942 struct audio_device *adev = in->dev;
6943 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006944 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306945 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006946
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306947 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006948 parms = str_parms_create_str(kvpairs);
6949
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306950 if (!parms)
6951 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006952 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006953 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006954
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306955 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6956 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306957 strlcpy(in->profile, value, sizeof(in->profile));
6958 ALOGV("updating stream profile with value '%s'", in->profile);
6959 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6960 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006961 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306962 in->sample_rate, in->bit_width,
6963 in->profile, &in->app_type_cfg);
6964 }
6965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006966 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006967 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006968
6969 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306970error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306971 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006972}
6973
6974static char* in_get_parameters(const struct audio_stream *stream,
6975 const char *keys)
6976{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006977 struct stream_in *in = (struct stream_in *)stream;
6978 struct str_parms *query = str_parms_create_str(keys);
6979 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006980 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006981
6982 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006983 if (reply) {
6984 str_parms_destroy(reply);
6985 }
6986 if (query) {
6987 str_parms_destroy(query);
6988 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006989 ALOGE("in_get_parameters: failed to create query or reply");
6990 return NULL;
6991 }
6992
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006993 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006994
6995 voice_extn_in_get_parameters(in, query, reply);
6996
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006997 stream_get_parameter_channels(query, reply,
6998 &in->supported_channel_masks[0]);
6999 stream_get_parameter_formats(query, reply,
7000 &in->supported_formats[0]);
7001 stream_get_parameter_rates(query, reply,
7002 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007003 str = str_parms_to_str(reply);
7004 str_parms_destroy(query);
7005 str_parms_destroy(reply);
7006
7007 ALOGV("%s: exit: returns - %s", __func__, str);
7008 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009}
7010
Aalique Grahame22e49102018-12-18 14:23:57 -08007011static int in_set_gain(struct audio_stream_in *stream,
7012 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007013{
Aalique Grahame22e49102018-12-18 14:23:57 -08007014 struct stream_in *in = (struct stream_in *)stream;
7015 char mixer_ctl_name[128];
7016 struct mixer_ctl *ctl;
7017 int ctl_value;
7018
7019 ALOGV("%s: gain %f", __func__, gain);
7020
7021 if (stream == NULL)
7022 return -EINVAL;
7023
7024 /* in_set_gain() only used to silence MMAP capture for now */
7025 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7026 return -ENOSYS;
7027
7028 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7029
7030 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7031 if (!ctl) {
7032 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7033 __func__, mixer_ctl_name);
7034 return -ENOSYS;
7035 }
7036
7037 if (gain < RECORD_GAIN_MIN)
7038 gain = RECORD_GAIN_MIN;
7039 else if (gain > RECORD_GAIN_MAX)
7040 gain = RECORD_GAIN_MAX;
7041 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7042
7043 mixer_ctl_set_value(ctl, 0, ctl_value);
7044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007045 return 0;
7046}
7047
7048static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7049 size_t bytes)
7050{
7051 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307052
7053 if (in == NULL) {
7054 ALOGE("%s: stream_in ptr is NULL", __func__);
7055 return -EINVAL;
7056 }
7057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007058 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307059 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307060 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007062 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307063
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007064 if (in->is_st_session) {
7065 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7066 /* Read from sound trigger HAL */
7067 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007068 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007069 if (adev->num_va_sessions < UINT_MAX)
7070 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007071 in->standby = 0;
7072 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007073 pthread_mutex_unlock(&in->lock);
7074 return bytes;
7075 }
7076
Haynes Mathew George16081042017-05-31 17:16:49 -07007077 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7078 ret = -ENOSYS;
7079 goto exit;
7080 }
7081
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007082 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7083 !in->standby && adev->adm_routing_changed) {
7084 ret = -ENOSYS;
7085 goto exit;
7086 }
7087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007088 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007089 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7090
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007091 pthread_mutex_lock(&adev->lock);
7092 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7093 ret = voice_extn_compress_voip_start_input_stream(in);
7094 else
7095 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007096 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7097 if (adev->num_va_sessions < UINT_MAX)
7098 adev->num_va_sessions++;
7099 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007100 pthread_mutex_unlock(&adev->lock);
7101 if (ret != 0) {
7102 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007103 }
7104 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007105
7106 // log startup time in ms.
7107 simple_stats_log(
7108 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007110
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307111 /* Avoid read if capture_stopped is set */
7112 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7113 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7114 ret = -EINVAL;
7115 goto exit;
7116 }
7117
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007118 // what's the duration requested by the client?
7119 long ns = 0;
7120
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307121 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007122 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7123 in->config.rate;
7124
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007125 ret = request_in_focus(in, ns);
7126 if (ret != 0)
7127 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007128 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007129
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307130 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307131 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7132 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307133 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007134 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307135 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007136 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007137 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007138 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007139 } else if (audio_extn_ffv_get_stream() == in) {
7140 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307141 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007142 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307143 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7144 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7145 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7146 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307147 ret = -EINVAL;
7148 goto exit;
7149 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307150 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307151 ret = -errno;
7152 }
7153 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307154 /* bytes read is always set to bytes for non compress usecases */
7155 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007156 }
7157
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007158 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007160 /*
Quinn Malef6050362019-01-30 15:55:40 -08007161 * Instead of writing zeroes here, we could trust the hardware to always
7162 * provide zeroes when muted. This is also muted with voice recognition
7163 * usecases so that other clients do not have access to voice recognition
7164 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007165 */
Quinn Malef6050362019-01-30 15:55:40 -08007166 if ((ret == 0 && voice_get_mic_mute(adev) &&
7167 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007168 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7169 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007170 (adev->num_va_sessions &&
7171 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7172 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7173 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007174 memset(buffer, 0, bytes);
7175
7176exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307177 frame_size = audio_stream_in_frame_size(stream);
7178 if (frame_size > 0)
7179 in->frames_read += bytes_read/frame_size;
7180
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007181 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307182 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007183 pthread_mutex_unlock(&in->lock);
7184
7185 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307186 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307187 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307188 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307189 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307190 in->standby = true;
7191 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307192 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307193 bytes_read = bytes;
7194 memset(buffer, 0, bytes);
7195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007197 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7198 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007199 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307200 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307201 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007202 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307203 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007204}
7205
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007206static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207{
7208 return 0;
7209}
7210
Aalique Grahame22e49102018-12-18 14:23:57 -08007211static int in_get_capture_position(const struct audio_stream_in *stream,
7212 int64_t *frames, int64_t *time)
7213{
7214 if (stream == NULL || frames == NULL || time == NULL) {
7215 return -EINVAL;
7216 }
7217 struct stream_in *in = (struct stream_in *)stream;
7218 int ret = -ENOSYS;
7219
7220 lock_input_stream(in);
7221 // note: ST sessions do not close the alsa pcm driver synchronously
7222 // on standby. Therefore, we may return an error even though the
7223 // pcm stream is still opened.
7224 if (in->standby) {
7225 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7226 "%s stream in standby but pcm not NULL for non ST session", __func__);
7227 goto exit;
7228 }
7229 if (in->pcm) {
7230 struct timespec timestamp;
7231 unsigned int avail;
7232 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7233 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007234 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007235 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007236 ret = 0;
7237 }
7238 }
7239exit:
7240 pthread_mutex_unlock(&in->lock);
7241 return ret;
7242}
7243
Carter Hsu2e429db2019-05-14 18:50:52 +08007244static int in_update_effect_list(bool add, effect_handle_t effect,
7245 struct listnode *head)
7246{
7247 struct listnode *node;
7248 struct in_effect_list *elist = NULL;
7249 struct in_effect_list *target = NULL;
7250 int ret = 0;
7251
7252 if (!head)
7253 return ret;
7254
7255 list_for_each(node, head) {
7256 elist = node_to_item(node, struct in_effect_list, list);
7257 if (elist->handle == effect) {
7258 target = elist;
7259 break;
7260 }
7261 }
7262
7263 if (add) {
7264 if (target) {
7265 ALOGD("effect %p already exist", effect);
7266 return ret;
7267 }
7268
7269 target = (struct in_effect_list *)
7270 calloc(1, sizeof(struct in_effect_list));
7271
7272 if (!target) {
7273 ALOGE("%s:fail to allocate memory", __func__);
7274 return -ENOMEM;
7275 }
7276
7277 target->handle = effect;
7278 list_add_tail(head, &target->list);
7279 } else {
7280 if (target) {
7281 list_remove(&target->list);
7282 free(target);
7283 }
7284 }
7285
7286 return ret;
7287}
7288
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007289static int add_remove_audio_effect(const struct audio_stream *stream,
7290 effect_handle_t effect,
7291 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007292{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007293 struct stream_in *in = (struct stream_in *)stream;
7294 int status = 0;
7295 effect_descriptor_t desc;
7296
7297 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007298 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7299
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007300 if (status != 0)
7301 return status;
7302
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007303 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007304 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007305 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007306 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7307 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007308 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007309
7310 in_update_effect_list(enable, effect, &in->aec_list);
7311 enable = !list_empty(&in->aec_list);
7312 if (enable == in->enable_aec)
7313 goto exit;
7314
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007315 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007316 ALOGD("AEC enable %d", enable);
7317
Aalique Grahame22e49102018-12-18 14:23:57 -08007318 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7319 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7320 in->dev->enable_voicerx = enable;
7321 struct audio_usecase *usecase;
7322 struct listnode *node;
7323 list_for_each(node, &in->dev->usecase_list) {
7324 usecase = node_to_item(node, struct audio_usecase, list);
7325 if (usecase->type == PCM_PLAYBACK)
7326 select_devices(in->dev, usecase->id);
7327 }
7328 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007329 if (!in->standby) {
7330 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7331 select_devices(in->dev, in->usecase);
7332 }
7333
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007334 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007335 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7336
7337 in_update_effect_list(enable, effect, &in->ns_list);
7338 enable = !list_empty(&in->ns_list);
7339 if (enable == in->enable_ns)
7340 goto exit;
7341
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007342 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007343 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007344 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007345 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7346 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007347 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7348 select_devices(in->dev, in->usecase);
7349 } else
7350 select_devices(in->dev, in->usecase);
7351 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007352 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007353exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007354 pthread_mutex_unlock(&in->dev->lock);
7355 pthread_mutex_unlock(&in->lock);
7356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007357 return 0;
7358}
7359
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007360static int in_add_audio_effect(const struct audio_stream *stream,
7361 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362{
Eric Laurent994a6932013-07-17 11:51:42 -07007363 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007364 return add_remove_audio_effect(stream, effect, true);
7365}
7366
7367static int in_remove_audio_effect(const struct audio_stream *stream,
7368 effect_handle_t effect)
7369{
Eric Laurent994a6932013-07-17 11:51:42 -07007370 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007371 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007372}
7373
Derek Chenf939fb72018-11-13 13:34:41 -08007374streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7375 audio_io_handle_t input)
7376{
7377 struct listnode *node;
7378
7379 list_for_each(node, &dev->active_inputs_list) {
7380 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7381 streams_input_ctxt_t,
7382 list);
7383 if (in_ctxt->input->capture_handle == input) {
7384 return in_ctxt;
7385 }
7386 }
7387 return NULL;
7388}
7389
7390streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7391 audio_io_handle_t output)
7392{
7393 struct listnode *node;
7394
7395 list_for_each(node, &dev->active_outputs_list) {
7396 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7397 streams_output_ctxt_t,
7398 list);
7399 if (out_ctxt->output->handle == output) {
7400 return out_ctxt;
7401 }
7402 }
7403 return NULL;
7404}
7405
Haynes Mathew George16081042017-05-31 17:16:49 -07007406static int in_stop(const struct audio_stream_in* stream)
7407{
7408 struct stream_in *in = (struct stream_in *)stream;
7409 struct audio_device *adev = in->dev;
7410
7411 int ret = -ENOSYS;
7412 ALOGV("%s", __func__);
7413 pthread_mutex_lock(&adev->lock);
7414 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7415 in->capture_started && in->pcm != NULL) {
7416 pcm_stop(in->pcm);
7417 ret = stop_input_stream(in);
7418 in->capture_started = false;
7419 }
7420 pthread_mutex_unlock(&adev->lock);
7421 return ret;
7422}
7423
7424static int in_start(const struct audio_stream_in* stream)
7425{
7426 struct stream_in *in = (struct stream_in *)stream;
7427 struct audio_device *adev = in->dev;
7428 int ret = -ENOSYS;
7429
7430 ALOGV("%s in %p", __func__, in);
7431 pthread_mutex_lock(&adev->lock);
7432 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7433 !in->capture_started && in->pcm != NULL) {
7434 if (!in->capture_started) {
7435 ret = start_input_stream(in);
7436 if (ret == 0) {
7437 in->capture_started = true;
7438 }
7439 }
7440 }
7441 pthread_mutex_unlock(&adev->lock);
7442 return ret;
7443}
7444
Phil Burke0a86d12019-02-16 22:28:11 -08007445// Read offset for the positional timestamp from a persistent vendor property.
7446// This is to workaround apparent inaccuracies in the timing information that
7447// is used by the AAudio timing model. The inaccuracies can cause glitches.
7448static int64_t in_get_mmap_time_offset() {
7449 const int32_t kDefaultOffsetMicros = 0;
7450 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007451 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007452 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7453 return mmap_time_offset_micros * (int64_t)1000;
7454}
7455
Haynes Mathew George16081042017-05-31 17:16:49 -07007456static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7457 int32_t min_size_frames,
7458 struct audio_mmap_buffer_info *info)
7459{
7460 struct stream_in *in = (struct stream_in *)stream;
7461 struct audio_device *adev = in->dev;
7462 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007463 unsigned int offset1 = 0;
7464 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007465 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007466 uint32_t mmap_size = 0;
7467 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007468
7469 pthread_mutex_lock(&adev->lock);
7470 ALOGV("%s in %p", __func__, in);
7471
Sharad Sanglec6f32552018-05-04 16:15:38 +05307472 if (CARD_STATUS_OFFLINE == in->card_status||
7473 CARD_STATUS_OFFLINE == adev->card_status) {
7474 ALOGW("in->card_status or adev->card_status offline, try again");
7475 ret = -EIO;
7476 goto exit;
7477 }
7478
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307479 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007480 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7481 ret = -EINVAL;
7482 goto exit;
7483 }
7484 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7485 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7486 ALOGV("%s in %p", __func__, in);
7487 ret = -ENOSYS;
7488 goto exit;
7489 }
7490 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7491 if (in->pcm_device_id < 0) {
7492 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7493 __func__, in->pcm_device_id, in->usecase);
7494 ret = -EINVAL;
7495 goto exit;
7496 }
7497
7498 adjust_mmap_period_count(&in->config, min_size_frames);
7499
7500 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7501 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7502 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7503 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307504 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307505 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7506 in->card_status = CARD_STATUS_OFFLINE;
7507 adev->card_status = CARD_STATUS_OFFLINE;
7508 ret = -EIO;
7509 goto exit;
7510 }
7511
Haynes Mathew George16081042017-05-31 17:16:49 -07007512 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7513 step = "open";
7514 ret = -ENODEV;
7515 goto exit;
7516 }
7517
7518 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7519 if (ret < 0) {
7520 step = "begin";
7521 goto exit;
7522 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007523
juyuchen626833d2019-06-04 16:48:02 +08007524 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007525 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7526 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7527 info->burst_size_frames = in->config.period_size;
7528 ret = platform_get_mmap_data_fd(adev->platform,
7529 in->pcm_device_id, 1 /*capture*/,
7530 &info->shared_memory_fd,
7531 &mmap_size);
7532 if (ret < 0) {
7533 // Fall back to non exclusive mode
7534 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7535 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007536 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7537 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7538
Arun Mirpuri5d170872019-03-26 13:21:31 -07007539 if (mmap_size < buffer_size) {
7540 step = "mmap";
7541 goto exit;
7542 }
juyuchen626833d2019-06-04 16:48:02 +08007543 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007544 }
7545
7546 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007547
7548 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7549 if (ret < 0) {
7550 step = "commit";
7551 goto exit;
7552 }
7553
Phil Burke0a86d12019-02-16 22:28:11 -08007554 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7555
Haynes Mathew George16081042017-05-31 17:16:49 -07007556 in->standby = false;
7557 ret = 0;
7558
7559 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7560 __func__, info->shared_memory_address, info->buffer_size_frames);
7561
7562exit:
7563 if (ret != 0) {
7564 if (in->pcm == NULL) {
7565 ALOGE("%s: %s - %d", __func__, step, ret);
7566 } else {
7567 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7568 pcm_close(in->pcm);
7569 in->pcm = NULL;
7570 }
7571 }
7572 pthread_mutex_unlock(&adev->lock);
7573 return ret;
7574}
7575
7576static int in_get_mmap_position(const struct audio_stream_in *stream,
7577 struct audio_mmap_position *position)
7578{
7579 struct stream_in *in = (struct stream_in *)stream;
7580 ALOGVV("%s", __func__);
7581 if (position == NULL) {
7582 return -EINVAL;
7583 }
7584 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7585 return -ENOSYS;
7586 }
7587 if (in->pcm == NULL) {
7588 return -ENOSYS;
7589 }
7590 struct timespec ts = { 0, 0 };
7591 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7592 if (ret < 0) {
7593 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7594 return ret;
7595 }
Phil Burke0a86d12019-02-16 22:28:11 -08007596 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7597 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007598 return 0;
7599}
7600
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307601static int in_get_active_microphones(const struct audio_stream_in *stream,
7602 struct audio_microphone_characteristic_t *mic_array,
7603 size_t *mic_count) {
7604 struct stream_in *in = (struct stream_in *)stream;
7605 struct audio_device *adev = in->dev;
7606 ALOGVV("%s", __func__);
7607
7608 lock_input_stream(in);
7609 pthread_mutex_lock(&adev->lock);
7610 int ret = platform_get_active_microphones(adev->platform,
7611 audio_channel_count_from_in_mask(in->channel_mask),
7612 in->usecase, mic_array, mic_count);
7613 pthread_mutex_unlock(&adev->lock);
7614 pthread_mutex_unlock(&in->lock);
7615
7616 return ret;
7617}
7618
7619static int adev_get_microphones(const struct audio_hw_device *dev,
7620 struct audio_microphone_characteristic_t *mic_array,
7621 size_t *mic_count) {
7622 struct audio_device *adev = (struct audio_device *)dev;
7623 ALOGVV("%s", __func__);
7624
7625 pthread_mutex_lock(&adev->lock);
7626 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7627 pthread_mutex_unlock(&adev->lock);
7628
7629 return ret;
7630}
juyuchendb308c22019-01-21 11:57:17 -07007631
7632static void in_update_sink_metadata(struct audio_stream_in *stream,
7633 const struct sink_metadata *sink_metadata) {
7634
7635 if (stream == NULL
7636 || sink_metadata == NULL
7637 || sink_metadata->tracks == NULL) {
7638 return;
7639 }
7640
7641 int error = 0;
7642 struct stream_in *in = (struct stream_in *)stream;
7643 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007644 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007645 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007646
7647 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007648
7649 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007650 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007651
7652 lock_input_stream(in);
7653 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007654 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007655
Zhou Song62ea0282020-03-22 19:53:01 +08007656 is_ha_usecase = adev->ha_proxy_enable ?
7657 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7658 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7659 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007660 && adev->voice_tx_output != NULL) {
7661 /* Use the rx device from afe-proxy record to route voice call because
7662 there is no routing if tx device is on primary hal and rx device
7663 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007664 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007665
7666 if (!voice_is_call_state_active(adev)) {
7667 if (adev->mode == AUDIO_MODE_IN_CALL) {
7668 adev->current_call_output = adev->voice_tx_output;
7669 error = voice_start_call(adev);
7670 if (error != 0)
7671 ALOGE("%s: start voice call failed %d", __func__, error);
7672 }
7673 } else {
7674 adev->current_call_output = adev->voice_tx_output;
7675 voice_update_devices_for_all_voice_usecases(adev);
7676 }
7677 }
7678
7679 pthread_mutex_unlock(&adev->lock);
7680 pthread_mutex_unlock(&in->lock);
7681}
7682
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307683int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007684 audio_io_handle_t handle,
7685 audio_devices_t devices,
7686 audio_output_flags_t flags,
7687 struct audio_config *config,
7688 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007689 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007690{
7691 struct audio_device *adev = (struct audio_device *)dev;
7692 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307693 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007694 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007695 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307696 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007697 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7698 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7699 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7700 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007701 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007702 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7703 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007704 bool force_haptic_path =
7705 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007706 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007707#ifdef AUDIO_GKI_ENABLED
7708 __s32 *generic_dec;
7709#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007710
kunleizdff872d2018-08-20 14:40:33 +08007711 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007712 is_usb_dev = false;
7713 devices = AUDIO_DEVICE_OUT_SPEAKER;
7714 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7715 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007716 if (config->format == AUDIO_FORMAT_DEFAULT)
7717 config->format = AUDIO_FORMAT_PCM_16_BIT;
7718 if (config->sample_rate == 0)
7719 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7720 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7721 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007722 }
7723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007724 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307725
Rahul Sharma99770982019-03-06 17:05:26 +05307726 pthread_mutex_lock(&adev->lock);
7727 if (out_get_stream(adev, handle) != NULL) {
7728 ALOGW("%s, output stream already opened", __func__);
7729 ret = -EEXIST;
7730 }
7731 pthread_mutex_unlock(&adev->lock);
7732 if (ret)
7733 return ret;
7734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007735 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7736
Mingming Yin3a941d42016-02-17 18:08:05 -08007737 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007738 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7739 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307740
7741
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007742 if (!out) {
7743 return -ENOMEM;
7744 }
7745
Haynes Mathew George204045b2015-02-25 20:32:03 -08007746 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007747 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007748 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007749 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007750 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007752 if (devices == AUDIO_DEVICE_NONE)
7753 devices = AUDIO_DEVICE_OUT_SPEAKER;
7754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007755 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007756 list_init(&out->device_list);
7757 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007758 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007759 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007760 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307761 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307762 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7763 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7764 else
7765 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007766 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007767 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007768 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307769 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307770 out->started = 0;
Zhou Song1f93fa52020-11-20 13:57:39 +08007771 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007772 out->hal_output_suspend_supported = 0;
7773 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307774 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307775 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307776 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007777 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007778
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307779 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307780 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007781 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7782
Aalique Grahame22e49102018-12-18 14:23:57 -08007783 if (direct_dev &&
7784 (audio_is_linear_pcm(out->format) ||
7785 config->format == AUDIO_FORMAT_DEFAULT) &&
7786 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7787 audio_format_t req_format = config->format;
7788 audio_channel_mask_t req_channel_mask = config->channel_mask;
7789 uint32_t req_sample_rate = config->sample_rate;
7790
7791 pthread_mutex_lock(&adev->lock);
7792 if (is_hdmi) {
7793 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7794 ret = read_hdmi_sink_caps(out);
7795 if (config->sample_rate == 0)
7796 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7797 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7798 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7799 if (config->format == AUDIO_FORMAT_DEFAULT)
7800 config->format = AUDIO_FORMAT_PCM_16_BIT;
7801 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007802 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7803 &config->format,
7804 &out->supported_formats[0],
7805 MAX_SUPPORTED_FORMATS,
7806 &config->channel_mask,
7807 &out->supported_channel_masks[0],
7808 MAX_SUPPORTED_CHANNEL_MASKS,
7809 &config->sample_rate,
7810 &out->supported_sample_rates[0],
7811 MAX_SUPPORTED_SAMPLE_RATES);
7812 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007813 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007814
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007815 pthread_mutex_unlock(&adev->lock);
7816 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007817 if (ret == -ENOSYS) {
7818 /* ignore and go with default */
7819 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007820 }
7821 // For MMAP NO IRQ, allow conversions in ADSP
7822 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7823 goto error_open;
7824 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007825 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007826 goto error_open;
7827 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007828
7829 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7830 config->sample_rate = req_sample_rate;
7831 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7832 config->channel_mask = req_channel_mask;
7833 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7834 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007835 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007836
7837 out->sample_rate = config->sample_rate;
7838 out->channel_mask = config->channel_mask;
7839 out->format = config->format;
7840 if (is_hdmi) {
7841 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7842 out->config = pcm_config_hdmi_multi;
7843 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7844 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7845 out->config = pcm_config_mmap_playback;
7846 out->stream.start = out_start;
7847 out->stream.stop = out_stop;
7848 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7849 out->stream.get_mmap_position = out_get_mmap_position;
7850 } else {
7851 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7852 out->config = pcm_config_hifi;
7853 }
7854
7855 out->config.rate = out->sample_rate;
7856 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7857 if (is_hdmi) {
7858 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7859 audio_bytes_per_sample(out->format));
7860 }
7861 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007862 }
7863
Derek Chenf6318be2017-06-12 17:16:24 -04007864 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007865 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007866 /* extract car audio stream index */
7867 out->car_audio_stream =
7868 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7869 if (out->car_audio_stream < 0) {
7870 ALOGE("%s: invalid car audio stream %x",
7871 __func__, out->car_audio_stream);
7872 ret = -EINVAL;
7873 goto error_open;
7874 }
Derek Chen5f67a942020-02-24 23:08:13 -08007875 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007876 }
7877
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007878 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007879 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007880 if (!voice_extn_is_compress_voip_supported()) {
7881 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7882 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007883 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307884 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007885 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7886 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007887 out->volume_l = INVALID_OUT_VOLUME;
7888 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007889
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007890 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007891 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007892 uint32_t channel_count =
7893 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307894 out->config.channels = channel_count;
7895
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007896 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7897 out->sample_rate, out->format,
7898 channel_count, false);
7899 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7900 if (frame_size != 0)
7901 out->config.period_size = buffer_size / frame_size;
7902 else
7903 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007904 }
7905 } else {
7906 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7907 voice_extn_compress_voip_is_active(out->dev)) &&
7908 (voice_extn_compress_voip_is_config_supported(config))) {
7909 ret = voice_extn_compress_voip_open_output_stream(out);
7910 if (ret != 0) {
7911 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7912 __func__, ret);
7913 goto error_open;
7914 }
Sujin Panicker19027262019-09-16 18:28:06 +05307915 } else {
7916 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7917 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007918 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007919 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007920 } else if (audio_is_linear_pcm(out->format) &&
7921 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7922 out->channel_mask = config->channel_mask;
7923 out->sample_rate = config->sample_rate;
7924 out->format = config->format;
7925 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7926 // does this change?
7927 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7928 out->config.rate = config->sample_rate;
7929 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7930 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7931 audio_bytes_per_sample(config->format));
7932 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007933 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307934 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307935 pthread_mutex_lock(&adev->lock);
7936 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7937 pthread_mutex_unlock(&adev->lock);
7938
7939 // reject offload during card offline to allow
7940 // fallback to s/w paths
7941 if (offline) {
7942 ret = -ENODEV;
7943 goto error_open;
7944 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007945
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007946 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7947 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7948 ALOGE("%s: Unsupported Offload information", __func__);
7949 ret = -EINVAL;
7950 goto error_open;
7951 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007952
Atul Khare3fa6e542017-08-09 00:56:17 +05307953 if (config->offload_info.format == 0)
7954 config->offload_info.format = config->format;
7955 if (config->offload_info.sample_rate == 0)
7956 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007957
Mingming Yin90310102013-11-13 16:57:00 -08007958 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307959 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007960 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007961 ret = -EINVAL;
7962 goto error_open;
7963 }
7964
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007965 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7966 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7967 (audio_extn_passthru_is_passthrough_stream(out)) &&
7968 !((config->sample_rate == 48000) ||
7969 (config->sample_rate == 96000) ||
7970 (config->sample_rate == 192000))) {
7971 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7972 __func__, config->sample_rate, config->offload_info.format);
7973 ret = -EINVAL;
7974 goto error_open;
7975 }
7976
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007977 out->compr_config.codec = (struct snd_codec *)
7978 calloc(1, sizeof(struct snd_codec));
7979
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007980 if (!out->compr_config.codec) {
7981 ret = -ENOMEM;
7982 goto error_open;
7983 }
7984
Dhananjay Kumarac341582017-02-23 23:42:25 +05307985 out->stream.pause = out_pause;
7986 out->stream.resume = out_resume;
7987 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307988 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307989 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007990 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307991 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007992 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307993 } else {
7994 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7995 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007996 }
vivek mehta446c3962015-09-14 10:57:35 -07007997
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307998 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7999 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008000#ifdef AUDIO_GKI_ENABLED
8001 /* out->compr_config.codec->reserved[1] is for flags */
8002 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8003#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308004 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008005#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308006 }
8007
vivek mehta446c3962015-09-14 10:57:35 -07008008 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008009 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008010 config->format == 0 && config->sample_rate == 0 &&
8011 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008012 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008013 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8014 } else {
8015 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8016 ret = -EEXIST;
8017 goto error_open;
8018 }
vivek mehta446c3962015-09-14 10:57:35 -07008019 }
8020
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008021 if (config->offload_info.channel_mask)
8022 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008023 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008024 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008025 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008026 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308027 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008028 ret = -EINVAL;
8029 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008030 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008031
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008032 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008033 out->sample_rate = config->offload_info.sample_rate;
8034
Mingming Yin3ee55c62014-08-04 14:23:35 -07008035 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008036
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308037 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308038 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308039 audio_extn_dolby_send_ddp_endp_params(adev);
8040 audio_extn_dolby_set_dmid(adev);
8041 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008042
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008043 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008044 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008045 out->compr_config.codec->bit_rate =
8046 config->offload_info.bit_rate;
8047 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308048 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008049 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308050 /* Update bit width only for non passthrough usecases.
8051 * For passthrough usecases, the output will always be opened @16 bit
8052 */
8053 if (!audio_extn_passthru_is_passthrough_stream(out))
8054 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308055
8056 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008057#ifdef AUDIO_GKI_ENABLED
8058 /* out->compr_config.codec->reserved[1] is for flags */
8059 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8060 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8061#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308062 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8063 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008064#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308065
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008066 /*TODO: Do we need to change it for passthrough */
8067 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008068
Manish Dewangana6fc5442015-08-24 20:30:31 +05308069 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8070 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308071 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308073 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8074 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308075
8076 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8077 AUDIO_FORMAT_PCM) {
8078
8079 /*Based on platform support, configure appropriate alsa format for corresponding
8080 *hal input format.
8081 */
8082 out->compr_config.codec->format = hal_format_to_alsa(
8083 config->offload_info.format);
8084
Ashish Jain83a6cc22016-06-28 14:34:17 +05308085 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308086 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308087 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308088
Dhananjay Kumarac341582017-02-23 23:42:25 +05308089 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308090 *hal input format and alsa format might differ based on platform support.
8091 */
8092 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308093 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308094
8095 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8096
Deeraj Soman93155a62019-09-30 19:00:37 +05308097 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8098 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8099 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8100 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8101 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308102
Ashish Jainf1eaa582016-05-23 20:54:24 +05308103 /* Check if alsa session is configured with the same format as HAL input format,
8104 * if not then derive correct fragment size needed to accomodate the
8105 * conversion of HAL input format to alsa format.
8106 */
8107 audio_extn_utils_update_direct_pcm_fragment_size(out);
8108
8109 /*if hal input and output fragment size is different this indicates HAL input format is
8110 *not same as the alsa format
8111 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308112 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308113 /*Allocate a buffer to convert input data to the alsa configured format.
8114 *size of convert buffer is equal to the size required to hold one fragment size
8115 *worth of pcm data, this is because flinger does not write more than fragment_size
8116 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308117 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8118 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308119 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8120 ret = -ENOMEM;
8121 goto error_open;
8122 }
8123 }
8124 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8125 out->compr_config.fragment_size =
8126 audio_extn_passthru_get_buffer_size(&config->offload_info);
8127 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8128 } else {
8129 out->compr_config.fragment_size =
8130 platform_get_compress_offload_buffer_size(&config->offload_info);
8131 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8132 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008133
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308134 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8135 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8136 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008137 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8138#ifdef AUDIO_GKI_ENABLED
8139 generic_dec =
8140 &(out->compr_config.codec->options.generic.reserved[1]);
8141 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8142 AUDIO_OUTPUT_BIT_WIDTH;
8143#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308144 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008145#endif
8146 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008147
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308148 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8149 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8150 }
8151
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008152 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8153 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008154
Manish Dewangan69426c82017-01-30 17:35:36 +05308155 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8156 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8157 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8158 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8159 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8160 } else {
8161 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8162 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008163
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308164 memset(&out->channel_map_param, 0,
8165 sizeof(struct audio_out_channel_map_param));
8166
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008167 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308168 out->send_next_track_params = false;
8169 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008170 out->offload_state = OFFLOAD_STATE_IDLE;
8171 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008172 out->writeAt.tv_sec = 0;
8173 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008174
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008175 audio_extn_dts_create_state_notifier_node(out->usecase);
8176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008177 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8178 __func__, config->offload_info.version,
8179 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308180
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308181 /* Check if DSD audio format is supported in codec
8182 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308183 */
8184
8185 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308186 (!platform_check_codec_dsd_support(adev->platform) ||
8187 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308188 ret = -EINVAL;
8189 goto error_open;
8190 }
8191
Ashish Jain5106d362016-05-11 19:23:33 +05308192 /* Disable gapless if any of the following is true
8193 * passthrough playback
8194 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308195 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308196 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308197 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308198 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008199 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308200 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308201 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308202 check_and_set_gapless_mode(adev, false);
8203 } else
8204 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008205
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308206 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008207 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8208 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308209 if (config->format == AUDIO_FORMAT_DSD) {
8210 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008211#ifdef AUDIO_GKI_ENABLED
8212 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8213 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8214#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308215 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008216#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308217 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008218
8219 create_offload_callback_thread(out);
8220
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008221 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008222 switch (config->sample_rate) {
8223 case 0:
8224 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8225 break;
8226 case 8000:
8227 case 16000:
8228 case 48000:
8229 out->sample_rate = config->sample_rate;
8230 break;
8231 default:
8232 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8233 config->sample_rate);
8234 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8235 ret = -EINVAL;
8236 goto error_open;
8237 }
8238 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8239 switch (config->channel_mask) {
8240 case AUDIO_CHANNEL_NONE:
8241 case AUDIO_CHANNEL_OUT_STEREO:
8242 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8243 break;
8244 default:
8245 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8246 config->channel_mask);
8247 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8248 ret = -EINVAL;
8249 goto error_open;
8250 }
8251 switch (config->format) {
8252 case AUDIO_FORMAT_DEFAULT:
8253 case AUDIO_FORMAT_PCM_16_BIT:
8254 out->format = AUDIO_FORMAT_PCM_16_BIT;
8255 break;
8256 default:
8257 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8258 config->format);
8259 config->format = AUDIO_FORMAT_PCM_16_BIT;
8260 ret = -EINVAL;
8261 goto error_open;
8262 }
8263
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308264 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008265 if (ret != 0) {
8266 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008267 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008268 goto error_open;
8269 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008270 } else if (is_single_device_type_equal(&out->device_list,
8271 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008272 switch (config->sample_rate) {
8273 case 0:
8274 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8275 break;
8276 case 8000:
8277 case 16000:
8278 case 48000:
8279 out->sample_rate = config->sample_rate;
8280 break;
8281 default:
8282 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8283 config->sample_rate);
8284 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8285 ret = -EINVAL;
8286 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008287 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008288 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8289 switch (config->channel_mask) {
8290 case AUDIO_CHANNEL_NONE:
8291 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8292 break;
8293 case AUDIO_CHANNEL_OUT_STEREO:
8294 out->channel_mask = config->channel_mask;
8295 break;
8296 default:
8297 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8298 config->channel_mask);
8299 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8300 ret = -EINVAL;
8301 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008302 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008303 switch (config->format) {
8304 case AUDIO_FORMAT_DEFAULT:
8305 out->format = AUDIO_FORMAT_PCM_16_BIT;
8306 break;
8307 case AUDIO_FORMAT_PCM_16_BIT:
8308 out->format = config->format;
8309 break;
8310 default:
8311 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8312 config->format);
8313 config->format = AUDIO_FORMAT_PCM_16_BIT;
8314 ret = -EINVAL;
8315 break;
8316 }
8317 if (ret != 0)
8318 goto error_open;
8319
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008320 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8321 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008322 out->config.rate = out->sample_rate;
8323 out->config.channels =
8324 audio_channel_count_from_out_mask(out->channel_mask);
8325 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008326 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008327 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308328 unsigned int channels = 0;
8329 /*Update config params to default if not set by the caller*/
8330 if (config->sample_rate == 0)
8331 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8332 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8333 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8334 if (config->format == AUDIO_FORMAT_DEFAULT)
8335 config->format = AUDIO_FORMAT_PCM_16_BIT;
8336
8337 channels = audio_channel_count_from_out_mask(out->channel_mask);
8338
Varun Balaraje49253e2017-07-06 19:48:56 +05308339 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8340 out->usecase = get_interactive_usecase(adev);
8341 out->config = pcm_config_low_latency;
8342 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308343 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008344 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8345 out->flags);
8346 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008347 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8348 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8349 out->config = pcm_config_mmap_playback;
8350 out->stream.start = out_start;
8351 out->stream.stop = out_stop;
8352 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8353 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308354 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8355 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008356 out->hal_output_suspend_supported =
8357 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8358 out->dynamic_pm_qos_config_supported =
8359 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8360 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008361 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8362 } else {
8363 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8364 //the mixer path will be a string similar to "low-latency-playback resume"
8365 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8366 strlcat(out->pm_qos_mixer_path,
8367 " resume", MAX_MIXER_PATH_LEN);
8368 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8369 out->pm_qos_mixer_path);
8370 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308371 out->config = pcm_config_low_latency;
8372 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8373 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8374 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308375 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8376 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8377 if (out->config.period_size <= 0) {
8378 ALOGE("Invalid configuration period size is not valid");
8379 ret = -EINVAL;
8380 goto error_open;
8381 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008382 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8383 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8384 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008385 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8386 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8387 out->config = pcm_config_haptics_audio;
8388 if (force_haptic_path)
8389 adev->haptics_config = pcm_config_haptics_audio;
8390 else
8391 adev->haptics_config = pcm_config_haptics;
8392
Meng Wangd08ce322020-04-02 08:59:20 +08008393 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008394 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8395
8396 if (force_haptic_path) {
8397 out->config.channels = 1;
8398 adev->haptics_config.channels = 1;
8399 } else
8400 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 -08008401 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008402 ret = audio_extn_auto_hal_open_output_stream(out);
8403 if (ret) {
8404 ALOGE("%s: Failed to open output stream for bus device", __func__);
8405 ret = -EINVAL;
8406 goto error_open;
8407 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308408 } else {
8409 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008410 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8411 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308412 }
8413 out->hal_ip_format = format = out->format;
8414 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8415 out->hal_op_format = pcm_format_to_hal(out->config.format);
8416 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8417 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008418 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308419 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308420 if (out->hal_ip_format != out->hal_op_format) {
8421 uint32_t buffer_size = out->config.period_size *
8422 format_to_bitwidth_table[out->hal_op_format] *
8423 out->config.channels;
8424 out->convert_buffer = calloc(1, buffer_size);
8425 if (out->convert_buffer == NULL){
8426 ALOGE("Allocation failed for convert buffer for size %d",
8427 out->compr_config.fragment_size);
8428 ret = -ENOMEM;
8429 goto error_open;
8430 }
8431 ALOGD("Convert buffer allocated of size %d", buffer_size);
8432 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008433 }
8434
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008435 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8436 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308437
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008438 /* TODO remove this hardcoding and check why width is zero*/
8439 if (out->bit_width == 0)
8440 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308441 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008442 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008443 &out->device_list, out->flags,
8444 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308445 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308446 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008447 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008448 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8449 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008450 if(adev->primary_output == NULL)
8451 adev->primary_output = out;
8452 else {
8453 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008454 ret = -EEXIST;
8455 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008456 }
8457 }
8458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008459 /* Check if this usecase is already existing */
8460 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008461 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8462 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008463 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008465 ret = -EEXIST;
8466 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008469 pthread_mutex_unlock(&adev->lock);
8470
8471 out->stream.common.get_sample_rate = out_get_sample_rate;
8472 out->stream.common.set_sample_rate = out_set_sample_rate;
8473 out->stream.common.get_buffer_size = out_get_buffer_size;
8474 out->stream.common.get_channels = out_get_channels;
8475 out->stream.common.get_format = out_get_format;
8476 out->stream.common.set_format = out_set_format;
8477 out->stream.common.standby = out_standby;
8478 out->stream.common.dump = out_dump;
8479 out->stream.common.set_parameters = out_set_parameters;
8480 out->stream.common.get_parameters = out_get_parameters;
8481 out->stream.common.add_audio_effect = out_add_audio_effect;
8482 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8483 out->stream.get_latency = out_get_latency;
8484 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008485#ifdef NO_AUDIO_OUT
8486 out->stream.write = out_write_for_no_output;
8487#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008488 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008489#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008490 out->stream.get_render_position = out_get_render_position;
8491 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008492 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493
Haynes Mathew George16081042017-05-31 17:16:49 -07008494 if (out->realtime)
8495 out->af_period_multiplier = af_period_multiplier;
8496 else
8497 out->af_period_multiplier = 1;
8498
Andy Hunga1f48fa2019-07-01 18:14:53 -07008499 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008501 out->standby = 1;
Zhou Song1f93fa52020-11-20 13:57:39 +08008502 out->volume_l = PLAYBACK_GAIN_MAX;
8503 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008504 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008505 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506
8507 config->format = out->stream.common.get_format(&out->stream.common);
8508 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8509 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308510 register_format(out->format, out->supported_formats);
8511 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8512 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008513
Aalique Grahame22e49102018-12-18 14:23:57 -08008514 out->error_log = error_log_create(
8515 ERROR_LOG_ENTRIES,
8516 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8517
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308518 /*
8519 By locking output stream before registering, we allow the callback
8520 to update stream's state only after stream's initial state is set to
8521 adev state.
8522 */
8523 lock_output_stream(out);
8524 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8525 pthread_mutex_lock(&adev->lock);
8526 out->card_status = adev->card_status;
8527 pthread_mutex_unlock(&adev->lock);
8528 pthread_mutex_unlock(&out->lock);
8529
Aalique Grahame22e49102018-12-18 14:23:57 -08008530 stream_app_type_cfg_init(&out->app_type_cfg);
8531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008532 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308533 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008534 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008535
8536 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8537 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8538 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008539 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308540 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008541 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008542 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308543 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8544 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008545 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8546 out->usecase, PCM_PLAYBACK);
8547 hdlr_stream_cfg.flags = out->flags;
8548 hdlr_stream_cfg.type = PCM_PLAYBACK;
8549 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8550 &hdlr_stream_cfg);
8551 if (ret) {
8552 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8553 out->adsp_hdlr_stream_handle = NULL;
8554 }
8555 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308556 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8557 is_direct_passthough, false);
8558 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8559 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008560 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008561 if (ret < 0) {
8562 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8563 out->ip_hdlr_handle = NULL;
8564 }
8565 }
Derek Chenf939fb72018-11-13 13:34:41 -08008566
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008567 ret = io_streams_map_insert(adev, &out->stream.common,
8568 out->handle, AUDIO_PATCH_HANDLE_NONE);
8569 if (ret != 0)
8570 goto error_open;
8571
Derek Chenf939fb72018-11-13 13:34:41 -08008572 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8573 calloc(1, sizeof(streams_output_ctxt_t));
8574 if (out_ctxt == NULL) {
8575 ALOGE("%s fail to allocate output ctxt", __func__);
8576 ret = -ENOMEM;
8577 goto error_open;
8578 }
8579 out_ctxt->output = out;
8580
8581 pthread_mutex_lock(&adev->lock);
8582 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8583 pthread_mutex_unlock(&adev->lock);
8584
Eric Laurent994a6932013-07-17 11:51:42 -07008585 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008586 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008587
8588error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308589 if (out->convert_buffer)
8590 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008591 free(out);
8592 *stream_out = NULL;
8593 ALOGD("%s: exit: ret %d", __func__, ret);
8594 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008595}
8596
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308597void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008598 struct audio_stream_out *stream)
8599{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008600 struct stream_out *out = (struct stream_out *)stream;
8601 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008602 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008603
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008604 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308605
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008606 io_streams_map_remove(adev, out->handle);
8607
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308608 // must deregister from sndmonitor first to prevent races
8609 // between the callback and close_stream
8610 audio_extn_snd_mon_unregister_listener(out);
8611
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008612 /* close adsp hdrl session before standby */
8613 if (out->adsp_hdlr_stream_handle) {
8614 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8615 if (ret)
8616 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8617 out->adsp_hdlr_stream_handle = NULL;
8618 }
8619
Manish Dewangan21a850a2017-08-14 12:03:55 +05308620 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008621 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8622 out->ip_hdlr_handle = NULL;
8623 }
8624
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008625 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308626 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008627 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308628 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308629 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008630 if(ret != 0)
8631 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8632 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008633 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008634 out_standby(&stream->common);
8635
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008636 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008637 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008638 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008639 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008640 if (out->compr_config.codec != NULL)
8641 free(out->compr_config.codec);
8642 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008643
Zhou Song1f93fa52020-11-20 13:57:39 +08008644 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308645
Varun Balaraje49253e2017-07-06 19:48:56 +05308646 if (is_interactive_usecase(out->usecase))
8647 free_interactive_usecase(adev, out->usecase);
8648
Ashish Jain83a6cc22016-06-28 14:34:17 +05308649 if (out->convert_buffer != NULL) {
8650 free(out->convert_buffer);
8651 out->convert_buffer = NULL;
8652 }
8653
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008654 if (adev->voice_tx_output == out)
8655 adev->voice_tx_output = NULL;
8656
Aalique Grahame22e49102018-12-18 14:23:57 -08008657 error_log_destroy(out->error_log);
8658 out->error_log = NULL;
8659
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308660 if (adev->primary_output == out)
8661 adev->primary_output = NULL;
8662
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008663 pthread_cond_destroy(&out->cond);
8664 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008665 pthread_mutex_destroy(&out->pre_lock);
8666 pthread_mutex_destroy(&out->latch_lock);
8667 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008668
8669 pthread_mutex_lock(&adev->lock);
8670 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8671 if (out_ctxt != NULL) {
8672 list_remove(&out_ctxt->list);
8673 free(out_ctxt);
8674 } else {
8675 ALOGW("%s, output stream already closed", __func__);
8676 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008677 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008678 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008679 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008680}
8681
8682static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8683{
8684 struct audio_device *adev = (struct audio_device *)dev;
8685 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008686 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008687 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008688 int ret;
8689 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008690 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008691 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008692 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008693
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008694 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008695 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008696
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308697 if (!parms)
8698 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308699
Derek Chen6f293672019-04-01 01:40:24 -07008700 /* notify adev and input/output streams on the snd card status */
8701 adev_snd_mon_cb((void *)adev, parms);
8702
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008703 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8704 if (ret >= 0) {
8705 list_for_each(node, &adev->active_outputs_list) {
8706 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8707 streams_output_ctxt_t,
8708 list);
8709 out_snd_mon_cb((void *)out_ctxt->output, parms);
8710 }
Derek Chen6f293672019-04-01 01:40:24 -07008711
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008712 list_for_each(node, &adev->active_inputs_list) {
8713 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8714 streams_input_ctxt_t,
8715 list);
8716 in_snd_mon_cb((void *)in_ctxt->input, parms);
8717 }
Derek Chen6f293672019-04-01 01:40:24 -07008718 }
8719
Zhou Songd6d71752019-05-21 18:08:51 +08008720 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308721 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8722 if (ret >= 0) {
8723 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008724 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308725 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008726 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308727 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008728 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008729 }
8730 }
8731
8732 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008733 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008734 if (!strncmp(value, "false", 5) &&
8735 audio_extn_a2dp_source_is_suspended()) {
8736 struct audio_usecase *usecase;
8737 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008738 list_for_each(node, &adev->usecase_list) {
8739 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008740 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008741 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008742 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008743 reassign_device_list(&usecase->stream.in->device_list,
8744 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008745 select_devices(adev, usecase->id);
8746 }
Zhou Songd6d71752019-05-21 18:08:51 +08008747 }
8748 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308749 }
8750
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008751 status = voice_set_parameters(adev, parms);
8752 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008753 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008755 status = platform_set_parameters(adev->platform, parms);
8756 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008757 goto done;
8758
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008759 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8760 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008761 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8763 adev->bluetooth_nrec = true;
8764 else
8765 adev->bluetooth_nrec = false;
8766 }
8767
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008768 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8769 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008770 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8771 adev->screen_off = false;
8772 else
8773 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008774 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008775 }
8776
Eric Laurent4b084132018-10-19 17:33:43 -07008777 ret = str_parms_get_int(parms, "rotation", &val);
8778 if (ret >= 0) {
8779 bool reverse_speakers = false;
8780 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8781 switch (val) {
8782 // FIXME: note that the code below assumes that the speakers are in the correct placement
8783 // relative to the user when the device is rotated 90deg from its default rotation. This
8784 // assumption is device-specific, not platform-specific like this code.
8785 case 270:
8786 reverse_speakers = true;
8787 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8788 break;
8789 case 0:
8790 case 180:
8791 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8792 break;
8793 case 90:
8794 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8795 break;
8796 default:
8797 ALOGE("%s: unexpected rotation of %d", __func__, val);
8798 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008799 }
Eric Laurent4b084132018-10-19 17:33:43 -07008800 if (status == 0) {
8801 // check and set swap
8802 // - check if orientation changed and speaker active
8803 // - set rotation and cache the rotation value
8804 adev->camera_orientation =
8805 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8806 if (!audio_extn_is_maxx_audio_enabled())
8807 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8808 }
8809 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008810
Mingming Yin514a8bc2014-07-29 15:22:21 -07008811 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8812 if (ret >= 0) {
8813 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8814 adev->bt_wb_speech_enabled = true;
8815 else
8816 adev->bt_wb_speech_enabled = false;
8817 }
8818
Zhou Song12c29502019-03-16 10:37:18 +08008819 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8820 if (ret >= 0) {
8821 val = atoi(value);
8822 adev->swb_speech_mode = val;
8823 }
8824
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008825 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8826 if (ret >= 0) {
8827 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308828 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008829 if (audio_is_output_device(val) &&
8830 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008831 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008832 platform_get_controller_stream_from_params(parms, &controller, &stream);
8833 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8834 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008835 if (ret < 0) {
8836 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308837 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008838 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008839 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308840 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008841 /*
8842 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8843 * Per AudioPolicyManager, USB device is higher priority than WFD.
8844 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8845 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8846 * starting voice call on USB
8847 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008848 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308849 if (ret >= 0)
8850 audio_extn_usb_add_device(device, atoi(value));
8851
Zhou Song6f862822017-11-06 17:27:57 +08008852 if (!audio_extn_usb_is_tunnel_supported()) {
8853 ALOGV("detected USB connect .. disable proxy");
8854 adev->allow_afe_proxy_usage = false;
8855 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008856 }
8857 }
8858
8859 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8860 if (ret >= 0) {
8861 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308862 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008863 /*
8864 * The HDMI / Displayport disconnect handling has been moved to
8865 * audio extension to ensure that its parameters are not
8866 * invalidated prior to updating sysfs of the disconnect event
8867 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8868 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308869 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008870 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308871 if (ret >= 0)
8872 audio_extn_usb_remove_device(device, atoi(value));
8873
Zhou Song6f862822017-11-06 17:27:57 +08008874 if (!audio_extn_usb_is_tunnel_supported()) {
8875 ALOGV("detected USB disconnect .. enable proxy");
8876 adev->allow_afe_proxy_usage = true;
8877 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008878 }
8879 }
8880
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008881 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008882
8883 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008884 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308885 struct audio_usecase *usecase;
8886 struct listnode *node;
8887 list_for_each(node, &adev->usecase_list) {
8888 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008889 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8890 continue;
8891
8892 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308893 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308894 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308895 ALOGD("Switching to speaker and muting the stream before select_devices");
8896 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308897 //force device switch to re configure encoder
8898 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308899 ALOGD("Unmuting the stream after select_devices");
Zhou Song1f93fa52020-11-20 13:57:39 +08008900 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308901 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308902 break;
Zhou Song9ebf6792020-09-23 22:49:01 +08008903 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008904 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08008905 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008906 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8907 reassign_device_list(&usecase->stream.out->device_list,
8908 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8909 check_a2dp_restore_l(adev, usecase->stream.out, true);
8910 break;
8911 }
8912 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308913 }
8914 }
8915 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008916
8917 //handle vr audio setparam
8918 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8919 value, sizeof(value));
8920 if (ret >= 0) {
8921 ALOGI("Setting vr mode to be %s", value);
8922 if (!strncmp(value, "true", 4)) {
8923 adev->vr_audio_mode_enabled = true;
8924 ALOGI("Setting vr mode to true");
8925 } else if (!strncmp(value, "false", 5)) {
8926 adev->vr_audio_mode_enabled = false;
8927 ALOGI("Setting vr mode to false");
8928 } else {
8929 ALOGI("wrong vr mode set");
8930 }
8931 }
8932
Eric Laurent4b084132018-10-19 17:33:43 -07008933 //FIXME: to be replaced by proper video capture properties API
8934 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8935 if (ret >= 0) {
8936 int camera_facing = CAMERA_FACING_BACK;
8937 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8938 camera_facing = CAMERA_FACING_FRONT;
8939 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8940 camera_facing = CAMERA_FACING_BACK;
8941 else {
8942 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8943 goto done;
8944 }
8945 adev->camera_orientation =
8946 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8947 struct audio_usecase *usecase;
8948 struct listnode *node;
8949 list_for_each(node, &adev->usecase_list) {
8950 usecase = node_to_item(node, struct audio_usecase, list);
8951 struct stream_in *in = usecase->stream.in;
8952 if (usecase->type == PCM_CAPTURE && in != NULL &&
8953 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8954 select_devices(adev, in->usecase);
8955 }
8956 }
8957 }
8958
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308959 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008960done:
8961 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008962 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308963error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008964 ALOGV("%s: exit with code(%d)", __func__, status);
8965 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008966}
8967
8968static char* adev_get_parameters(const struct audio_hw_device *dev,
8969 const char *keys)
8970{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308971 ALOGD("%s:%s", __func__, keys);
8972
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008973 struct audio_device *adev = (struct audio_device *)dev;
8974 struct str_parms *reply = str_parms_create();
8975 struct str_parms *query = str_parms_create_str(keys);
8976 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308977 char value[256] = {0};
8978 int ret = 0;
8979
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008980 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008981 if (reply) {
8982 str_parms_destroy(reply);
8983 }
8984 if (query) {
8985 str_parms_destroy(query);
8986 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008987 ALOGE("adev_get_parameters: failed to create query or reply");
8988 return NULL;
8989 }
8990
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008991 //handle vr audio getparam
8992
8993 ret = str_parms_get_str(query,
8994 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8995 value, sizeof(value));
8996
8997 if (ret >= 0) {
8998 bool vr_audio_enabled = false;
8999 pthread_mutex_lock(&adev->lock);
9000 vr_audio_enabled = adev->vr_audio_mode_enabled;
9001 pthread_mutex_unlock(&adev->lock);
9002
9003 ALOGI("getting vr mode to %d", vr_audio_enabled);
9004
9005 if (vr_audio_enabled) {
9006 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9007 "true");
9008 goto exit;
9009 } else {
9010 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9011 "false");
9012 goto exit;
9013 }
9014 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009015
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009016 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009017 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009018 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009019 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009020 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009021 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309022 pthread_mutex_unlock(&adev->lock);
9023
Naresh Tannirud7205b62014-06-20 02:54:48 +05309024exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009025 str = str_parms_to_str(reply);
9026 str_parms_destroy(query);
9027 str_parms_destroy(reply);
9028
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309029 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009030 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009031}
9032
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009033static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009034{
9035 return 0;
9036}
9037
9038static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9039{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009040 int ret;
9041 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009042
9043 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9044
Haynes Mathew George5191a852013-09-11 14:19:36 -07009045 pthread_mutex_lock(&adev->lock);
9046 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009047 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009048 pthread_mutex_unlock(&adev->lock);
9049 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009050}
9051
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009052static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9053 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009054{
9055 return -ENOSYS;
9056}
9057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009058static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9059 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009060{
9061 return -ENOSYS;
9062}
9063
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009064static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9065 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009066{
9067 return -ENOSYS;
9068}
9069
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009070static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9071 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009072{
9073 return -ENOSYS;
9074}
9075
9076static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9077{
9078 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009079 struct listnode *node;
9080 struct audio_usecase *usecase = NULL;
9081 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009083 pthread_mutex_lock(&adev->lock);
9084 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309085 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9086 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009087 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009088 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309089 adev->current_call_output = adev->primary_output;
9090 voice_start_call(adev);
9091 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009092 (mode == AUDIO_MODE_NORMAL ||
9093 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009094 list_for_each(node, &adev->usecase_list) {
9095 usecase = node_to_item(node, struct audio_usecase, list);
9096 if (usecase->type == VOICE_CALL)
9097 break;
9098 }
9099 if (usecase &&
9100 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9101 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9102 true);
9103 if (ret != 0) {
9104 /* default service interval was successfully updated,
9105 reopen USB backend with new service interval */
9106 check_usecases_codec_backend(adev,
9107 usecase,
9108 usecase->out_snd_device);
9109 }
9110 }
9111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009112 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009113 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009114 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009115 // restore device for other active usecases after stop call
9116 list_for_each(node, &adev->usecase_list) {
9117 usecase = node_to_item(node, struct audio_usecase, list);
9118 select_devices(adev, usecase->id);
9119 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121 }
9122 pthread_mutex_unlock(&adev->lock);
9123 return 0;
9124}
9125
9126static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9127{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009128 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009129 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009130
9131 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009132 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009133 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009134
Derek Chend2530072014-11-24 12:39:14 -08009135 if (adev->ext_hw_plugin)
9136 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009137
9138 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009139 pthread_mutex_unlock(&adev->lock);
9140
9141 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009142}
9143
9144static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9145{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009146 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009147 return 0;
9148}
9149
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009150static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009151 const struct audio_config *config)
9152{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009153 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009154
Aalique Grahame22e49102018-12-18 14:23:57 -08009155 /* Don't know if USB HIFI in this context so use true to be conservative */
9156 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9157 true /*is_usb_hifi */) != 0)
9158 return 0;
9159
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009160 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9161 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009162}
9163
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009164static bool adev_input_allow_hifi_record(struct audio_device *adev,
9165 audio_devices_t devices,
9166 audio_input_flags_t flags,
9167 audio_source_t source) {
9168 const bool allowed = true;
9169
9170 if (!audio_is_usb_in_device(devices))
9171 return !allowed;
9172
9173 switch (flags) {
9174 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009175 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009176 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9177 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009178 default:
9179 return !allowed;
9180 }
9181
9182 switch (source) {
9183 case AUDIO_SOURCE_DEFAULT:
9184 case AUDIO_SOURCE_MIC:
9185 case AUDIO_SOURCE_UNPROCESSED:
9186 break;
9187 default:
9188 return !allowed;
9189 }
9190
9191 switch (adev->mode) {
9192 case 0:
9193 break;
9194 default:
9195 return !allowed;
9196 }
9197
9198 return allowed;
9199}
9200
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009201static int adev_update_voice_comm_input_stream(struct stream_in *in,
9202 struct audio_config *config)
9203{
9204 bool valid_rate = (config->sample_rate == 8000 ||
9205 config->sample_rate == 16000 ||
9206 config->sample_rate == 32000 ||
9207 config->sample_rate == 48000);
9208 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9209
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009210 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009211 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009212 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9213 in->config = default_pcm_config_voip_copp;
9214 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9215 DEFAULT_VOIP_BUF_DURATION_MS,
9216 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009217 } else {
9218 ALOGW("%s No valid input in voip, use defaults"
9219 "sample rate %u, channel mask 0x%X",
9220 __func__, config->sample_rate, in->channel_mask);
9221 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009222 in->config.rate = config->sample_rate;
9223 in->sample_rate = config->sample_rate;
9224 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009225 //XXX needed for voice_extn_compress_voip_open_input_stream
9226 in->config.rate = config->sample_rate;
9227 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309228 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009229 voice_extn_compress_voip_is_active(in->dev)) &&
9230 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9231 valid_rate && valid_ch) {
9232 voice_extn_compress_voip_open_input_stream(in);
9233 // update rate entries to match config from AF
9234 in->config.rate = config->sample_rate;
9235 in->sample_rate = config->sample_rate;
9236 } else {
9237 ALOGW("%s compress voip not active, use defaults", __func__);
9238 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009239 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009240 return 0;
9241}
9242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009243static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009244 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009245 audio_devices_t devices,
9246 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009247 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309248 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009249 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009250 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009251{
9252 struct audio_device *adev = (struct audio_device *)dev;
9253 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009254 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009255 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009256 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309257 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009258 bool is_usb_dev = audio_is_usb_in_device(devices);
9259 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9260 devices,
9261 flags,
9262 source);
Andy Hung94320602018-10-29 18:31:12 -07009263 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9264 " sample_rate %u, channel_mask %#x, format %#x",
9265 __func__, flags, is_usb_dev, may_use_hifi_record,
9266 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309267
kunleizdff872d2018-08-20 14:40:33 +08009268 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009269 is_usb_dev = false;
9270 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9271 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9272 __func__, devices);
9273 }
9274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009275 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009276
9277 if (!(is_usb_dev && may_use_hifi_record)) {
9278 if (config->sample_rate == 0)
9279 config->sample_rate = 48000;
9280 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9281 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9282 if (config->format == AUDIO_FORMAT_DEFAULT)
9283 config->format = AUDIO_FORMAT_PCM_16_BIT;
9284
9285 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9286
Aalique Grahame22e49102018-12-18 14:23:57 -08009287 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9288 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009289 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009291
Rahul Sharma99770982019-03-06 17:05:26 +05309292 pthread_mutex_lock(&adev->lock);
9293 if (in_get_stream(adev, handle) != NULL) {
9294 ALOGW("%s, input stream already opened", __func__);
9295 ret = -EEXIST;
9296 }
9297 pthread_mutex_unlock(&adev->lock);
9298 if (ret)
9299 return ret;
9300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009301 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009302
9303 if (!in) {
9304 ALOGE("failed to allocate input stream");
9305 return -ENOMEM;
9306 }
9307
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309308 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309309 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9310 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009311 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009312 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009314 in->stream.common.get_sample_rate = in_get_sample_rate;
9315 in->stream.common.set_sample_rate = in_set_sample_rate;
9316 in->stream.common.get_buffer_size = in_get_buffer_size;
9317 in->stream.common.get_channels = in_get_channels;
9318 in->stream.common.get_format = in_get_format;
9319 in->stream.common.set_format = in_set_format;
9320 in->stream.common.standby = in_standby;
9321 in->stream.common.dump = in_dump;
9322 in->stream.common.set_parameters = in_set_parameters;
9323 in->stream.common.get_parameters = in_get_parameters;
9324 in->stream.common.add_audio_effect = in_add_audio_effect;
9325 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9326 in->stream.set_gain = in_set_gain;
9327 in->stream.read = in_read;
9328 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009329 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309330 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009331 in->stream.set_microphone_direction = in_set_microphone_direction;
9332 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009333 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009334
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009335 list_init(&in->device_list);
9336 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009337 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009338 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009339 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009340 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009341 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009342 in->bit_width = 16;
9343 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009344 in->direction = MIC_DIRECTION_UNSPECIFIED;
9345 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009346 list_init(&in->aec_list);
9347 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009348 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009349
Andy Hung94320602018-10-29 18:31:12 -07009350 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009351 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9352 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9353 /* Force channel config requested to mono if incall
9354 record is being requested for only uplink/downlink */
9355 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9356 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9357 ret = -EINVAL;
9358 goto err_open;
9359 }
9360 }
9361
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009362 if (is_usb_dev && may_use_hifi_record) {
9363 /* HiFi record selects an appropriate format, channel, rate combo
9364 depending on sink capabilities*/
9365 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9366 &config->format,
9367 &in->supported_formats[0],
9368 MAX_SUPPORTED_FORMATS,
9369 &config->channel_mask,
9370 &in->supported_channel_masks[0],
9371 MAX_SUPPORTED_CHANNEL_MASKS,
9372 &config->sample_rate,
9373 &in->supported_sample_rates[0],
9374 MAX_SUPPORTED_SAMPLE_RATES);
9375 if (ret != 0) {
9376 ret = -EINVAL;
9377 goto err_open;
9378 }
9379 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009380 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309381 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309382 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9383 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9384 in->config.format = PCM_FORMAT_S32_LE;
9385 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309386 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9387 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9388 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9389 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9390 bool ret_error = false;
9391 in->bit_width = 24;
9392 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9393 from HAL is 24_packed and 8_24
9394 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9395 24_packed return error indicating supported format is 24_packed
9396 *> In case of any other source requesting 24 bit or float return error
9397 indicating format supported is 16 bit only.
9398
9399 on error flinger will retry with supported format passed
9400 */
9401 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9402 (source != AUDIO_SOURCE_CAMCORDER)) {
9403 config->format = AUDIO_FORMAT_PCM_16_BIT;
9404 if (config->sample_rate > 48000)
9405 config->sample_rate = 48000;
9406 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009407 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9408 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309409 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9410 ret_error = true;
9411 }
9412
9413 if (ret_error) {
9414 ret = -EINVAL;
9415 goto err_open;
9416 }
9417 }
9418
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009419 in->channel_mask = config->channel_mask;
9420 in->format = config->format;
9421
9422 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309423
9424 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9425 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9426 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9427 else {
9428 ret = -EINVAL;
9429 goto err_open;
9430 }
9431 }
9432
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009433 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309434 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9435 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009436 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9437 is_low_latency = true;
9438#if LOW_LATENCY_CAPTURE_USE_CASE
9439 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9440#endif
9441 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009442 if (!in->realtime) {
9443 in->config = pcm_config_audio_capture;
9444 frame_size = audio_stream_in_frame_size(&in->stream);
9445 buffer_size = get_input_buffer_size(config->sample_rate,
9446 config->format,
9447 channel_count,
9448 is_low_latency);
9449 in->config.period_size = buffer_size / frame_size;
9450 in->config.rate = config->sample_rate;
9451 in->af_period_multiplier = 1;
9452 } else {
9453 // period size is left untouched for rt mode playback
9454 in->config = pcm_config_audio_capture_rt;
9455 in->af_period_multiplier = af_period_multiplier;
9456 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009457 }
9458
9459 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9460 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9461 in->realtime = 0;
9462 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9463 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009464 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009465 in->stream.start = in_start;
9466 in->stream.stop = in_stop;
9467 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9468 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009469 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009470 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009471 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9472 in->config = pcm_config_audio_capture;
9473 frame_size = audio_stream_in_frame_size(&in->stream);
9474 buffer_size = get_input_buffer_size(config->sample_rate,
9475 config->format,
9476 channel_count,
9477 false /*is_low_latency*/);
9478 in->config.period_size = buffer_size / frame_size;
9479 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009480 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009481 switch (config->format) {
9482 case AUDIO_FORMAT_PCM_32_BIT:
9483 in->bit_width = 32;
9484 break;
9485 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9486 case AUDIO_FORMAT_PCM_8_24_BIT:
9487 in->bit_width = 24;
9488 break;
9489 default:
9490 in->bit_width = 16;
9491 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009492 } else if (is_single_device_type_equal(&in->device_list,
9493 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9494 is_single_device_type_equal(&in->device_list,
9495 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009496 if (config->sample_rate == 0)
9497 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9498 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9499 config->sample_rate != 8000) {
9500 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9501 ret = -EINVAL;
9502 goto err_open;
9503 }
9504 if (config->format == AUDIO_FORMAT_DEFAULT)
9505 config->format = AUDIO_FORMAT_PCM_16_BIT;
9506 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9507 config->format = AUDIO_FORMAT_PCM_16_BIT;
9508 ret = -EINVAL;
9509 goto err_open;
9510 }
9511
9512 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009513 if (adev->ha_proxy_enable &&
9514 is_single_device_type_equal(&in->device_list,
9515 AUDIO_DEVICE_IN_TELEPHONY_RX))
9516 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009517 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009518 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009519 in->af_period_multiplier = 1;
9520 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaabdf7482020-01-03 15:00:14 +05309521 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009522 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9523 (config->sample_rate == 8000 ||
9524 config->sample_rate == 16000 ||
9525 config->sample_rate == 32000 ||
9526 config->sample_rate == 48000) &&
9527 channel_count == 1) {
9528 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9529 in->config = pcm_config_audio_capture;
9530 frame_size = audio_stream_in_frame_size(&in->stream);
9531 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9532 config->sample_rate,
9533 config->format,
9534 channel_count, false /*is_low_latency*/);
9535 in->config.period_size = buffer_size / frame_size;
9536 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9537 in->config.rate = config->sample_rate;
9538 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009539 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309540 int ret_val;
9541 pthread_mutex_lock(&adev->lock);
9542 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9543 in, config, &channel_mask_updated);
9544 pthread_mutex_unlock(&adev->lock);
9545
9546 if (!ret_val) {
9547 if (channel_mask_updated == true) {
9548 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9549 __func__, config->channel_mask);
9550 ret = -EINVAL;
9551 goto err_open;
9552 }
9553 ALOGD("%s: created multi-channel session succesfully",__func__);
9554 } else if (audio_extn_compr_cap_enabled() &&
9555 audio_extn_compr_cap_format_supported(config->format) &&
9556 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9557 audio_extn_compr_cap_init(in);
9558 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309559 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309560 if (ret)
9561 goto err_open;
9562 } else {
9563 in->config = pcm_config_audio_capture;
9564 in->config.rate = config->sample_rate;
9565 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309566 in->format = config->format;
9567 frame_size = audio_stream_in_frame_size(&in->stream);
9568 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009569 config->format,
9570 channel_count,
9571 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009572 /* prevent division-by-zero */
9573 if (frame_size == 0) {
9574 ALOGE("%s: Error frame_size==0", __func__);
9575 ret = -EINVAL;
9576 goto err_open;
9577 }
9578
Revathi Uddarajud2634032017-12-07 14:42:34 +05309579 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009580 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009581
Revathi Uddarajud2634032017-12-07 14:42:34 +05309582 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9583 /* optionally use VOIP usecase depending on config(s) */
9584 ret = adev_update_voice_comm_input_stream(in, config);
9585 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009586
Revathi Uddarajud2634032017-12-07 14:42:34 +05309587 if (ret) {
9588 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9589 goto err_open;
9590 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009591 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309592
9593 /* assign concurrent capture usecase if record has to caried out from
9594 * actual hardware input source */
9595 if (audio_extn_is_concurrent_capture_enabled() &&
9596 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309597 /* Acquire lock to avoid two concurrent use cases initialized to
9598 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009599
Samyak Jainc37062f2019-04-25 18:41:06 +05309600 if (in->usecase == USECASE_AUDIO_RECORD) {
9601 pthread_mutex_lock(&adev->lock);
9602 if (!(adev->pcm_record_uc_state)) {
9603 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9604 adev->pcm_record_uc_state = 1;
9605 pthread_mutex_unlock(&adev->lock);
9606 } else {
9607 pthread_mutex_unlock(&adev->lock);
9608 /* Assign compress record use case for second record */
9609 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9610 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9611 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9612 if (audio_extn_cin_applicable_stream(in)) {
9613 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309614 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309615 if (ret)
9616 goto err_open;
9617 }
9618 }
9619 }
kunleiz28c73e72019-03-27 17:24:04 +08009620 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009621 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309622 if (audio_extn_ssr_get_stream() != in)
9623 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009624
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009625 in->sample_rate = in->config.rate;
9626
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309627 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9628 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009629 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009630 in->sample_rate, in->bit_width,
9631 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309632 register_format(in->format, in->supported_formats);
9633 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9634 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309635
Aalique Grahame22e49102018-12-18 14:23:57 -08009636 in->error_log = error_log_create(
9637 ERROR_LOG_ENTRIES,
9638 1000000000 /* aggregate consecutive identical errors within one second */);
9639
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009640 /* This stream could be for sound trigger lab,
9641 get sound trigger pcm if present */
9642 audio_extn_sound_trigger_check_and_get_session(in);
9643
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309644 lock_input_stream(in);
9645 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9646 pthread_mutex_lock(&adev->lock);
9647 in->card_status = adev->card_status;
9648 pthread_mutex_unlock(&adev->lock);
9649 pthread_mutex_unlock(&in->lock);
9650
Aalique Grahame22e49102018-12-18 14:23:57 -08009651 stream_app_type_cfg_init(&in->app_type_cfg);
9652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009653 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009654
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009655 ret = io_streams_map_insert(adev, &in->stream.common,
9656 handle, AUDIO_PATCH_HANDLE_NONE);
9657 if (ret != 0)
9658 goto err_open;
9659
Derek Chenf939fb72018-11-13 13:34:41 -08009660 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9661 calloc(1, sizeof(streams_input_ctxt_t));
9662 if (in_ctxt == NULL) {
9663 ALOGE("%s fail to allocate input ctxt", __func__);
9664 ret = -ENOMEM;
9665 goto err_open;
9666 }
9667 in_ctxt->input = in;
9668
9669 pthread_mutex_lock(&adev->lock);
9670 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9671 pthread_mutex_unlock(&adev->lock);
9672
Eric Laurent994a6932013-07-17 11:51:42 -07009673 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009674 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009675
9676err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309677 if (in->usecase == USECASE_AUDIO_RECORD) {
9678 pthread_mutex_lock(&adev->lock);
9679 adev->pcm_record_uc_state = 0;
9680 pthread_mutex_unlock(&adev->lock);
9681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009682 free(in);
9683 *stream_in = NULL;
9684 return ret;
9685}
9686
9687static void adev_close_input_stream(struct audio_hw_device *dev,
9688 struct audio_stream_in *stream)
9689{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009690 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009691 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009692 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309693
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309694 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009695
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009696 if (in == NULL) {
9697 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9698 return;
9699 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009700 io_streams_map_remove(adev, in->capture_handle);
9701
kunleiz70e57612018-12-28 17:50:23 +08009702 /* must deregister from sndmonitor first to prevent races
9703 * between the callback and close_stream
9704 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309705 audio_extn_snd_mon_unregister_listener(stream);
9706
kunleiz70e57612018-12-28 17:50:23 +08009707 /* Disable echo reference if there are no active input, hfp call
9708 * and sound trigger while closing input stream
9709 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009710 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009711 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009712 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9713 struct listnode out_devices;
9714 list_init(&out_devices);
9715 platform_set_echo_reference(adev, false, &out_devices);
9716 } else
kunleiz70e57612018-12-28 17:50:23 +08009717 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309718
Weiyin Jiang2995f662019-04-17 14:25:12 +08009719 error_log_destroy(in->error_log);
9720 in->error_log = NULL;
9721
Pallavid7c7a272018-01-16 11:22:55 +05309722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009723 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309724 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009725 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309726 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009727 if (ret != 0)
9728 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9729 __func__, ret);
9730 } else
9731 in_standby(&stream->common);
9732
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009733 pthread_mutex_destroy(&in->lock);
9734 pthread_mutex_destroy(&in->pre_lock);
9735
Revathi Uddarajud2634032017-12-07 14:42:34 +05309736 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309737 if (in->usecase == USECASE_AUDIO_RECORD) {
9738 adev->pcm_record_uc_state = 0;
9739 }
9740
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009741 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9742 adev->enable_voicerx = false;
9743 }
9744
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009745 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009746 audio_extn_ssr_deinit();
9747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009748
Garmond Leunge2433c32017-09-28 21:51:22 -07009749 if (audio_extn_ffv_get_stream() == in) {
9750 audio_extn_ffv_stream_deinit();
9751 }
9752
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309753 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009754 audio_extn_compr_cap_format_supported(in->config.format))
9755 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309756
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309757 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309758 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009759
Mingming Yinfd7607b2016-01-22 12:48:44 -08009760 if (in->is_st_session) {
9761 ALOGV("%s: sound trigger pcm stop lab", __func__);
9762 audio_extn_sound_trigger_stop_lab(in);
9763 }
Derek Chenf939fb72018-11-13 13:34:41 -08009764 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9765 if (in_ctxt != NULL) {
9766 list_remove(&in_ctxt->list);
9767 free(in_ctxt);
9768 } else {
9769 ALOGW("%s, input stream already closed", __func__);
9770 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009771 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309772 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009773 return;
9774}
9775
Aalique Grahame22e49102018-12-18 14:23:57 -08009776/* verifies input and output devices and their capabilities.
9777 *
9778 * This verification is required when enabling extended bit-depth or
9779 * sampling rates, as not all qcom products support it.
9780 *
9781 * Suitable for calling only on initialization such as adev_open().
9782 * It fills the audio_device use_case_table[] array.
9783 *
9784 * Has a side-effect that it needs to configure audio routing / devices
9785 * in order to power up the devices and read the device parameters.
9786 * It does not acquire any hw device lock. Should restore the devices
9787 * back to "normal state" upon completion.
9788 */
9789static int adev_verify_devices(struct audio_device *adev)
9790{
9791 /* enumeration is a bit difficult because one really wants to pull
9792 * the use_case, device id, etc from the hidden pcm_device_table[].
9793 * In this case there are the following use cases and device ids.
9794 *
9795 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9796 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9797 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9798 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9799 * [USECASE_AUDIO_RECORD] = {0, 0},
9800 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9801 * [USECASE_VOICE_CALL] = {2, 2},
9802 *
9803 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9804 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9805 */
9806
9807 /* should be the usecases enabled in adev_open_input_stream() */
9808 static const int test_in_usecases[] = {
9809 USECASE_AUDIO_RECORD,
9810 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9811 };
9812 /* should be the usecases enabled in adev_open_output_stream()*/
9813 static const int test_out_usecases[] = {
9814 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9815 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9816 };
9817 static const usecase_type_t usecase_type_by_dir[] = {
9818 PCM_PLAYBACK,
9819 PCM_CAPTURE,
9820 };
9821 static const unsigned flags_by_dir[] = {
9822 PCM_OUT,
9823 PCM_IN,
9824 };
9825
9826 size_t i;
9827 unsigned dir;
9828 const unsigned card_id = adev->snd_card;
9829
9830 for (dir = 0; dir < 2; ++dir) {
9831 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9832 const unsigned flags_dir = flags_by_dir[dir];
9833 const size_t testsize =
9834 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9835 const int *testcases =
9836 dir ? test_in_usecases : test_out_usecases;
9837 const audio_devices_t audio_device =
9838 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9839
9840 for (i = 0; i < testsize; ++i) {
9841 const audio_usecase_t audio_usecase = testcases[i];
9842 int device_id;
9843 struct pcm_params **pparams;
9844 struct stream_out out;
9845 struct stream_in in;
9846 struct audio_usecase uc_info;
9847 int retval;
9848
9849 pparams = &adev->use_case_table[audio_usecase];
9850 pcm_params_free(*pparams); /* can accept null input */
9851 *pparams = NULL;
9852
9853 /* find the device ID for the use case (signed, for error) */
9854 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9855 if (device_id < 0)
9856 continue;
9857
9858 /* prepare structures for device probing */
9859 memset(&uc_info, 0, sizeof(uc_info));
9860 uc_info.id = audio_usecase;
9861 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009862 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009863 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009864 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009865 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009866 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009867 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9868 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009869 }
9870 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009871 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009872 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009873 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009874 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009875 uc_info.in_snd_device = SND_DEVICE_NONE;
9876 uc_info.out_snd_device = SND_DEVICE_NONE;
9877 list_add_tail(&adev->usecase_list, &uc_info.list);
9878
9879 /* select device - similar to start_(in/out)put_stream() */
9880 retval = select_devices(adev, audio_usecase);
9881 if (retval >= 0) {
9882 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9883#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009884 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009885 if (*pparams) {
9886 ALOGV("%s: (%s) card %d device %d", __func__,
9887 dir ? "input" : "output", card_id, device_id);
9888 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9889 } else {
9890 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9891 }
9892#endif
9893 }
9894
9895 /* deselect device - similar to stop_(in/out)put_stream() */
9896 /* 1. Get and set stream specific mixer controls */
9897 retval = disable_audio_route(adev, &uc_info);
9898 /* 2. Disable the rx device */
9899 retval = disable_snd_device(adev,
9900 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9901 list_remove(&uc_info.list);
9902 }
9903 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009904 return 0;
9905}
9906
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009907int update_patch(unsigned int num_sources,
9908 const struct audio_port_config *sources,
9909 unsigned int num_sinks,
9910 const struct audio_port_config *sinks,
9911 audio_patch_handle_t handle,
9912 struct audio_patch_info *p_info,
9913 patch_type_t patch_type, bool new_patch)
9914{
9915 ALOGD("%s: enter", __func__);
9916
9917 if (p_info == NULL) {
9918 ALOGE("%s: Invalid patch pointer", __func__);
9919 return -EINVAL;
9920 }
9921
9922 if (new_patch) {
9923 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9924 if (p_info->patch == NULL) {
9925 ALOGE("%s: Could not allocate patch", __func__);
9926 return -ENOMEM;
9927 }
9928 }
9929
9930 p_info->patch->id = handle;
9931 p_info->patch->num_sources = num_sources;
9932 p_info->patch->num_sinks = num_sinks;
9933
9934 for (int i = 0; i < num_sources; i++)
9935 p_info->patch->sources[i] = sources[i];
9936 for (int i = 0; i < num_sinks; i++)
9937 p_info->patch->sinks[i] = sinks[i];
9938
9939 p_info->patch_type = patch_type;
9940 return 0;
9941}
9942
9943audio_patch_handle_t generate_patch_handle()
9944{
9945 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9946 if (++patch_handle < 0)
9947 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9948 return patch_handle;
9949}
9950
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309951int adev_create_audio_patch(struct audio_hw_device *dev,
9952 unsigned int num_sources,
9953 const struct audio_port_config *sources,
9954 unsigned int num_sinks,
9955 const struct audio_port_config *sinks,
9956 audio_patch_handle_t *handle)
9957{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009958 int ret = 0;
9959 struct audio_device *adev = (struct audio_device *)dev;
9960 struct audio_patch_info *p_info = NULL;
9961 patch_type_t patch_type = PATCH_NONE;
9962 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9963 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9964 struct audio_stream_info *s_info = NULL;
9965 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009966 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009967 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9968 bool new_patch = false;
9969 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309970
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009971 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9972 num_sources, num_sinks, *handle);
9973
9974 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9975 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9976 ALOGE("%s: Invalid patch arguments", __func__);
9977 ret = -EINVAL;
9978 goto done;
9979 }
9980
9981 if (num_sources > 1) {
9982 ALOGE("%s: Multiple sources are not supported", __func__);
9983 ret = -EINVAL;
9984 goto done;
9985 }
9986
9987 if (sources == NULL || sinks == NULL) {
9988 ALOGE("%s: Invalid sources or sinks port config", __func__);
9989 ret = -EINVAL;
9990 goto done;
9991 }
9992
9993 ALOGV("%s: source role %d, source type %d", __func__,
9994 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009995 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009996
9997 // Populate source/sink information and fetch stream info
9998 switch (sources[0].type) {
9999 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10000 device_type = sources[0].ext.device.type;
10001 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010002 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010003 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10004 patch_type = PATCH_CAPTURE;
10005 io_handle = sinks[0].ext.mix.handle;
10006 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010007 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010008 __func__, device_type, io_handle);
10009 } else {
10010 // Device to device patch is not implemented.
10011 // This space will need changes if audio HAL
10012 // handles device to device patches in the future.
10013 patch_type = PATCH_DEVICE_LOOPBACK;
10014 }
10015 break;
10016 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10017 io_handle = sources[0].ext.mix.handle;
10018 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010019 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010020 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010021 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010022 }
10023 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010024 ALOGD("%s: Playback patch from mix handle %d to device %x",
10025 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010026 break;
10027 case AUDIO_PORT_TYPE_SESSION:
10028 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010029 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10030 ret = -EINVAL;
10031 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032 }
10033
10034 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010036 // Generate patch info and update patch
10037 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010038 *handle = generate_patch_handle();
10039 p_info = (struct audio_patch_info *)
10040 calloc(1, sizeof(struct audio_patch_info));
10041 if (p_info == NULL) {
10042 ALOGE("%s: Failed to allocate memory", __func__);
10043 pthread_mutex_unlock(&adev->lock);
10044 ret = -ENOMEM;
10045 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010046 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010047 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010048 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010049 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010050 if (p_info == NULL) {
10051 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10052 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010053 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010054 ret = -EINVAL;
10055 goto done;
10056 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010057 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010058 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010059 *handle, p_info, patch_type, new_patch);
10060
10061 // Fetch stream info of associated mix for playback or capture patches
10062 if (p_info->patch_type == PATCH_PLAYBACK ||
10063 p_info->patch_type == PATCH_CAPTURE) {
10064 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10065 if (s_info == NULL) {
10066 ALOGE("%s: Failed to obtain stream info", __func__);
10067 if (new_patch)
10068 free(p_info);
10069 pthread_mutex_unlock(&adev->lock);
10070 ret = -EINVAL;
10071 goto done;
10072 }
10073 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10074 s_info->patch_handle = *handle;
10075 stream = s_info->stream;
10076 }
10077 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010078
10079 // Update routing for stream
10080 if (stream != NULL) {
10081 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010082 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010084 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010085 if (ret < 0) {
10086 pthread_mutex_lock(&adev->lock);
10087 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10088 if (new_patch)
10089 free(p_info);
10090 pthread_mutex_unlock(&adev->lock);
10091 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10092 goto done;
10093 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010094 }
10095
10096 // Add new patch to patch map
10097 if (!ret && new_patch) {
10098 pthread_mutex_lock(&adev->lock);
10099 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010101 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010102 }
10103
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104done:
10105 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010106 num_sources,
10107 sources,
10108 num_sinks,
10109 sinks,
10110 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010111 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010112 num_sources,
10113 sources,
10114 num_sinks,
10115 sinks,
10116 handle);
10117 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010118}
10119
10120int adev_release_audio_patch(struct audio_hw_device *dev,
10121 audio_patch_handle_t handle)
10122{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010123 struct audio_device *adev = (struct audio_device *) dev;
10124 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010125 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010126 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010127
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10129 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10130 ret = -EINVAL;
10131 goto done;
10132 }
10133
10134 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010135 pthread_mutex_lock(&adev->lock);
10136 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 if (p_info == NULL) {
10138 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010139 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 ret = -EINVAL;
10141 goto done;
10142 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010143 struct audio_patch *patch = p_info->patch;
10144 if (patch == NULL) {
10145 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010146 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010148 goto done;
10149 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010150 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10151 switch (patch->sources[0].type) {
10152 case AUDIO_PORT_TYPE_MIX:
10153 io_handle = patch->sources[0].ext.mix.handle;
10154 break;
10155 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010156 if (p_info->patch_type == PATCH_CAPTURE)
10157 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010158 break;
10159 case AUDIO_PORT_TYPE_SESSION:
10160 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010161 pthread_mutex_unlock(&adev->lock);
10162 ret = -EINVAL;
10163 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010164 }
10165
10166 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010167 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010168 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010169 if (patch_type == PATCH_PLAYBACK ||
10170 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010171 struct audio_stream_info *s_info =
10172 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10173 if (s_info == NULL) {
10174 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10175 pthread_mutex_unlock(&adev->lock);
10176 goto done;
10177 }
10178 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10179 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010180 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010181 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010182
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010183 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010184 struct listnode devices;
10185 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010186 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010187 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010188 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010189 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010190 }
10191
10192 if (ret < 0)
10193 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10194
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195done:
10196 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10197 audio_extn_auto_hal_release_audio_patch(dev, handle);
10198
10199 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010200 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010201}
10202
10203int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10204{
Derek Chenf13dd492018-11-13 14:53:51 -080010205 int ret = 0;
10206
10207 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10208 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10209 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010210}
10211
10212int adev_set_audio_port_config(struct audio_hw_device *dev,
10213 const struct audio_port_config *config)
10214{
Derek Chenf13dd492018-11-13 14:53:51 -080010215 int ret = 0;
10216
10217 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10218 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10219 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010220}
10221
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010222static int adev_dump(const audio_hw_device_t *device __unused,
10223 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010224{
10225 return 0;
10226}
10227
10228static int adev_close(hw_device_t *device)
10229{
Aalique Grahame22e49102018-12-18 14:23:57 -080010230 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010231 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010232
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010233 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010234 return 0;
10235
10236 pthread_mutex_lock(&adev_init_lock);
10237
10238 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010239 if (audio_extn_spkr_prot_is_enabled())
10240 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010241 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010242 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010243 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010244 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010245 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010246 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010247 audio_extn_utils_release_streams_cfg_lists(
10248 &adev->streams_output_cfg_list,
10249 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010250 if (audio_extn_qap_is_enabled())
10251 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010252 if (audio_extn_qaf_is_enabled())
10253 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010254 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010255 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010256 free(adev->snd_dev_ref_cnt);
10257 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010258 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10259 pcm_params_free(adev->use_case_table[i]);
10260 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010261 if (adev->adm_deinit)
10262 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010263 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010264 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010265 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010266 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010267 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010268 if (adev->device_cfg_params) {
10269 free(adev->device_cfg_params);
10270 adev->device_cfg_params = NULL;
10271 }
Derek Chend2530072014-11-24 12:39:14 -080010272 if(adev->ext_hw_plugin)
10273 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010274 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010275 free_map(adev->patch_map);
10276 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010277 free(device);
10278 adev = NULL;
10279 }
10280 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010281 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010282 return 0;
10283}
10284
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010285/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10286 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10287 * just that it _might_ work.
10288 */
10289static int period_size_is_plausible_for_low_latency(int period_size)
10290{
10291 switch (period_size) {
10292 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010293 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010294 case 240:
10295 case 320:
10296 case 480:
10297 return 1;
10298 default:
10299 return 0;
10300 }
10301}
10302
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010303static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10304{
10305 bool is_snd_card_status = false;
10306 bool is_ext_device_status = false;
10307 char value[32];
10308 int card = -1;
10309 card_status_t status;
10310
10311 if (cookie != adev || !parms)
10312 return;
10313
10314 if (!parse_snd_card_status(parms, &card, &status)) {
10315 is_snd_card_status = true;
10316 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10317 is_ext_device_status = true;
10318 } else {
10319 // not a valid event
10320 return;
10321 }
10322
10323 pthread_mutex_lock(&adev->lock);
10324 if (card == adev->snd_card || is_ext_device_status) {
10325 if (is_snd_card_status && adev->card_status != status) {
10326 adev->card_status = status;
10327 platform_snd_card_update(adev->platform, status);
10328 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010329 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010330 if (status == CARD_STATUS_OFFLINE)
10331 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010332 } else if (is_ext_device_status) {
10333 platform_set_parameters(adev->platform, parms);
10334 }
10335 }
10336 pthread_mutex_unlock(&adev->lock);
10337 return;
10338}
10339
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010340/* adev lock held */
10341int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010342{
10343 struct audio_usecase *uc_info;
10344 float left_p;
10345 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010346 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010347
10348 uc_info = get_usecase_from_list(adev, out->usecase);
10349 if (uc_info == NULL) {
10350 ALOGE("%s: Could not find the usecase (%d) in the list",
10351 __func__, out->usecase);
10352 return -EINVAL;
10353 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010354 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010355
Zhou Song1f93fa52020-11-20 13:57:39 +080010356 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10357 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010358
10359 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010360 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010361 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010362 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010363 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010364 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10365 select_devices(adev, uc_info->id);
Zhou Song1f93fa52020-11-20 13:57:39 +080010366
10367 if (is_offload_usecase(out->usecase)) {
10368 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010369 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Song1f93fa52020-11-20 13:57:39 +080010370 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10371 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10372 } else {
10373 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010374 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010375 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010376 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010377 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010378 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010379 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +080010380 // mute stream and switch to speaker if suspended
10381 if (!out->a2dp_muted && !out->standby) {
10382 ALOGD("%s: selecting speaker and muting stream", __func__);
10383 assign_devices(&devices, &out->device_list);
10384 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
10385 left_p = out->volume_l;
10386 right_p = out->volume_r;
10387 out->a2dp_muted = true;
10388 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010389 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10390 compress_pause(out->compr);
10391 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song1f93fa52020-11-20 13:57:39 +080010392 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10393 out_set_voip_volume(&out->stream, (float)0, (float)0);
10394 } else {
10395 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10396 /* wait for stale pcm drained before switching to speaker */
10397 uint32_t latency =
10398 (out->config.period_count * out->config.period_size * 1000) /
10399 (out->config.rate);
10400 usleep(latency * 1000);
10401 }
10402 select_devices(adev, out->usecase);
10403 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010404 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10405 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010406 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010407 assign_devices(&out->device_list, &devices);
10408 out->volume_l = left_p;
10409 out->volume_r = right_p;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010410 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010411 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010412 }
10413 ALOGV("%s: exit", __func__);
10414 return 0;
10415}
10416
Haynes Mathew George01156f92018-04-13 15:29:54 -070010417void adev_on_battery_status_changed(bool charging)
10418{
10419 pthread_mutex_lock(&adev->lock);
10420 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10421 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010422 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010423 pthread_mutex_unlock(&adev->lock);
10424}
10425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010426static int adev_open(const hw_module_t *module, const char *name,
10427 hw_device_t **device)
10428{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010429 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010430 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010431 char mixer_ctl_name[128] = {0};
10432 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010433
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010434 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010435 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10436
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010437 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010438 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010439 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010440 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010441 ALOGD("%s: returning existing instance of adev", __func__);
10442 ALOGD("%s: exit", __func__);
10443 pthread_mutex_unlock(&adev_init_lock);
10444 return 0;
10445 }
10446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010447 adev = calloc(1, sizeof(struct audio_device));
10448
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010449 if (!adev) {
10450 pthread_mutex_unlock(&adev_init_lock);
10451 return -ENOMEM;
10452 }
10453
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010454 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10455
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010456 // register audio ext hidl at the earliest
10457 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010458#ifdef DYNAMIC_LOG_ENABLED
10459 register_for_dynamic_logging("hal");
10460#endif
10461
Derek Chenf939fb72018-11-13 13:34:41 -080010462 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010463 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010464 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10465 maj_version = atoi(value);
10466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010467 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010468 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010469 adev->device.common.module = (struct hw_module_t *)module;
10470 adev->device.common.close = adev_close;
10471
10472 adev->device.init_check = adev_init_check;
10473 adev->device.set_voice_volume = adev_set_voice_volume;
10474 adev->device.set_master_volume = adev_set_master_volume;
10475 adev->device.get_master_volume = adev_get_master_volume;
10476 adev->device.set_master_mute = adev_set_master_mute;
10477 adev->device.get_master_mute = adev_get_master_mute;
10478 adev->device.set_mode = adev_set_mode;
10479 adev->device.set_mic_mute = adev_set_mic_mute;
10480 adev->device.get_mic_mute = adev_get_mic_mute;
10481 adev->device.set_parameters = adev_set_parameters;
10482 adev->device.get_parameters = adev_get_parameters;
10483 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10484 adev->device.open_output_stream = adev_open_output_stream;
10485 adev->device.close_output_stream = adev_close_output_stream;
10486 adev->device.open_input_stream = adev_open_input_stream;
10487 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010488 adev->device.create_audio_patch = adev_create_audio_patch;
10489 adev->device.release_audio_patch = adev_release_audio_patch;
10490 adev->device.get_audio_port = adev_get_audio_port;
10491 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010492 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010493 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010494
10495 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010496 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010497 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010498 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010499 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010500 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010501 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010502 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010503 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010504 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010505 /* Init audio and voice feature */
10506 audio_extn_feature_init();
10507 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010508 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010509 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010510 list_init(&adev->active_inputs_list);
10511 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010512 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010513 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10514 audio_extn_utils_hash_eq);
10515 if (!adev->io_streams_map) {
10516 ALOGE("%s: Could not create io streams map", __func__);
10517 ret = -ENOMEM;
10518 goto adev_open_err;
10519 }
10520 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10521 audio_extn_utils_hash_eq);
10522 if (!adev->patch_map) {
10523 ALOGE("%s: Could not create audio patch map", __func__);
10524 ret = -ENOMEM;
10525 goto adev_open_err;
10526 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010527 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010528 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010529 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010530 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010531 adev->perf_lock_opts[0] = 0x101;
10532 adev->perf_lock_opts[1] = 0x20E;
10533 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010534 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010535 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010536 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010537 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010538 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010539
Zhou Song68ebc352019-12-05 17:11:15 +080010540 audio_extn_perf_lock_init();
10541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010542 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010543 adev->platform = platform_init(adev);
10544 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010545 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010546 ret = -EINVAL;
10547 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010548 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010549
Aalique Grahame22e49102018-12-18 14:23:57 -080010550 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010551 if (audio_extn_qap_is_enabled()) {
10552 ret = audio_extn_qap_init(adev);
10553 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010554 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010555 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010556 }
10557 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10558 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10559 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010560
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010561 if (audio_extn_qaf_is_enabled()) {
10562 ret = audio_extn_qaf_init(adev);
10563 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010564 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010565 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010566 }
10567
10568 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10569 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10570 }
10571
Derek Chenae7b0342019-02-08 15:17:04 -080010572 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010573 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10574
Eric Laurentc4aef752013-09-12 17:45:53 -070010575 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10576 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10577 if (adev->visualizer_lib == NULL) {
10578 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10579 } else {
10580 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10581 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010582 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010583 "visualizer_hal_start_output");
10584 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010585 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010586 "visualizer_hal_stop_output");
10587 }
10588 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010589 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010590 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010591 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010592 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010593 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010594 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010595
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010596 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10597 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10598 if (adev->offload_effects_lib == NULL) {
10599 ALOGE("%s: DLOPEN failed for %s", __func__,
10600 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10601 } else {
10602 ALOGV("%s: DLOPEN successful for %s", __func__,
10603 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10604 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010605 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010606 "offload_effects_bundle_hal_start_output");
10607 adev->offload_effects_stop_output =
10608 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10609 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010610 adev->offload_effects_set_hpx_state =
10611 (int (*)(bool))dlsym(adev->offload_effects_lib,
10612 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010613 adev->offload_effects_get_parameters =
10614 (void (*)(struct str_parms *, struct str_parms *))
10615 dlsym(adev->offload_effects_lib,
10616 "offload_effects_bundle_get_parameters");
10617 adev->offload_effects_set_parameters =
10618 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10619 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010620 }
10621 }
10622
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010623 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10624 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10625 if (adev->adm_lib == NULL) {
10626 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10627 } else {
10628 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10629 adev->adm_init = (adm_init_t)
10630 dlsym(adev->adm_lib, "adm_init");
10631 adev->adm_deinit = (adm_deinit_t)
10632 dlsym(adev->adm_lib, "adm_deinit");
10633 adev->adm_register_input_stream = (adm_register_input_stream_t)
10634 dlsym(adev->adm_lib, "adm_register_input_stream");
10635 adev->adm_register_output_stream = (adm_register_output_stream_t)
10636 dlsym(adev->adm_lib, "adm_register_output_stream");
10637 adev->adm_deregister_stream = (adm_deregister_stream_t)
10638 dlsym(adev->adm_lib, "adm_deregister_stream");
10639 adev->adm_request_focus = (adm_request_focus_t)
10640 dlsym(adev->adm_lib, "adm_request_focus");
10641 adev->adm_abandon_focus = (adm_abandon_focus_t)
10642 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010643 adev->adm_set_config = (adm_set_config_t)
10644 dlsym(adev->adm_lib, "adm_set_config");
10645 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10646 dlsym(adev->adm_lib, "adm_request_focus_v2");
10647 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10648 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10649 adev->adm_on_routing_change = (adm_on_routing_change_t)
10650 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010651 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10652 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010653 }
10654 }
10655
Aalique Grahame22e49102018-12-18 14:23:57 -080010656 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010657 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010658 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010659 //initialize this to false for now,
10660 //this will be set to true through set param
10661 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010662
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010663 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010664 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010665
10666 if (k_enable_extended_precision)
10667 adev_verify_devices(adev);
10668
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010669 adev->dsp_bit_width_enforce_mode =
10670 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010671
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010672 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10673 &adev->streams_output_cfg_list,
10674 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010675
Kiran Kandi910e1862013-10-29 13:29:42 -070010676 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010677
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010678 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010679 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010680 trial = atoi(value);
10681 if (period_size_is_plausible_for_low_latency(trial)) {
10682 pcm_config_low_latency.period_size = trial;
10683 pcm_config_low_latency.start_threshold = trial / 4;
10684 pcm_config_low_latency.avail_min = trial / 4;
10685 configured_low_latency_capture_period_size = trial;
10686 }
10687 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010688 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10689 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010690 trial = atoi(value);
10691 if (period_size_is_plausible_for_low_latency(trial)) {
10692 configured_low_latency_capture_period_size = trial;
10693 }
10694 }
10695
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010696 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10697
Eric Laurent4b084132018-10-19 17:33:43 -070010698 adev->camera_orientation = CAMERA_DEFAULT;
10699
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010700 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010701 af_period_multiplier = atoi(value);
10702 if (af_period_multiplier < 0)
10703 af_period_multiplier = 2;
10704 else if (af_period_multiplier > 4)
10705 af_period_multiplier = 4;
10706
10707 ALOGV("new period_multiplier = %d", af_period_multiplier);
10708 }
10709
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010710 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010711
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010712 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010713 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010714 pthread_mutex_unlock(&adev_init_lock);
10715
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010716 if (adev->adm_init)
10717 adev->adm_data = adev->adm_init();
10718
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010719 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010720 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010721
10722 audio_extn_snd_mon_init();
10723 pthread_mutex_lock(&adev->lock);
10724 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10725 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010726 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10727 /*
10728 * if the battery state callback happens before charging can be queried,
10729 * it will be guarded with the adev->lock held in the cb function and so
10730 * the callback value will reflect the latest state
10731 */
10732 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010733 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010734 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010735 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010736 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010737 /* Allocate memory for Device config params */
10738 adev->device_cfg_params = (struct audio_device_config_param*)
10739 calloc(platform_get_max_codec_backend(),
10740 sizeof(struct audio_device_config_param));
10741 if (adev->device_cfg_params == NULL)
10742 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010743
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010744 /*
10745 * Check if new PSPD matrix mixer control is supported. If not
10746 * supported, then set flag so that old mixer ctrl is sent while
10747 * sending pspd coefficients on older kernel version. Query mixer
10748 * control for default pcm id and channel value one.
10749 */
10750 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10751 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10752
10753 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10754 if (!ctl) {
10755 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10756 __func__, mixer_ctl_name);
10757 adev->use_old_pspd_mix_ctrl = true;
10758 }
10759
Eric Laurent994a6932013-07-17 11:51:42 -070010760 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010761 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010762
10763adev_open_err:
10764 free_map(adev->patch_map);
10765 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010766 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010767 pthread_mutex_destroy(&adev->lock);
10768 free(adev);
10769 adev = NULL;
10770 *device = NULL;
10771 pthread_mutex_unlock(&adev_init_lock);
10772 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010773}
10774
10775static struct hw_module_methods_t hal_module_methods = {
10776 .open = adev_open,
10777};
10778
10779struct audio_module HAL_MODULE_INFO_SYM = {
10780 .common = {
10781 .tag = HARDWARE_MODULE_TAG,
10782 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10783 .hal_api_version = HARDWARE_HAL_API_VERSION,
10784 .id = AUDIO_HARDWARE_MODULE_ID,
10785 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010786 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010787 .methods = &hal_module_methods,
10788 },
10789};