blob: d732fa520b3fce46aff9f6eb425749603b0b675a [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
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003350/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351static void stop_compressed_output_l(struct stream_out *out)
3352{
3353 out->offload_state = OFFLOAD_STATE_IDLE;
3354 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003355 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 if (out->compr != NULL) {
3357 compress_stop(out->compr);
3358 while (out->offload_thread_blocked) {
3359 pthread_cond_wait(&out->cond, &out->lock);
3360 }
3361 }
3362}
3363
Varun Balaraje49253e2017-07-06 19:48:56 +05303364bool is_interactive_usecase(audio_usecase_t uc_id)
3365{
3366 unsigned int i;
3367 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3368 if (uc_id == interactive_usecases[i])
3369 return true;
3370 }
3371 return false;
3372}
3373
3374static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3375{
3376 audio_usecase_t ret_uc = USECASE_INVALID;
3377 unsigned int intract_uc_index;
3378 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3379
3380 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3381 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3382 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3383 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3384 ret_uc = interactive_usecases[intract_uc_index];
3385 break;
3386 }
3387 }
3388
3389 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3390 return ret_uc;
3391}
3392
3393static void free_interactive_usecase(struct audio_device *adev,
3394 audio_usecase_t uc_id)
3395{
3396 unsigned int interact_uc_index;
3397 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3398
3399 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3400 if (interactive_usecases[interact_uc_index] == uc_id) {
3401 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3402 break;
3403 }
3404 }
3405 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3406}
3407
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003408bool is_offload_usecase(audio_usecase_t uc_id)
3409{
3410 unsigned int i;
3411 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3412 if (uc_id == offload_usecases[i])
3413 return true;
3414 }
3415 return false;
3416}
3417
Dhananjay Kumarac341582017-02-23 23:42:25 +05303418static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003419{
vivek mehta446c3962015-09-14 10:57:35 -07003420 audio_usecase_t ret_uc = USECASE_INVALID;
3421 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003422 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003423 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303424 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003425 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3426 else
3427 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003428
vivek mehta446c3962015-09-14 10:57:35 -07003429 pthread_mutex_lock(&adev->lock);
3430 if (get_usecase_from_list(adev, ret_uc) != NULL)
3431 ret_uc = USECASE_INVALID;
3432 pthread_mutex_unlock(&adev->lock);
3433
3434 return ret_uc;
3435 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003436
3437 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003438 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3439 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3440 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3441 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003442 break;
3443 }
3444 }
vivek mehta446c3962015-09-14 10:57:35 -07003445
3446 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3447 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003448}
3449
3450static void free_offload_usecase(struct audio_device *adev,
3451 audio_usecase_t uc_id)
3452{
vivek mehta446c3962015-09-14 10:57:35 -07003453 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003454 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003455
3456 if (!adev->multi_offload_enable)
3457 return;
3458
3459 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3460 if (offload_usecases[offload_uc_index] == uc_id) {
3461 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003462 break;
3463 }
3464 }
3465 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3466}
3467
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468static void *offload_thread_loop(void *context)
3469{
3470 struct stream_out *out = (struct stream_out *) context;
3471 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003472 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003475 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3477
3478 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003479 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003480 out->offload_state = OFFLOAD_STATE_IDLE;
3481 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 for (;;) {
3483 struct offload_cmd *cmd = NULL;
3484 stream_callback_event_t event;
3485 bool send_callback = false;
3486
3487 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3488 __func__, list_empty(&out->offload_cmd_list),
3489 out->offload_state);
3490 if (list_empty(&out->offload_cmd_list)) {
3491 ALOGV("%s SLEEPING", __func__);
3492 pthread_cond_wait(&out->offload_cond, &out->lock);
3493 ALOGV("%s RUNNING", __func__);
3494 continue;
3495 }
3496
3497 item = list_head(&out->offload_cmd_list);
3498 cmd = node_to_item(item, struct offload_cmd, node);
3499 list_remove(item);
3500
3501 ALOGVV("%s STATE %d CMD %d out->compr %p",
3502 __func__, out->offload_state, cmd->cmd, out->compr);
3503
3504 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3505 free(cmd);
3506 break;
3507 }
3508
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003509 // allow OFFLOAD_CMD_ERROR reporting during standby
3510 // this is needed to handle failures during compress_open
3511 // Note however that on a pause timeout, the stream is closed
3512 // and no offload usecase will be active. Therefore this
3513 // special case is needed for compress_open failures alone
3514 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3515 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003516 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003517 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 pthread_cond_signal(&out->cond);
3519 continue;
3520 }
3521 out->offload_thread_blocked = true;
3522 pthread_mutex_unlock(&out->lock);
3523 send_callback = false;
3524 switch(cmd->cmd) {
3525 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003526 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003527 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003528 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003529 send_callback = true;
3530 event = STREAM_CBK_EVENT_WRITE_READY;
3531 break;
3532 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003533 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303534 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003535 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303536 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003537 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303538 if (ret < 0)
3539 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303540 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303541 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003542 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003543 else
3544 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003545 if (-ENETRESET != ret && !(-EINTR == ret &&
3546 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303547 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303548 pthread_mutex_lock(&out->lock);
3549 out->send_new_metadata = 1;
3550 out->send_next_track_params = true;
3551 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303552 event = STREAM_CBK_EVENT_DRAIN_READY;
3553 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3554 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303555 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 break;
3557 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003558 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003559 ret = compress_drain(out->compr);
3560 ALOGD("copl(%p):out of compress_drain", out);
3561 // EINTR check avoids drain interruption due to SSR
3562 if (-ENETRESET != ret && !(-EINTR == ret &&
3563 CARD_STATUS_OFFLINE == out->card_status)) {
3564 send_callback = true;
3565 event = STREAM_CBK_EVENT_DRAIN_READY;
3566 } else
3567 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003568 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303569 case OFFLOAD_CMD_ERROR:
3570 ALOGD("copl(%p): sending error callback to AF", out);
3571 send_callback = true;
3572 event = STREAM_CBK_EVENT_ERROR;
3573 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 default:
3575 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3576 break;
3577 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003578 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003579 out->offload_thread_blocked = false;
3580 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003581 if (send_callback && out->client_callback) {
3582 ALOGVV("%s: sending client_callback event %d", __func__, event);
3583 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003584 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003585 free(cmd);
3586 }
3587
3588 pthread_cond_signal(&out->cond);
3589 while (!list_empty(&out->offload_cmd_list)) {
3590 item = list_head(&out->offload_cmd_list);
3591 list_remove(item);
3592 free(node_to_item(item, struct offload_cmd, node));
3593 }
3594 pthread_mutex_unlock(&out->lock);
3595
3596 return NULL;
3597}
3598
3599static int create_offload_callback_thread(struct stream_out *out)
3600{
3601 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3602 list_init(&out->offload_cmd_list);
3603 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3604 offload_thread_loop, out);
3605 return 0;
3606}
3607
3608static int destroy_offload_callback_thread(struct stream_out *out)
3609{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003610 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003611 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003612 stop_compressed_output_l(out);
3613 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3614
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003615 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003616 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)) {
4510 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004511 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004512 pthread_mutex_unlock(&out->latch_lock);
4513 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004514
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004515 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004517 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4518 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304519 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004520 pthread_mutex_unlock(&adev->lock);
4521 pthread_mutex_unlock(&out->lock);
4522 ALOGD("VOIP output entered standby");
4523 return 0;
4524 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 if (out->pcm) {
4526 pcm_close(out->pcm);
4527 out->pcm = NULL;
4528 }
Meng Wanga09da002020-04-20 12:56:04 +08004529 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4530 if (adev->haptic_pcm) {
4531 pcm_close(adev->haptic_pcm);
4532 adev->haptic_pcm = NULL;
4533 }
4534
4535 if (adev->haptic_buffer != NULL) {
4536 free(adev->haptic_buffer);
4537 adev->haptic_buffer = NULL;
4538 adev->haptic_buffer_size = 0;
4539 }
4540 adev->haptic_pcm_device_id = 0;
4541 }
4542
Haynes Mathew George16081042017-05-31 17:16:49 -07004543 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4544 do_stop = out->playback_started;
4545 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004546
4547 if (out->mmap_shared_memory_fd >= 0) {
4548 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4549 __func__, out->mmap_shared_memory_fd);
4550 close(out->mmap_shared_memory_fd);
4551 out->mmap_shared_memory_fd = -1;
4552 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004553 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004554 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004555 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304556 out->send_next_track_params = false;
4557 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004558 out->gapless_mdata.encoder_delay = 0;
4559 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004560 if (out->compr != NULL) {
4561 compress_close(out->compr);
4562 out->compr = NULL;
4563 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004564 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004565 if (do_stop) {
4566 stop_output_stream(out);
4567 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304568 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004569 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004570 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 }
4572 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304573 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574 return 0;
4575}
4576
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304577static int out_on_error(struct audio_stream *stream)
4578{
4579 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004580 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304581
4582 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004583 // always send CMD_ERROR for offload streams, this
4584 // is needed e.g. when SSR happens within compress_open
4585 // since the stream is active, offload_callback_thread is also active.
4586 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004587 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004588 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004589 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004590 }
4591 pthread_mutex_unlock(&out->lock);
4592
4593 status = out_standby(&out->stream.common);
4594
4595 lock_output_stream(out);
4596 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004597 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304598 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304599
4600 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4601 ALOGD("Setting previous card status if offline");
4602 out->prev_card_status_offline = true;
4603 }
4604
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304605 pthread_mutex_unlock(&out->lock);
4606
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004607 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304608}
4609
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304610/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004611 * standby implementation without locks, assumes that the callee already
4612 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304613 */
4614int out_standby_l(struct audio_stream *stream)
4615{
4616 struct stream_out *out = (struct stream_out *)stream;
4617 struct audio_device *adev = out->dev;
4618
4619 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4620 stream, out->usecase, use_case_table[out->usecase]);
4621
4622 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004623 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304624 if (adev->adm_deregister_stream)
4625 adev->adm_deregister_stream(adev->adm_data, out->handle);
4626
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004627 if (is_offload_usecase(out->usecase)) {
4628 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304629 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004630 pthread_mutex_unlock(&out->latch_lock);
4631 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304632
4633 out->standby = true;
4634 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4635 voice_extn_compress_voip_close_output_stream(stream);
4636 out->started = 0;
4637 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004638 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304639 return 0;
4640 } else if (!is_offload_usecase(out->usecase)) {
4641 if (out->pcm) {
4642 pcm_close(out->pcm);
4643 out->pcm = NULL;
4644 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004645 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4646 if (adev->haptic_pcm) {
4647 pcm_close(adev->haptic_pcm);
4648 adev->haptic_pcm = NULL;
4649 }
4650
4651 if (adev->haptic_buffer != NULL) {
4652 free(adev->haptic_buffer);
4653 adev->haptic_buffer = NULL;
4654 adev->haptic_buffer_size = 0;
4655 }
4656 adev->haptic_pcm_device_id = 0;
4657 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304658 } else {
4659 ALOGD("copl(%p):standby", out);
4660 out->send_next_track_params = false;
4661 out->is_compr_metadata_avail = false;
4662 out->gapless_mdata.encoder_delay = 0;
4663 out->gapless_mdata.encoder_padding = 0;
4664 if (out->compr != NULL) {
4665 compress_close(out->compr);
4666 out->compr = NULL;
4667 }
4668 }
4669 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004670 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304671 }
4672 ALOGD("%s: exit", __func__);
4673 return 0;
4674}
4675
Aalique Grahame22e49102018-12-18 14:23:57 -08004676static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677{
Aalique Grahame22e49102018-12-18 14:23:57 -08004678 struct stream_out *out = (struct stream_out *)stream;
4679
4680 // We try to get the lock for consistency,
4681 // but it isn't necessary for these variables.
4682 // If we're not in standby, we may be blocked on a write.
4683 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4684 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4685 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4686
Andy Hunga1f48fa2019-07-01 18:14:53 -07004687 char buffer[256]; // for statistics formatting
4688 if (!is_offload_usecase(out->usecase)) {
4689 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4690 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4691 }
4692
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004693 if (out->start_latency_ms.n > 0) {
4694 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4695 dprintf(fd, " Start latency ms: %s\n", buffer);
4696 }
4697
Aalique Grahame22e49102018-12-18 14:23:57 -08004698 if (locked) {
4699 pthread_mutex_unlock(&out->lock);
4700 }
4701
4702 // dump error info
4703 (void)error_log_dump(
4704 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 return 0;
4707}
4708
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004709static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4710{
4711 int ret = 0;
4712 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004713
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004714 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004715 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004716 return -EINVAL;
4717 }
4718
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304719 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004720
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004721 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4722 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304723 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004724 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004725 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4726 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304727 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004728 }
4729
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004730 ALOGV("%s new encoder delay %u and padding %u", __func__,
4731 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4732
4733 return 0;
4734}
4735
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004736static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4737{
4738 return out == adev->primary_output || out == adev->voice_tx_output;
4739}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004740
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304741// note: this call is safe only if the stream_cb is
4742// removed first in close_output_stream (as is done now).
4743static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4744{
4745 if (!stream || !parms)
4746 return;
4747
4748 struct stream_out *out = (struct stream_out *)stream;
4749 struct audio_device *adev = out->dev;
4750
4751 card_status_t status;
4752 int card;
4753 if (parse_snd_card_status(parms, &card, &status) < 0)
4754 return;
4755
4756 pthread_mutex_lock(&adev->lock);
4757 bool valid_cb = (card == adev->snd_card);
4758 pthread_mutex_unlock(&adev->lock);
4759
4760 if (!valid_cb)
4761 return;
4762
4763 lock_output_stream(out);
4764 if (out->card_status != status)
4765 out->card_status = status;
4766 pthread_mutex_unlock(&out->lock);
4767
4768 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4769 use_case_table[out->usecase],
4770 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4771
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304772 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304773 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304774 if (voice_is_call_state_active(adev) &&
4775 out == adev->primary_output) {
4776 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4777 pthread_mutex_lock(&adev->lock);
4778 voice_stop_call(adev);
4779 adev->mode = AUDIO_MODE_NORMAL;
4780 pthread_mutex_unlock(&adev->lock);
4781 }
4782 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304783 return;
4784}
4785
Kevin Rocardfce19002017-08-07 19:21:36 -07004786static int get_alive_usb_card(struct str_parms* parms) {
4787 int card;
4788 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4789 !audio_extn_usb_alive(card)) {
4790 return card;
4791 }
4792 return -ENODEV;
4793}
4794
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004795int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004796 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004797{
4798 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004799 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004800 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004801 bool bypass_a2dp = false;
4802 bool reconfig = false;
4803 unsigned long service_interval = 0;
4804
4805 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004806 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4807
4808 list_init(&new_devices);
4809 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004810
4811 lock_output_stream(out);
4812 pthread_mutex_lock(&adev->lock);
4813
4814 /*
4815 * When HDMI cable is unplugged the music playback is paused and
4816 * the policy manager sends routing=0. But the audioflinger continues
4817 * to write data until standby time (3sec). As the HDMI core is
4818 * turned off, the write gets blocked.
4819 * Avoid this by routing audio to speaker until standby.
4820 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004821 if (is_single_device_type_equal(&out->device_list,
4822 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004823 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004824 !audio_extn_passthru_is_passthrough_stream(out) &&
4825 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004826 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004827 }
4828 /*
4829 * When A2DP is disconnected the
4830 * music playback is paused and the policy manager sends routing=0
4831 * But the audioflinger continues to write data until standby time
4832 * (3sec). As BT is turned off, the write gets blocked.
4833 * Avoid this by routing audio to speaker until standby.
4834 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004835 if (is_a2dp_out_device_type(&out->device_list) &&
4836 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004837 !audio_extn_a2dp_source_is_ready() &&
4838 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004839 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004840 }
4841 /*
4842 * When USB headset is disconnected the music platback paused
4843 * and the policy manager send routing=0. But if the USB is connected
4844 * back before the standby time, AFE is not closed and opened
4845 * when USB is connected back. So routing to speker will guarantee
4846 * AFE reconfiguration and AFE will be opend once USB is connected again
4847 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004848 if (is_usb_out_device_type(&out->device_list) &&
4849 list_empty(&new_devices) &&
4850 !audio_extn_usb_connected(NULL)) {
4851 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4852 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004853 /* To avoid a2dp to sco overlapping / BT device improper state
4854 * check with BT lib about a2dp streaming support before routing
4855 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004856 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004858 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4859 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004860 //combo usecase just by pass a2dp
4861 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4862 bypass_a2dp = true;
4863 } else {
4864 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4865 /* update device to a2dp and don't route as BT returned error
4866 * However it is still possible a2dp routing called because
4867 * of current active device disconnection (like wired headset)
4868 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004869 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870 pthread_mutex_unlock(&adev->lock);
4871 pthread_mutex_unlock(&out->lock);
4872 goto error;
4873 }
4874 }
4875 }
4876
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004877 // Workaround: If routing to an non existing usb device, fail gracefully
4878 // The routing request will otherwise block during 10 second
4879 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004880 if (is_usb_out_device_type(&new_devices)) {
4881 struct str_parms *parms =
4882 str_parms_create_str(get_usb_device_address(&new_devices));
4883 if (!parms)
4884 goto error;
4885 if ((card = get_alive_usb_card(parms)) >= 0) {
4886 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4887 pthread_mutex_unlock(&adev->lock);
4888 pthread_mutex_unlock(&out->lock);
4889 str_parms_destroy(parms);
4890 ret = -ENOSYS;
4891 goto error;
4892 }
4893 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004894 }
4895
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004896 // Workaround: If routing to an non existing hdmi device, fail gracefully
4897 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4898 (platform_get_edid_info_v2(adev->platform,
4899 out->extconn.cs.controller,
4900 out->extconn.cs.stream) != 0)) {
4901 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4902 pthread_mutex_unlock(&adev->lock);
4903 pthread_mutex_unlock(&out->lock);
4904 ret = -ENOSYS;
4905 goto error;
4906 }
4907
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004908 /*
4909 * select_devices() call below switches all the usecases on the same
4910 * backend to the new device. Refer to check_usecases_codec_backend() in
4911 * the select_devices(). But how do we undo this?
4912 *
4913 * For example, music playback is active on headset (deep-buffer usecase)
4914 * and if we go to ringtones and select a ringtone, low-latency usecase
4915 * will be started on headset+speaker. As we can't enable headset+speaker
4916 * and headset devices at the same time, select_devices() switches the music
4917 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4918 * So when the ringtone playback is completed, how do we undo the same?
4919 *
4920 * We are relying on the out_set_parameters() call on deep-buffer output,
4921 * once the ringtone playback is ended.
4922 * NOTE: We should not check if the current devices are same as new devices.
4923 * Because select_devices() must be called to switch back the music
4924 * playback to headset.
4925 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004926 if (!list_empty(&new_devices)) {
4927 bool same_dev = compare_devices(&out->device_list, &new_devices);
4928 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004929
4930 if (output_drives_call(adev, out)) {
4931 if (!voice_is_call_state_active(adev)) {
4932 if (adev->mode == AUDIO_MODE_IN_CALL) {
4933 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004934 ret = voice_start_call(adev);
4935 }
4936 } else {
4937 adev->current_call_output = out;
4938 voice_update_devices_for_all_voice_usecases(adev);
4939 }
4940 }
4941
Mingshu Pang60536d72020-09-09 15:28:22 +08004942 if (is_usb_out_device_type(&out->device_list)) {
4943 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4944 audio_extn_usb_set_service_interval(true /*playback*/,
4945 service_interval,
4946 &reconfig);
4947 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4948 }
4949
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004950 if (!out->standby) {
4951 if (!same_dev) {
4952 ALOGV("update routing change");
4953 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4954 adev->perf_lock_opts,
4955 adev->perf_lock_opts_size);
4956 if (adev->adm_on_routing_change)
4957 adev->adm_on_routing_change(adev->adm_data,
4958 out->handle);
4959 }
4960 if (!bypass_a2dp) {
4961 select_devices(adev, out->usecase);
4962 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004963 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4964 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004965 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004966 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004967 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004968 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004969 }
4970
4971 if (!same_dev) {
4972 // on device switch force swap, lower functions will make sure
4973 // to check if swap is allowed or not.
4974 platform_set_swap_channels(adev, true);
4975 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4976 }
Zhou Song1f93fa52020-11-20 13:57:39 +08004977 pthread_mutex_lock(&out->latch_lock);
4978 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
4979 if (out->a2dp_muted) {
4980 out->a2dp_muted = false;
4981 if (is_offload_usecase(out->usecase))
4982 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4983 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
4984 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004985 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 }
Zhou Song1f93fa52020-11-20 13:57:39 +08004987 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
4988 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4989 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990 }
4991 }
4992
4993 pthread_mutex_unlock(&adev->lock);
4994 pthread_mutex_unlock(&out->lock);
4995
4996 /*handles device and call state changes*/
4997 audio_extn_extspk_update(adev->extspk);
4998
4999error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005000 ALOGV("%s: exit: code(%d)", __func__, ret);
5001 return ret;
5002}
5003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5005{
5006 struct stream_out *out = (struct stream_out *)stream;
5007 struct audio_device *adev = out->dev;
5008 struct str_parms *parms;
5009 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005010 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005011 int ext_controller = -1;
5012 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013
sangwoobc677242013-08-08 16:53:43 +09005014 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005015 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305017 if (!parms)
5018 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005019
5020 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5021 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005022 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005023 out->extconn.cs.controller = ext_controller;
5024 out->extconn.cs.stream = ext_stream;
5025 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5026 use_case_table[out->usecase], out->extconn.cs.controller,
5027 out->extconn.cs.stream);
5028 }
5029
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005030 if (out == adev->primary_output) {
5031 pthread_mutex_lock(&adev->lock);
5032 audio_extn_set_parameters(adev, parms);
5033 pthread_mutex_unlock(&adev->lock);
5034 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005035 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005036 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005037 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005038
5039 audio_extn_dts_create_state_notifier_node(out->usecase);
5040 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5041 popcount(out->channel_mask),
5042 out->playback_started);
5043
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005044 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005045 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005046
Surendar Karkaf51b5842018-04-26 11:28:38 +05305047 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5048 sizeof(value));
5049 if (err >= 0) {
5050 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5051 audio_extn_send_dual_mono_mixing_coefficients(out);
5052 }
5053
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305054 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5055 if (err >= 0) {
5056 strlcpy(out->profile, value, sizeof(out->profile));
5057 ALOGV("updating stream profile with value '%s'", out->profile);
5058 lock_output_stream(out);
5059 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5060 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005061 &out->device_list, out->flags,
5062 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305063 out->sample_rate, out->bit_width,
5064 out->channel_mask, out->profile,
5065 &out->app_type_cfg);
5066 pthread_mutex_unlock(&out->lock);
5067 }
5068
Alexy Joseph98988832017-01-13 14:56:59 -08005069 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005070 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5071 // and vendor.audio.hal.output.suspend.supported is set to true
5072 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005073 //check suspend parameter only for low latency and if the property
5074 //is enabled
5075 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5076 ALOGI("%s: got suspend_playback %s", __func__, value);
5077 lock_output_stream(out);
5078 if (!strncmp(value, "false", 5)) {
5079 //suspend_playback=false is supposed to set QOS value back to 75%
5080 //the mixer control sent with value Enable will achieve that
5081 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5082 } else if (!strncmp (value, "true", 4)) {
5083 //suspend_playback=true is supposed to remove QOS value
5084 //resetting the mixer control will set the default value
5085 //for the mixer control which is Disable and this removes the QOS vote
5086 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5087 } else {
5088 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5089 " got %s", __func__, value);
5090 ret = -1;
5091 }
5092
5093 if (ret != 0) {
5094 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5095 __func__, out->pm_qos_mixer_path, ret);
5096 }
5097
5098 pthread_mutex_unlock(&out->lock);
5099 }
5100 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005101
Alexy Joseph98988832017-01-13 14:56:59 -08005102 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305104error:
Eric Laurent994a6932013-07-17 11:51:42 -07005105 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005106 return ret;
5107}
5108
Paul McLeana50b7332018-12-17 08:24:21 -07005109static int in_set_microphone_direction(const struct audio_stream_in *stream,
5110 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005111 struct stream_in *in = (struct stream_in *)stream;
5112
5113 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5114
5115 in->direction = dir;
5116
5117 if (in->standby)
5118 return 0;
5119
5120 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005121}
5122
5123static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005124 struct stream_in *in = (struct stream_in *)stream;
5125
5126 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5127
5128 if (zoom > 1.0 || zoom < -1.0)
5129 return -EINVAL;
5130
5131 in->zoom = zoom;
5132
5133 if (in->standby)
5134 return 0;
5135
5136 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005137}
5138
5139
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005140static bool stream_get_parameter_channels(struct str_parms *query,
5141 struct str_parms *reply,
5142 audio_channel_mask_t *supported_channel_masks) {
5143 int ret = -1;
5144 char value[512];
5145 bool first = true;
5146 size_t i, j;
5147
5148 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5149 ret = 0;
5150 value[0] = '\0';
5151 i = 0;
5152 while (supported_channel_masks[i] != 0) {
5153 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5154 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5155 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305156 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005157
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305158 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005159 first = false;
5160 break;
5161 }
5162 }
5163 i++;
5164 }
5165 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5166 }
5167 return ret == 0;
5168}
5169
5170static bool stream_get_parameter_formats(struct str_parms *query,
5171 struct str_parms *reply,
5172 audio_format_t *supported_formats) {
5173 int ret = -1;
5174 char value[256];
5175 size_t i, j;
5176 bool first = true;
5177
5178 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5179 ret = 0;
5180 value[0] = '\0';
5181 i = 0;
5182 while (supported_formats[i] != 0) {
5183 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5184 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5185 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305186 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005187 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305188 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005189 first = false;
5190 break;
5191 }
5192 }
5193 i++;
5194 }
5195 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5196 }
5197 return ret == 0;
5198}
5199
5200static bool stream_get_parameter_rates(struct str_parms *query,
5201 struct str_parms *reply,
5202 uint32_t *supported_sample_rates) {
5203
5204 int i;
5205 char value[256];
5206 int ret = -1;
5207 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5208 ret = 0;
5209 value[0] = '\0';
5210 i=0;
5211 int cursor = 0;
5212 while (supported_sample_rates[i]) {
5213 int avail = sizeof(value) - cursor;
5214 ret = snprintf(value + cursor, avail, "%s%d",
5215 cursor > 0 ? "|" : "",
5216 supported_sample_rates[i]);
5217 if (ret < 0 || ret >= avail) {
5218 // if cursor is at the last element of the array
5219 // overwrite with \0 is duplicate work as
5220 // snprintf already put a \0 in place.
5221 // else
5222 // we had space to write the '|' at value[cursor]
5223 // (which will be overwritten) or no space to fill
5224 // the first element (=> cursor == 0)
5225 value[cursor] = '\0';
5226 break;
5227 }
5228 cursor += ret;
5229 ++i;
5230 }
5231 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5232 value);
5233 }
5234 return ret >= 0;
5235}
5236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005237static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5238{
5239 struct stream_out *out = (struct stream_out *)stream;
5240 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005241 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 char value[256];
5243 struct str_parms *reply = str_parms_create();
5244 size_t i, j;
5245 int ret;
5246 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005247
5248 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005249 if (reply) {
5250 str_parms_destroy(reply);
5251 }
5252 if (query) {
5253 str_parms_destroy(query);
5254 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005255 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5256 return NULL;
5257 }
5258
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005259 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5261 if (ret >= 0) {
5262 value[0] = '\0';
5263 i = 0;
5264 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005265 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5266 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005268 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005269 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005270 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 first = false;
5272 break;
5273 }
5274 }
5275 i++;
5276 }
5277 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5278 str = str_parms_to_str(reply);
5279 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005280 voice_extn_out_get_parameters(out, query, reply);
5281 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005282 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005283
Alexy Joseph62142aa2015-11-16 15:10:34 -08005284
5285 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5286 if (ret >= 0) {
5287 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305288 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5289 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005290 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305291 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005292 } else {
5293 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305294 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005295 }
5296 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005297 if (str)
5298 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005299 str = str_parms_to_str(reply);
5300 }
5301
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005302 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5303 if (ret >= 0) {
5304 value[0] = '\0';
5305 i = 0;
5306 first = true;
5307 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005308 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5309 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005310 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005311 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005312 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005313 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005314 first = false;
5315 break;
5316 }
5317 }
5318 i++;
5319 }
5320 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005321 if (str)
5322 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005323 str = str_parms_to_str(reply);
5324 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005325
5326 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5327 if (ret >= 0) {
5328 value[0] = '\0';
5329 i = 0;
5330 first = true;
5331 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005332 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5333 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005334 if (!first) {
5335 strlcat(value, "|", sizeof(value));
5336 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005337 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005338 first = false;
5339 break;
5340 }
5341 }
5342 i++;
5343 }
5344 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5345 if (str)
5346 free(str);
5347 str = str_parms_to_str(reply);
5348 }
5349
Alexy Joseph98988832017-01-13 14:56:59 -08005350 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5351 //only low latency track supports suspend_resume
5352 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005353 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005354 if (str)
5355 free(str);
5356 str = str_parms_to_str(reply);
5357 }
5358
5359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005360 str_parms_destroy(query);
5361 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005362 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363 return str;
5364}
5365
5366static uint32_t out_get_latency(const struct audio_stream_out *stream)
5367{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005368 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005370 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371
Alexy Josephaa54c872014-12-03 02:46:47 -08005372 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305373 lock_output_stream(out);
5374 latency = audio_extn_utils_compress_get_dsp_latency(out);
5375 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005376 } else if ((out->realtime) ||
5377 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005378 // since the buffer won't be filled up faster than realtime,
5379 // return a smaller number
5380 if (out->config.rate)
5381 period_ms = (out->af_period_multiplier * out->config.period_size *
5382 1000) / (out->config.rate);
5383 else
5384 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005385 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005386 } else {
5387 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005388 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005389 }
5390
Zhou Songd2537a02020-06-11 22:04:46 +08005391 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005392 latency += audio_extn_a2dp_get_encoder_latency();
5393
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305394 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005395 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005396}
5397
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305398static float AmpToDb(float amplification)
5399{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305400 float db = DSD_VOLUME_MIN_DB;
5401 if (amplification > 0) {
5402 db = 20 * log10(amplification);
5403 if(db < DSD_VOLUME_MIN_DB)
5404 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305405 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305406 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305407}
5408
Arun Mirpuri5d170872019-03-26 13:21:31 -07005409static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5410 float right)
5411{
5412 struct stream_out *out = (struct stream_out *)stream;
5413 long volume = 0;
5414 char mixer_ctl_name[128] = "";
5415 struct audio_device *adev = out->dev;
5416 struct mixer_ctl *ctl = NULL;
5417 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5418 PCM_PLAYBACK);
5419
5420 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5421 "Playback %d Volume", pcm_device_id);
5422 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5423 if (!ctl) {
5424 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5425 __func__, mixer_ctl_name);
5426 return -EINVAL;
5427 }
5428 if (left != right)
5429 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5430 __func__, left, right);
5431 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5432 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5433 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5434 __func__, mixer_ctl_name, volume);
5435 return -EINVAL;
5436 }
5437 return 0;
5438}
5439
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305440static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5441 float right)
5442{
5443 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305444 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305445 char mixer_ctl_name[128];
5446 struct audio_device *adev = out->dev;
5447 struct mixer_ctl *ctl;
5448 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5449 PCM_PLAYBACK);
5450
5451 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5452 "Compress Playback %d Volume", pcm_device_id);
5453 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5454 if (!ctl) {
5455 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5456 __func__, mixer_ctl_name);
5457 return -EINVAL;
5458 }
5459 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5460 __func__, mixer_ctl_name, left, right);
5461 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5462 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5463 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5464
5465 return 0;
5466}
5467
Zhou Song2b8f28f2017-09-11 10:51:38 +08005468static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5469 float right)
5470{
5471 struct stream_out *out = (struct stream_out *)stream;
5472 char mixer_ctl_name[] = "App Type Gain";
5473 struct audio_device *adev = out->dev;
5474 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305475 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005476
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005477 if (!is_valid_volume(left, right)) {
5478 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5479 __func__, left, right);
5480 return -EINVAL;
5481 }
5482
Zhou Song2b8f28f2017-09-11 10:51:38 +08005483 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5484 if (!ctl) {
5485 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5486 __func__, mixer_ctl_name);
5487 return -EINVAL;
5488 }
5489
5490 set_values[0] = 0; //0: Rx Session 1:Tx Session
5491 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305492 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5493 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005494
5495 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5496 return 0;
5497}
5498
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305499static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5500 float right)
5501{
5502 struct stream_out *out = (struct stream_out *)stream;
5503 /* Volume control for pcm playback */
5504 if (left != right) {
5505 return -EINVAL;
5506 } else {
5507 char mixer_ctl_name[128];
5508 struct audio_device *adev = out->dev;
5509 struct mixer_ctl *ctl;
5510 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5511 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5512 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5513 if (!ctl) {
5514 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5515 return -EINVAL;
5516 }
5517
5518 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5519 int ret = mixer_ctl_set_value(ctl, 0, volume);
5520 if (ret < 0) {
5521 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5522 return -EINVAL;
5523 }
5524
5525 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5526
5527 return 0;
5528 }
5529}
5530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531static int out_set_volume(struct audio_stream_out *stream, float left,
5532 float right)
5533{
Eric Laurenta9024de2013-04-04 09:19:12 -07005534 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005535 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305536 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005537
Arun Mirpuri5d170872019-03-26 13:21:31 -07005538 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005539 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5540 /* only take left channel into account: the API is for stereo anyway */
5541 out->muted = (left == 0.0f);
5542 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005543 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305544 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005545 /*
5546 * Set mute or umute on HDMI passthrough stream.
5547 * Only take left channel into account.
5548 * Mute is 0 and unmute 1
5549 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305550 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305551 } else if (out->format == AUDIO_FORMAT_DSD){
5552 char mixer_ctl_name[128] = "DSD Volume";
5553 struct audio_device *adev = out->dev;
5554 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5555
5556 if (!ctl) {
5557 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5558 __func__, mixer_ctl_name);
5559 return -EINVAL;
5560 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305561 volume[0] = (long)(AmpToDb(left));
5562 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305563 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5564 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005565 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005566 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005567 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5568 struct listnode *node = NULL;
5569 list_for_each(node, &adev->active_outputs_list) {
5570 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5571 streams_output_ctxt_t,
5572 list);
5573 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5574 out->volume_l = out_ctxt->output->volume_l;
5575 out->volume_r = out_ctxt->output->volume_r;
5576 }
5577 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005578 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005579 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005580 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5581 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005582 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005583 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005584 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005585 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005586 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5587 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305588 ret = out_set_compr_volume(stream, left, right);
5589 out->volume_l = left;
5590 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005591 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305592 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005593 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005594 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005595 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5596 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song1f93fa52020-11-20 13:57:39 +08005597 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005598 if (!out->standby) {
5599 audio_extn_utils_send_app_type_gain(out->dev,
5600 out->app_type_cfg.app_type,
5601 &out->app_type_cfg.gain[0]);
Zhou Song1f93fa52020-11-20 13:57:39 +08005602 if (!out->a2dp_muted)
5603 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005604 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005605 out->volume_l = left;
5606 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005607 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005608 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005609 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5610 ALOGV("%s: MMAP set volume called", __func__);
5611 if (!out->standby)
5612 ret = out_set_mmap_volume(stream, left, right);
5613 out->volume_l = left;
5614 out->volume_r = right;
5615 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305616 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305617 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5618 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Song1f93fa52020-11-20 13:57:39 +08005619 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305620 /* Volume control for pcm playback */
Zhou Song1f93fa52020-11-20 13:57:39 +08005621 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305622 ret = out_set_pcm_volume(stream, left, right);
5623 else
5624 out->apply_volume = true;
5625
5626 out->volume_l = left;
5627 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005628 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305629 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005630 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5631 ALOGV("%s: bus device set volume called", __func__);
Zhou Song1f93fa52020-11-20 13:57:39 +08005632 pthread_mutex_lock(&out->latch_lock);
5633 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005634 ret = out_set_pcm_volume(stream, left, right);
5635 out->volume_l = left;
5636 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005637 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005638 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005639 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641 return -ENOSYS;
5642}
5643
Zhou Songc9672822017-08-16 16:01:39 +08005644static void update_frames_written(struct stream_out *out, size_t bytes)
5645{
5646 size_t bpf = 0;
5647
5648 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5649 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5650 bpf = 1;
5651 else if (!is_offload_usecase(out->usecase))
5652 bpf = audio_bytes_per_sample(out->format) *
5653 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005654
5655 pthread_mutex_lock(&out->position_query_lock);
5656 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005657 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005658 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5659 }
5660 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005661}
5662
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005663int split_and_write_audio_haptic_data(struct stream_out *out,
5664 const void *buffer, size_t bytes_to_write)
5665{
5666 struct audio_device *adev = out->dev;
5667
5668 int ret = 0;
5669 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5670 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5671 size_t frame_size = channel_count * bytes_per_sample;
5672 size_t frame_count = bytes_to_write / frame_size;
5673
5674 bool force_haptic_path =
5675 property_get_bool("vendor.audio.test_haptic", false);
5676
5677 // extract Haptics data from Audio buffer
5678 bool alloc_haptic_buffer = false;
5679 int haptic_channel_count = adev->haptics_config.channels;
5680 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5681 size_t audio_frame_size = frame_size - haptic_frame_size;
5682 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5683
5684 if (adev->haptic_buffer == NULL) {
5685 alloc_haptic_buffer = true;
5686 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5687 free(adev->haptic_buffer);
5688 adev->haptic_buffer_size = 0;
5689 alloc_haptic_buffer = true;
5690 }
5691
5692 if (alloc_haptic_buffer) {
5693 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005694 if(adev->haptic_buffer == NULL) {
5695 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5696 return -ENOMEM;
5697 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005698 adev->haptic_buffer_size = total_haptic_buffer_size;
5699 }
5700
5701 size_t src_index = 0, aud_index = 0, hap_index = 0;
5702 uint8_t *audio_buffer = (uint8_t *)buffer;
5703 uint8_t *haptic_buffer = adev->haptic_buffer;
5704
5705 // This is required for testing only. This works for stereo data only.
5706 // One channel is fed to audio stream and other to haptic stream for testing.
5707 if (force_haptic_path)
5708 audio_frame_size = haptic_frame_size = bytes_per_sample;
5709
5710 for (size_t i = 0; i < frame_count; i++) {
5711 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5712 audio_frame_size);
5713 aud_index += audio_frame_size;
5714 src_index += audio_frame_size;
5715
5716 if (adev->haptic_pcm)
5717 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5718 haptic_frame_size);
5719 hap_index += haptic_frame_size;
5720 src_index += haptic_frame_size;
5721
5722 // This is required for testing only.
5723 // Discard haptic channel data.
5724 if (force_haptic_path)
5725 src_index += haptic_frame_size;
5726 }
5727
5728 // write to audio pipeline
5729 ret = pcm_write(out->pcm, (void *)audio_buffer,
5730 frame_count * audio_frame_size);
5731
5732 // write to haptics pipeline
5733 if (adev->haptic_pcm)
5734 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5735 frame_count * haptic_frame_size);
5736
5737 return ret;
5738}
5739
Aalique Grahame22e49102018-12-18 14:23:57 -08005740#ifdef NO_AUDIO_OUT
5741static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5742 const void *buffer __unused, size_t bytes)
5743{
5744 struct stream_out *out = (struct stream_out *)stream;
5745
5746 /* No Output device supported other than BT for playback.
5747 * Sleep for the amount of buffer duration
5748 */
5749 lock_output_stream(out);
5750 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5751 (const struct audio_stream_out *)&out->stream) /
5752 out_get_sample_rate(&out->stream.common));
5753 pthread_mutex_unlock(&out->lock);
5754 return bytes;
5755}
5756#endif
5757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005758static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5759 size_t bytes)
5760{
5761 struct stream_out *out = (struct stream_out *)stream;
5762 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005763 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305764 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005765 const size_t frame_size = audio_stream_out_frame_size(stream);
5766 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305767 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005768 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005769
Haynes Mathew George380745d2017-10-04 15:27:45 -07005770 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005771 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305772
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305773 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005774
Dhananjay Kumarac341582017-02-23 23:42:25 +05305775 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305776 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305777 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5778 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005779 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305780 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305781 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305782 ALOGD(" %s: sound card is not active/SSR state", __func__);
5783 ret= -EIO;
5784 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305785 }
5786 }
5787
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305788 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305789 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305790 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305791 goto exit;
5792 }
5793
Haynes Mathew George16081042017-05-31 17:16:49 -07005794 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5795 ret = -EINVAL;
5796 goto exit;
5797 }
5798
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005799 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305800 !out->is_iec61937_info_available) {
5801
5802 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5803 out->is_iec61937_info_available = true;
5804 } else if (audio_extn_passthru_is_enabled()) {
5805 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305806 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305807
5808 if((out->format == AUDIO_FORMAT_DTS) ||
5809 (out->format == AUDIO_FORMAT_DTS_HD)) {
5810 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5811 buffer, bytes);
5812 if (ret) {
5813 if (ret != -ENOSYS) {
5814 out->is_iec61937_info_available = false;
5815 ALOGD("iec61937 transmission info not yet updated retry");
5816 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305817 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305818 /* if stream has started and after that there is
5819 * stream config change (iec transmission config)
5820 * then trigger select_device to update backend configuration.
5821 */
5822 out->stream_config_changed = true;
5823 pthread_mutex_lock(&adev->lock);
5824 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305825 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005826 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305827 ret = -EINVAL;
5828 goto exit;
5829 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305830 pthread_mutex_unlock(&adev->lock);
5831 out->stream_config_changed = false;
5832 out->is_iec61937_info_available = true;
5833 }
5834 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305835
Meng Wang4c32fb42020-01-16 17:57:11 +08005836#ifdef AUDIO_GKI_ENABLED
5837 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5838 compr_passthr = out->compr_config.codec->reserved[0];
5839#else
5840 compr_passthr = out->compr_config.codec->compr_passthr;
5841#endif
5842
Garmond Leung317cbf12017-09-13 16:20:50 -07005843 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005844 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305845 (out->is_iec61937_info_available == true)) {
5846 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5847 ret = -EINVAL;
5848 goto exit;
5849 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305850 }
5851 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305852
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005853 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005854 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005855 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5856 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Song9ebf6792020-09-23 22:49:01 +08005857 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305858 ret = -EIO;
5859 goto exit;
5860 }
5861 }
5862 }
5863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005864 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005865 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005866 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5867
Eric Laurent150dbfe2013-02-27 14:31:02 -08005868 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005869 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5870 ret = voice_extn_compress_voip_start_output_stream(out);
5871 else
5872 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005873 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005874 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005875 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005876 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005877 goto exit;
5878 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305879 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005880 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005881
5882 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005883 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005884 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305885 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005886 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005887 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305888
5889 if ((out->is_iec61937_info_available == true) &&
5890 (audio_extn_passthru_is_passthrough_stream(out))&&
5891 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5892 ret = -EINVAL;
5893 goto exit;
5894 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305895 if (out->set_dual_mono)
5896 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005897
5898 // log startup time in ms.
5899 simple_stats_log(
5900 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005901 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005902
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005903 if (adev->is_channel_status_set == false &&
5904 compare_device_type(&out->device_list,
5905 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005906 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305907 adev->is_channel_status_set = true;
5908 }
5909
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305910 if ((adev->use_old_pspd_mix_ctrl == true) &&
5911 (out->pspd_coeff_sent == false)) {
5912 /*
5913 * Need to resend pspd coefficients after stream started for
5914 * older kernel version as it does not save the coefficients
5915 * and also stream has to be started for coeff to apply.
5916 */
5917 usecase = get_usecase_from_list(adev, out->usecase);
5918 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305919 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305920 out->pspd_coeff_sent = true;
5921 }
5922 }
5923
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005924 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005925 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005926 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005927 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005928 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5929 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305930 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5931 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005932 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305933 out->send_next_track_params = false;
5934 out->is_compr_metadata_avail = false;
5935 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005936 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305937 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305938 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005939
Ashish Jain83a6cc22016-06-28 14:34:17 +05305940 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305941 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305942 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305943 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005944 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305945 return -EINVAL;
5946 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305947 audio_format_t dst_format = out->hal_op_format;
5948 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305949
Dieter Luecking5d57def2018-09-07 14:23:37 +02005950 /* prevent division-by-zero */
5951 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5952 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5953 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5954 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305955 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005956 ATRACE_END();
5957 return -EINVAL;
5958 }
5959
Ashish Jainf1eaa582016-05-23 20:54:24 +05305960 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5961 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5962
Ashish Jain83a6cc22016-06-28 14:34:17 +05305963 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305964 dst_format,
5965 buffer,
5966 src_format,
5967 frames);
5968
Ashish Jain83a6cc22016-06-28 14:34:17 +05305969 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305970 bytes_to_write);
5971
5972 /*Convert written bytes in audio flinger format*/
5973 if (ret > 0)
5974 ret = ((ret * format_to_bitwidth_table[out->format]) /
5975 format_to_bitwidth_table[dst_format]);
5976 }
5977 } else
5978 ret = compress_write(out->compr, buffer, bytes);
5979
Zhou Songc9672822017-08-16 16:01:39 +08005980 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5981 update_frames_written(out, bytes);
5982
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305983 if (ret < 0)
5984 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005985 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305986 /*msg to cb thread only if non blocking write is enabled*/
5987 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305988 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005989 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305990 } else if (-ENETRESET == ret) {
5991 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305992 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305993 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305994 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005995 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305996 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005997 }
Ashish Jain5106d362016-05-11 19:23:33 +05305998
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305999 /* Call compr start only when non-zero bytes of data is there to be rendered */
6000 if (!out->playback_started && ret > 0) {
6001 int status = compress_start(out->compr);
6002 if (status < 0) {
6003 ret = status;
6004 ALOGE("%s: compr start failed with err %d", __func__, errno);
6005 goto exit;
6006 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006007 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006009 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006010 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006011 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006012
6013 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6014 popcount(out->channel_mask),
6015 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006016 }
6017 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006018 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006019 return ret;
6020 } else {
6021 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006022 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006023 if (out->muted)
6024 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006025 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6026 __func__, frames, frame_size, bytes_to_write);
6027
Aalique Grahame22e49102018-12-18 14:23:57 -08006028 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006029 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6030 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6031 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006032 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6033 int16_t *src = (int16_t *)buffer;
6034 int16_t *dst = (int16_t *)buffer;
6035
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006036 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006037 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006038 "out_write called for %s use case with wrong properties",
6039 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006040
6041 /*
6042 * FIXME: this can be removed once audio flinger mixer supports
6043 * mono output
6044 */
6045
6046 /*
6047 * Code below goes over each frame in the buffer and adds both
6048 * L and R samples and then divides by 2 to convert to mono
6049 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006050 if (channel_count == 2) {
6051 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6052 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6053 }
6054 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006055 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006056 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006057
6058 // Note: since out_get_presentation_position() is called alternating with out_write()
6059 // by AudioFlinger, we can check underruns using the prior timestamp read.
6060 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6061 if (out->last_fifo_valid) {
6062 // compute drain to see if there is an underrun.
6063 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306064 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6065 int64_t frames_by_time =
6066 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6067 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006068 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6069
6070 if (underrun > 0) {
6071 simple_stats_log(&out->fifo_underruns, underrun);
6072
6073 ALOGW("%s: underrun(%lld) "
6074 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6075 __func__,
6076 (long long)out->fifo_underruns.n,
6077 (long long)frames_by_time,
6078 (long long)out->last_fifo_frames_remaining);
6079 }
6080 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6081 }
6082
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306083 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006084
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006085 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006086
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006087 if (out->config.rate)
6088 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6089 out->config.rate;
6090
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006091 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006092 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6093
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006094 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006095 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006096 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306097 out->convert_buffer != NULL) {
6098
6099 memcpy_by_audio_format(out->convert_buffer,
6100 out->hal_op_format,
6101 buffer,
6102 out->hal_ip_format,
6103 out->config.period_size * out->config.channels);
6104
6105 ret = pcm_write(out->pcm, out->convert_buffer,
6106 (out->config.period_size *
6107 out->config.channels *
6108 format_to_bitwidth_table[out->hal_op_format]));
6109 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306110 /*
6111 * To avoid underrun in DSP when the application is not pumping
6112 * data at required rate, check for the no. of bytes and ignore
6113 * pcm_write if it is less than actual buffer size.
6114 * It is a work around to a change in compress VOIP driver.
6115 */
6116 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6117 bytes < (out->config.period_size * out->config.channels *
6118 audio_bytes_per_sample(out->format))) {
6119 size_t voip_buf_size =
6120 out->config.period_size * out->config.channels *
6121 audio_bytes_per_sample(out->format);
6122 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6123 __func__, bytes, voip_buf_size);
6124 usleep(((uint64_t)voip_buf_size - bytes) *
6125 1000000 / audio_stream_out_frame_size(stream) /
6126 out_get_sample_rate(&out->stream.common));
6127 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006128 } else {
6129 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6130 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6131 else
6132 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6133 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306134 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006135
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006136 release_out_focus(out);
6137
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306138 if (ret < 0)
6139 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006140 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306141 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006143 }
6144
6145exit:
Zhou Songc9672822017-08-16 16:01:39 +08006146 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306147 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306148 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150 pthread_mutex_unlock(&out->lock);
6151
6152 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006153 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006154 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306155 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306156 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306157 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306158 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306159 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306160 out->standby = true;
6161 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306162 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006163 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6164 /* prevent division-by-zero */
6165 uint32_t stream_size = audio_stream_out_frame_size(stream);
6166 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006167
Dieter Luecking5d57def2018-09-07 14:23:37 +02006168 if ((stream_size == 0) || (srate == 0)) {
6169 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6170 ATRACE_END();
6171 return -EINVAL;
6172 }
6173 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6174 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006175 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306176 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006177 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006178 return ret;
6179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006180 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006181 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006182 return bytes;
6183}
6184
6185static int out_get_render_position(const struct audio_stream_out *stream,
6186 uint32_t *dsp_frames)
6187{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006188 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006189
6190 if (dsp_frames == NULL)
6191 return -EINVAL;
6192
6193 *dsp_frames = 0;
6194 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006195 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306196
6197 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6198 * this operation and adev_close_output_stream(where out gets reset).
6199 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306200 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006201 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306202 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006203 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306204 return 0;
6205 }
6206
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006207 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306208 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306209 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006210 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306211 if (ret < 0)
6212 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006213 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306214 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006215 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306216 if (-ENETRESET == ret) {
6217 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306218 out->card_status = CARD_STATUS_OFFLINE;
6219 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306220 } else if(ret < 0) {
6221 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306222 ret = -EINVAL;
6223 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306224 /*
6225 * Handle corner case where compress session is closed during SSR
6226 * and timestamp is queried
6227 */
6228 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306229 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306230 } else if (out->prev_card_status_offline) {
6231 ALOGE("ERROR: previously sound card was offline,return error");
6232 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306233 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306234 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006235 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306236 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306237 pthread_mutex_unlock(&out->lock);
6238 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006239 } else if (audio_is_linear_pcm(out->format)) {
6240 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006241 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006242 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006243 } else
6244 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006245}
6246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006247static int out_add_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_remove_audio_effect(const struct audio_stream *stream __unused,
6254 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255{
6256 return 0;
6257}
6258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006259static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6260 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306262 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263}
6264
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006265static int out_get_presentation_position(const struct audio_stream_out *stream,
6266 uint64_t *frames, struct timespec *timestamp)
6267{
6268 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306269 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006270 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006271
Ashish Jain5106d362016-05-11 19:23:33 +05306272 /* below piece of code is not guarded against any lock because audioFliner serializes
6273 * this operation and adev_close_output_stream( where out gets reset).
6274 */
6275 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306276 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006277 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306278 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6279 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6280 return 0;
6281 }
6282
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006283 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006284
Ashish Jain5106d362016-05-11 19:23:33 +05306285 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6286 ret = compress_get_tstamp(out->compr, &dsp_frames,
6287 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006288 // Adjustment accounts for A2dp encoder latency with offload usecases
6289 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006290 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006291 unsigned long offset =
6292 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6293 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6294 }
Ashish Jain5106d362016-05-11 19:23:33 +05306295 ALOGVV("%s rendered frames %ld sample_rate %d",
6296 __func__, dsp_frames, out->sample_rate);
6297 *frames = dsp_frames;
6298 if (ret < 0)
6299 ret = -errno;
6300 if (-ENETRESET == ret) {
6301 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306302 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306303 ret = -EINVAL;
6304 } else
6305 ret = 0;
6306 /* this is the best we can do */
6307 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006308 } else {
6309 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006310 unsigned int avail;
6311 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006312 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006313 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006314
Andy Hunga1f48fa2019-07-01 18:14:53 -07006315 if (out->kernel_buffer_size > avail) {
6316 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6317 } else {
6318 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6319 __func__, avail, out->kernel_buffer_size);
6320 avail = out->kernel_buffer_size;
6321 frames_temp = out->last_fifo_frames_remaining = 0;
6322 }
6323 out->last_fifo_valid = true;
6324 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6325
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006326 if (out->written >= frames_temp)
6327 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006328
Andy Hunga1f48fa2019-07-01 18:14:53 -07006329 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6330 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6331
Weiyin Jiangd4633762018-03-16 12:05:03 +08006332 // This adjustment accounts for buffering after app processor.
6333 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006334 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006335 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006336 if (signed_frames >= frames_temp)
6337 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006338
Weiyin Jiangd4633762018-03-16 12:05:03 +08006339 // Adjustment accounts for A2dp encoder latency with non offload usecases
6340 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006341 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006342 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6343 if (signed_frames >= frames_temp)
6344 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006345 }
6346
6347 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006348 *frames = signed_frames;
6349 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006350 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006351 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6352 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006353 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306354 *frames = out->written;
6355 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306356 if (is_offload_usecase(out->usecase))
6357 ret = -EINVAL;
6358 else
6359 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006360 }
6361 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006362 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006363 return ret;
6364}
6365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006366static int out_set_callback(struct audio_stream_out *stream,
6367 stream_callback_t callback, void *cookie)
6368{
6369 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006370 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006371
6372 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006373 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006374 out->client_callback = callback;
6375 out->client_cookie = cookie;
6376 if (out->adsp_hdlr_stream_handle) {
6377 ret = audio_extn_adsp_hdlr_stream_set_callback(
6378 out->adsp_hdlr_stream_handle,
6379 callback,
6380 cookie);
6381 if (ret)
6382 ALOGW("%s:adsp hdlr callback registration failed %d",
6383 __func__, ret);
6384 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006385 pthread_mutex_unlock(&out->lock);
6386 return 0;
6387}
6388
6389static int out_pause(struct audio_stream_out* stream)
6390{
6391 struct stream_out *out = (struct stream_out *)stream;
6392 int status = -ENOSYS;
6393 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006394 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006395 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306396 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006397 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006398 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006399 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306400 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306401 status = compress_pause(out->compr);
6402
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006404
Mingming Yin21854652016-04-13 11:54:02 -07006405 if (audio_extn_passthru_is_active()) {
6406 ALOGV("offload use case, pause passthru");
6407 audio_extn_passthru_on_pause(out);
6408 }
6409
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306410 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006411 audio_extn_dts_notify_playback_state(out->usecase, 0,
6412 out->sample_rate, popcount(out->channel_mask),
6413 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006414 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006415 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006416 pthread_mutex_unlock(&out->lock);
6417 }
6418 return status;
6419}
6420
6421static int out_resume(struct audio_stream_out* stream)
6422{
6423 struct stream_out *out = (struct stream_out *)stream;
6424 int status = -ENOSYS;
6425 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006426 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006427 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306428 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006429 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006430 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006431 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306432 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306433 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006434 }
6435 if (!status) {
6436 out->offload_state = OFFLOAD_STATE_PLAYING;
6437 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306438 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006439 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6440 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006441 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006442 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006443 pthread_mutex_unlock(&out->lock);
6444 }
6445 return status;
6446}
6447
6448static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6449{
6450 struct stream_out *out = (struct stream_out *)stream;
6451 int status = -ENOSYS;
6452 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006453 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6456 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6457 else
6458 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6459 pthread_mutex_unlock(&out->lock);
6460 }
6461 return status;
6462}
6463
6464static int out_flush(struct audio_stream_out* stream)
6465{
6466 struct stream_out *out = (struct stream_out *)stream;
6467 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006468 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006469 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006470 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006471 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006472 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6473 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006474 } else {
6475 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6476 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006477 out->written = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006478 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006479 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006480 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006481 return 0;
6482 }
6483 return -ENOSYS;
6484}
6485
Haynes Mathew George16081042017-05-31 17:16:49 -07006486static int out_stop(const struct audio_stream_out* stream)
6487{
6488 struct stream_out *out = (struct stream_out *)stream;
6489 struct audio_device *adev = out->dev;
6490 int ret = -ENOSYS;
6491
6492 ALOGV("%s", __func__);
6493 pthread_mutex_lock(&adev->lock);
6494 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6495 out->playback_started && out->pcm != NULL) {
6496 pcm_stop(out->pcm);
6497 ret = stop_output_stream(out);
6498 out->playback_started = false;
6499 }
6500 pthread_mutex_unlock(&adev->lock);
6501 return ret;
6502}
6503
6504static int out_start(const struct audio_stream_out* stream)
6505{
6506 struct stream_out *out = (struct stream_out *)stream;
6507 struct audio_device *adev = out->dev;
6508 int ret = -ENOSYS;
6509
6510 ALOGV("%s", __func__);
6511 pthread_mutex_lock(&adev->lock);
6512 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6513 !out->playback_started && out->pcm != NULL) {
6514 ret = start_output_stream(out);
6515 if (ret == 0) {
6516 out->playback_started = true;
6517 }
6518 }
6519 pthread_mutex_unlock(&adev->lock);
6520 return ret;
6521}
6522
6523/*
6524 * Modify config->period_count based on min_size_frames
6525 */
6526static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6527{
6528 int periodCountRequested = (min_size_frames + config->period_size - 1)
6529 / config->period_size;
6530 int periodCount = MMAP_PERIOD_COUNT_MIN;
6531
6532 ALOGV("%s original config.period_size = %d config.period_count = %d",
6533 __func__, config->period_size, config->period_count);
6534
6535 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6536 periodCount *= 2;
6537 }
6538 config->period_count = periodCount;
6539
6540 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6541}
6542
Phil Burkfe17efd2019-03-25 10:23:35 -07006543// Read offset for the positional timestamp from a persistent vendor property.
6544// This is to workaround apparent inaccuracies in the timing information that
6545// is used by the AAudio timing model. The inaccuracies can cause glitches.
6546static int64_t get_mmap_out_time_offset() {
6547 const int32_t kDefaultOffsetMicros = 0;
6548 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006549 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006550 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6551 return mmap_time_offset_micros * (int64_t)1000;
6552}
6553
Haynes Mathew George16081042017-05-31 17:16:49 -07006554static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6555 int32_t min_size_frames,
6556 struct audio_mmap_buffer_info *info)
6557{
6558 struct stream_out *out = (struct stream_out *)stream;
6559 struct audio_device *adev = out->dev;
6560 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006561 unsigned int offset1 = 0;
6562 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006563 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006564 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006565 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006566
Arun Mirpuri5d170872019-03-26 13:21:31 -07006567 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306568 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006569 pthread_mutex_lock(&adev->lock);
6570
Sharad Sanglec6f32552018-05-04 16:15:38 +05306571 if (CARD_STATUS_OFFLINE == out->card_status ||
6572 CARD_STATUS_OFFLINE == adev->card_status) {
6573 ALOGW("out->card_status or adev->card_status offline, try again");
6574 ret = -EIO;
6575 goto exit;
6576 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306577 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006578 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6579 ret = -EINVAL;
6580 goto exit;
6581 }
6582 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6583 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6584 ret = -ENOSYS;
6585 goto exit;
6586 }
6587 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6588 if (out->pcm_device_id < 0) {
6589 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6590 __func__, out->pcm_device_id, out->usecase);
6591 ret = -EINVAL;
6592 goto exit;
6593 }
6594
6595 adjust_mmap_period_count(&out->config, min_size_frames);
6596
Arun Mirpuri5d170872019-03-26 13:21:31 -07006597 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006598 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6599 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6600 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306601 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306602 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6603 out->card_status = CARD_STATUS_OFFLINE;
6604 adev->card_status = CARD_STATUS_OFFLINE;
6605 ret = -EIO;
6606 goto exit;
6607 }
6608
Haynes Mathew George16081042017-05-31 17:16:49 -07006609 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6610 step = "open";
6611 ret = -ENODEV;
6612 goto exit;
6613 }
6614 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6615 if (ret < 0) {
6616 step = "begin";
6617 goto exit;
6618 }
juyuchen626833d2019-06-04 16:48:02 +08006619
6620 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006621 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006622 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006623 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006624 ret = platform_get_mmap_data_fd(adev->platform,
6625 out->pcm_device_id, 0 /*playback*/,
6626 &info->shared_memory_fd,
6627 &mmap_size);
6628 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006629 // Fall back to non exclusive mode
6630 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6631 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006632 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6633 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6634
Arun Mirpuri5d170872019-03-26 13:21:31 -07006635 if (mmap_size < buffer_size) {
6636 step = "mmap";
6637 goto exit;
6638 }
juyuchen626833d2019-06-04 16:48:02 +08006639 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006640 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006641 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006642 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006643
6644 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6645 if (ret < 0) {
6646 step = "commit";
6647 goto exit;
6648 }
6649
Phil Burkfe17efd2019-03-25 10:23:35 -07006650 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6651
Haynes Mathew George16081042017-05-31 17:16:49 -07006652 out->standby = false;
6653 ret = 0;
6654
Arun Mirpuri5d170872019-03-26 13:21:31 -07006655 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006656 __func__, info->shared_memory_address, info->buffer_size_frames);
6657
6658exit:
6659 if (ret != 0) {
6660 if (out->pcm == NULL) {
6661 ALOGE("%s: %s - %d", __func__, step, ret);
6662 } else {
6663 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6664 pcm_close(out->pcm);
6665 out->pcm = NULL;
6666 }
6667 }
6668 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306669 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006670 return ret;
6671}
6672
6673static int out_get_mmap_position(const struct audio_stream_out *stream,
6674 struct audio_mmap_position *position)
6675{
6676 struct stream_out *out = (struct stream_out *)stream;
6677 ALOGVV("%s", __func__);
6678 if (position == NULL) {
6679 return -EINVAL;
6680 }
6681 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006682 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006683 return -ENOSYS;
6684 }
6685 if (out->pcm == NULL) {
6686 return -ENOSYS;
6687 }
6688
6689 struct timespec ts = { 0, 0 };
6690 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6691 if (ret < 0) {
6692 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6693 return ret;
6694 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006695 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6696 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006697 return 0;
6698}
6699
6700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701/** audio_stream_in implementation **/
6702static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6703{
6704 struct stream_in *in = (struct stream_in *)stream;
6705
6706 return in->config.rate;
6707}
6708
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006709static int in_set_sample_rate(struct audio_stream *stream __unused,
6710 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711{
6712 return -ENOSYS;
6713}
6714
6715static size_t in_get_buffer_size(const struct audio_stream *stream)
6716{
6717 struct stream_in *in = (struct stream_in *)stream;
6718
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006719 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6720 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006721 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6722 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306723 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306724 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006725
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006726 return in->config.period_size * in->af_period_multiplier *
6727 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728}
6729
6730static uint32_t in_get_channels(const struct audio_stream *stream)
6731{
6732 struct stream_in *in = (struct stream_in *)stream;
6733
6734 return in->channel_mask;
6735}
6736
6737static audio_format_t in_get_format(const struct audio_stream *stream)
6738{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006739 struct stream_in *in = (struct stream_in *)stream;
6740
6741 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006742}
6743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006744static int in_set_format(struct audio_stream *stream __unused,
6745 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006746{
6747 return -ENOSYS;
6748}
6749
6750static int in_standby(struct audio_stream *stream)
6751{
6752 struct stream_in *in = (struct stream_in *)stream;
6753 struct audio_device *adev = in->dev;
6754 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306755 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6756 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006757 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306758
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006759 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006760 if (!in->standby && in->is_st_session) {
6761 ALOGD("%s: sound trigger pcm stop lab", __func__);
6762 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006763 if (adev->num_va_sessions > 0)
6764 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006765 in->standby = 1;
6766 }
6767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006768 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006769 if (adev->adm_deregister_stream)
6770 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6771
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006773 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006774 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006775 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006776 voice_extn_compress_voip_close_input_stream(stream);
6777 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006778 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6779 do_stop = in->capture_started;
6780 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006781 if (in->mmap_shared_memory_fd >= 0) {
6782 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6783 __func__, in->mmap_shared_memory_fd);
6784 close(in->mmap_shared_memory_fd);
6785 in->mmap_shared_memory_fd = -1;
6786 }
Zhou Songa8895042016-07-05 17:54:22 +08006787 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306788 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306789 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006790 }
6791
Arun Mirpuri5d170872019-03-26 13:21:31 -07006792 if (in->pcm) {
6793 ATRACE_BEGIN("pcm_in_close");
6794 pcm_close(in->pcm);
6795 ATRACE_END();
6796 in->pcm = NULL;
6797 }
6798
Carter Hsu2e429db2019-05-14 18:50:52 +08006799 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006800 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006801
George Gao3018ede2019-10-23 13:23:00 -07006802 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6803 if (adev->num_va_sessions > 0)
6804 adev->num_va_sessions--;
6805 }
Quinn Malef6050362019-01-30 15:55:40 -08006806
Eric Laurent150dbfe2013-02-27 14:31:02 -08006807 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006808 }
6809 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006810 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006811 return status;
6812}
6813
Aalique Grahame22e49102018-12-18 14:23:57 -08006814static int in_dump(const struct audio_stream *stream,
6815 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006816{
Aalique Grahame22e49102018-12-18 14:23:57 -08006817 struct stream_in *in = (struct stream_in *)stream;
6818
6819 // We try to get the lock for consistency,
6820 // but it isn't necessary for these variables.
6821 // If we're not in standby, we may be blocked on a read.
6822 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6823 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6824 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6825 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6826
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006827 char buffer[256]; // for statistics formatting
6828 if (in->start_latency_ms.n > 0) {
6829 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6830 dprintf(fd, " Start latency ms: %s\n", buffer);
6831 }
6832
Aalique Grahame22e49102018-12-18 14:23:57 -08006833 if (locked) {
6834 pthread_mutex_unlock(&in->lock);
6835 }
6836
6837 // dump error info
6838 (void)error_log_dump(
6839 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006841 return 0;
6842}
6843
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306844static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6845{
6846 if (!stream || !parms)
6847 return;
6848
6849 struct stream_in *in = (struct stream_in *)stream;
6850 struct audio_device *adev = in->dev;
6851
6852 card_status_t status;
6853 int card;
6854 if (parse_snd_card_status(parms, &card, &status) < 0)
6855 return;
6856
6857 pthread_mutex_lock(&adev->lock);
6858 bool valid_cb = (card == adev->snd_card);
6859 pthread_mutex_unlock(&adev->lock);
6860
6861 if (!valid_cb)
6862 return;
6863
6864 lock_input_stream(in);
6865 if (in->card_status != status)
6866 in->card_status = status;
6867 pthread_mutex_unlock(&in->lock);
6868
6869 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6870 use_case_table[in->usecase],
6871 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6872
6873 // a better solution would be to report error back to AF and let
6874 // it put the stream to standby
6875 if (status == CARD_STATUS_OFFLINE)
6876 in_standby(&in->stream.common);
6877
6878 return;
6879}
6880
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006881int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006882 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006883 audio_source_t source)
6884{
6885 struct audio_device *adev = in->dev;
6886 int ret = 0;
6887
6888 lock_input_stream(in);
6889 pthread_mutex_lock(&adev->lock);
6890
6891 /* no audio source uses val == 0 */
6892 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6893 in->source = source;
6894 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6895 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6896 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6897 (in->config.rate == 8000 || in->config.rate == 16000 ||
6898 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6899 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6900 ret = voice_extn_compress_voip_open_input_stream(in);
6901 if (ret != 0) {
6902 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6903 __func__, ret);
6904 }
6905 }
6906 }
6907
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006908 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6909 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006910 // Workaround: If routing to an non existing usb device, fail gracefully
6911 // The routing request will otherwise block during 10 second
6912 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006913 struct str_parms *usb_addr =
6914 str_parms_create_str(get_usb_device_address(devices));
6915 if (is_usb_in_device_type(devices) && usb_addr &&
6916 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006917 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6918 ret = -ENOSYS;
6919 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006920 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006921 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006922 if (!in->standby && !in->is_st_session) {
6923 ALOGV("update input routing change");
6924 // inform adm before actual routing to prevent glitches.
6925 if (adev->adm_on_routing_change) {
6926 adev->adm_on_routing_change(adev->adm_data,
6927 in->capture_handle);
6928 ret = select_devices(adev, in->usecase);
6929 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6930 adev->adm_routing_changed = true;
6931 }
6932 }
6933 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006934 if (usb_addr)
6935 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006936 }
6937 pthread_mutex_unlock(&adev->lock);
6938 pthread_mutex_unlock(&in->lock);
6939
6940 ALOGD("%s: exit: status(%d)", __func__, ret);
6941 return ret;
6942}
6943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006944static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6945{
6946 struct stream_in *in = (struct stream_in *)stream;
6947 struct audio_device *adev = in->dev;
6948 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006949 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306950 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306952 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006953 parms = str_parms_create_str(kvpairs);
6954
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306955 if (!parms)
6956 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006957 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006958 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006959
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306960 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6961 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306962 strlcpy(in->profile, value, sizeof(in->profile));
6963 ALOGV("updating stream profile with value '%s'", in->profile);
6964 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6965 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006966 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306967 in->sample_rate, in->bit_width,
6968 in->profile, &in->app_type_cfg);
6969 }
6970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006971 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006972 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973
6974 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306975error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306976 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006977}
6978
6979static char* in_get_parameters(const struct audio_stream *stream,
6980 const char *keys)
6981{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006982 struct stream_in *in = (struct stream_in *)stream;
6983 struct str_parms *query = str_parms_create_str(keys);
6984 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006985 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006986
6987 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006988 if (reply) {
6989 str_parms_destroy(reply);
6990 }
6991 if (query) {
6992 str_parms_destroy(query);
6993 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006994 ALOGE("in_get_parameters: failed to create query or reply");
6995 return NULL;
6996 }
6997
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006998 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006999
7000 voice_extn_in_get_parameters(in, query, reply);
7001
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007002 stream_get_parameter_channels(query, reply,
7003 &in->supported_channel_masks[0]);
7004 stream_get_parameter_formats(query, reply,
7005 &in->supported_formats[0]);
7006 stream_get_parameter_rates(query, reply,
7007 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007008 str = str_parms_to_str(reply);
7009 str_parms_destroy(query);
7010 str_parms_destroy(reply);
7011
7012 ALOGV("%s: exit: returns - %s", __func__, str);
7013 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007014}
7015
Aalique Grahame22e49102018-12-18 14:23:57 -08007016static int in_set_gain(struct audio_stream_in *stream,
7017 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007018{
Aalique Grahame22e49102018-12-18 14:23:57 -08007019 struct stream_in *in = (struct stream_in *)stream;
7020 char mixer_ctl_name[128];
7021 struct mixer_ctl *ctl;
7022 int ctl_value;
7023
7024 ALOGV("%s: gain %f", __func__, gain);
7025
7026 if (stream == NULL)
7027 return -EINVAL;
7028
7029 /* in_set_gain() only used to silence MMAP capture for now */
7030 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7031 return -ENOSYS;
7032
7033 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7034
7035 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7036 if (!ctl) {
7037 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7038 __func__, mixer_ctl_name);
7039 return -ENOSYS;
7040 }
7041
7042 if (gain < RECORD_GAIN_MIN)
7043 gain = RECORD_GAIN_MIN;
7044 else if (gain > RECORD_GAIN_MAX)
7045 gain = RECORD_GAIN_MAX;
7046 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7047
7048 mixer_ctl_set_value(ctl, 0, ctl_value);
7049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050 return 0;
7051}
7052
7053static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7054 size_t bytes)
7055{
7056 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307057
7058 if (in == NULL) {
7059 ALOGE("%s: stream_in ptr is NULL", __func__);
7060 return -EINVAL;
7061 }
7062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007063 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307064 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307065 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007066
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007067 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307068
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007069 if (in->is_st_session) {
7070 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7071 /* Read from sound trigger HAL */
7072 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007073 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007074 if (adev->num_va_sessions < UINT_MAX)
7075 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007076 in->standby = 0;
7077 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007078 pthread_mutex_unlock(&in->lock);
7079 return bytes;
7080 }
7081
Haynes Mathew George16081042017-05-31 17:16:49 -07007082 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7083 ret = -ENOSYS;
7084 goto exit;
7085 }
7086
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007087 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7088 !in->standby && adev->adm_routing_changed) {
7089 ret = -ENOSYS;
7090 goto exit;
7091 }
7092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007093 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007094 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7095
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007096 pthread_mutex_lock(&adev->lock);
7097 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7098 ret = voice_extn_compress_voip_start_input_stream(in);
7099 else
7100 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007101 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7102 if (adev->num_va_sessions < UINT_MAX)
7103 adev->num_va_sessions++;
7104 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007105 pthread_mutex_unlock(&adev->lock);
7106 if (ret != 0) {
7107 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007108 }
7109 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007110
7111 // log startup time in ms.
7112 simple_stats_log(
7113 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307116 /* Avoid read if capture_stopped is set */
7117 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7118 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7119 ret = -EINVAL;
7120 goto exit;
7121 }
7122
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007123 // what's the duration requested by the client?
7124 long ns = 0;
7125
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307126 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007127 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7128 in->config.rate;
7129
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007130 ret = request_in_focus(in, ns);
7131 if (ret != 0)
7132 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007133 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007134
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307135 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307136 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7137 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307138 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007139 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307140 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007141 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007142 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007143 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007144 } else if (audio_extn_ffv_get_stream() == in) {
7145 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307146 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007147 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307148 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7149 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7150 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7151 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307152 ret = -EINVAL;
7153 goto exit;
7154 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307155 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307156 ret = -errno;
7157 }
7158 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307159 /* bytes read is always set to bytes for non compress usecases */
7160 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161 }
7162
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007163 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007165 /*
Quinn Malef6050362019-01-30 15:55:40 -08007166 * Instead of writing zeroes here, we could trust the hardware to always
7167 * provide zeroes when muted. This is also muted with voice recognition
7168 * usecases so that other clients do not have access to voice recognition
7169 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 */
Quinn Malef6050362019-01-30 15:55:40 -08007171 if ((ret == 0 && voice_get_mic_mute(adev) &&
7172 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007173 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7174 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007175 (adev->num_va_sessions &&
7176 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7177 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7178 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007179 memset(buffer, 0, bytes);
7180
7181exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307182 frame_size = audio_stream_in_frame_size(stream);
7183 if (frame_size > 0)
7184 in->frames_read += bytes_read/frame_size;
7185
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007186 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307187 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188 pthread_mutex_unlock(&in->lock);
7189
7190 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307191 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307192 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307193 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307194 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307195 in->standby = true;
7196 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307197 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307198 bytes_read = bytes;
7199 memset(buffer, 0, bytes);
7200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007202 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7203 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007204 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307205 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307206 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307208 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007209}
7210
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007211static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007212{
7213 return 0;
7214}
7215
Aalique Grahame22e49102018-12-18 14:23:57 -08007216static int in_get_capture_position(const struct audio_stream_in *stream,
7217 int64_t *frames, int64_t *time)
7218{
7219 if (stream == NULL || frames == NULL || time == NULL) {
7220 return -EINVAL;
7221 }
7222 struct stream_in *in = (struct stream_in *)stream;
7223 int ret = -ENOSYS;
7224
7225 lock_input_stream(in);
7226 // note: ST sessions do not close the alsa pcm driver synchronously
7227 // on standby. Therefore, we may return an error even though the
7228 // pcm stream is still opened.
7229 if (in->standby) {
7230 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7231 "%s stream in standby but pcm not NULL for non ST session", __func__);
7232 goto exit;
7233 }
7234 if (in->pcm) {
7235 struct timespec timestamp;
7236 unsigned int avail;
7237 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7238 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007239 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007240 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007241 ret = 0;
7242 }
7243 }
7244exit:
7245 pthread_mutex_unlock(&in->lock);
7246 return ret;
7247}
7248
Carter Hsu2e429db2019-05-14 18:50:52 +08007249static int in_update_effect_list(bool add, effect_handle_t effect,
7250 struct listnode *head)
7251{
7252 struct listnode *node;
7253 struct in_effect_list *elist = NULL;
7254 struct in_effect_list *target = NULL;
7255 int ret = 0;
7256
7257 if (!head)
7258 return ret;
7259
7260 list_for_each(node, head) {
7261 elist = node_to_item(node, struct in_effect_list, list);
7262 if (elist->handle == effect) {
7263 target = elist;
7264 break;
7265 }
7266 }
7267
7268 if (add) {
7269 if (target) {
7270 ALOGD("effect %p already exist", effect);
7271 return ret;
7272 }
7273
7274 target = (struct in_effect_list *)
7275 calloc(1, sizeof(struct in_effect_list));
7276
7277 if (!target) {
7278 ALOGE("%s:fail to allocate memory", __func__);
7279 return -ENOMEM;
7280 }
7281
7282 target->handle = effect;
7283 list_add_tail(head, &target->list);
7284 } else {
7285 if (target) {
7286 list_remove(&target->list);
7287 free(target);
7288 }
7289 }
7290
7291 return ret;
7292}
7293
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007294static int add_remove_audio_effect(const struct audio_stream *stream,
7295 effect_handle_t effect,
7296 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007297{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007298 struct stream_in *in = (struct stream_in *)stream;
7299 int status = 0;
7300 effect_descriptor_t desc;
7301
7302 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007303 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7304
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007305 if (status != 0)
7306 return status;
7307
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007308 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007309 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007310 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007311 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7312 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007313 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007314
7315 in_update_effect_list(enable, effect, &in->aec_list);
7316 enable = !list_empty(&in->aec_list);
7317 if (enable == in->enable_aec)
7318 goto exit;
7319
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007320 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007321 ALOGD("AEC enable %d", enable);
7322
Aalique Grahame22e49102018-12-18 14:23:57 -08007323 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7324 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7325 in->dev->enable_voicerx = enable;
7326 struct audio_usecase *usecase;
7327 struct listnode *node;
7328 list_for_each(node, &in->dev->usecase_list) {
7329 usecase = node_to_item(node, struct audio_usecase, list);
7330 if (usecase->type == PCM_PLAYBACK)
7331 select_devices(in->dev, usecase->id);
7332 }
7333 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007334 if (!in->standby) {
7335 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7336 select_devices(in->dev, in->usecase);
7337 }
7338
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007339 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007340 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7341
7342 in_update_effect_list(enable, effect, &in->ns_list);
7343 enable = !list_empty(&in->ns_list);
7344 if (enable == in->enable_ns)
7345 goto exit;
7346
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007347 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007348 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007349 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007350 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7351 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007352 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7353 select_devices(in->dev, in->usecase);
7354 } else
7355 select_devices(in->dev, in->usecase);
7356 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007357 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007358exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007359 pthread_mutex_unlock(&in->dev->lock);
7360 pthread_mutex_unlock(&in->lock);
7361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362 return 0;
7363}
7364
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007365static int in_add_audio_effect(const struct audio_stream *stream,
7366 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367{
Eric Laurent994a6932013-07-17 11:51:42 -07007368 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007369 return add_remove_audio_effect(stream, effect, true);
7370}
7371
7372static int in_remove_audio_effect(const struct audio_stream *stream,
7373 effect_handle_t effect)
7374{
Eric Laurent994a6932013-07-17 11:51:42 -07007375 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007376 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007377}
7378
Derek Chenf939fb72018-11-13 13:34:41 -08007379streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7380 audio_io_handle_t input)
7381{
7382 struct listnode *node;
7383
7384 list_for_each(node, &dev->active_inputs_list) {
7385 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7386 streams_input_ctxt_t,
7387 list);
7388 if (in_ctxt->input->capture_handle == input) {
7389 return in_ctxt;
7390 }
7391 }
7392 return NULL;
7393}
7394
7395streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7396 audio_io_handle_t output)
7397{
7398 struct listnode *node;
7399
7400 list_for_each(node, &dev->active_outputs_list) {
7401 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7402 streams_output_ctxt_t,
7403 list);
7404 if (out_ctxt->output->handle == output) {
7405 return out_ctxt;
7406 }
7407 }
7408 return NULL;
7409}
7410
Haynes Mathew George16081042017-05-31 17:16:49 -07007411static int in_stop(const struct audio_stream_in* stream)
7412{
7413 struct stream_in *in = (struct stream_in *)stream;
7414 struct audio_device *adev = in->dev;
7415
7416 int ret = -ENOSYS;
7417 ALOGV("%s", __func__);
7418 pthread_mutex_lock(&adev->lock);
7419 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7420 in->capture_started && in->pcm != NULL) {
7421 pcm_stop(in->pcm);
7422 ret = stop_input_stream(in);
7423 in->capture_started = false;
7424 }
7425 pthread_mutex_unlock(&adev->lock);
7426 return ret;
7427}
7428
7429static int in_start(const struct audio_stream_in* stream)
7430{
7431 struct stream_in *in = (struct stream_in *)stream;
7432 struct audio_device *adev = in->dev;
7433 int ret = -ENOSYS;
7434
7435 ALOGV("%s in %p", __func__, in);
7436 pthread_mutex_lock(&adev->lock);
7437 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7438 !in->capture_started && in->pcm != NULL) {
7439 if (!in->capture_started) {
7440 ret = start_input_stream(in);
7441 if (ret == 0) {
7442 in->capture_started = true;
7443 }
7444 }
7445 }
7446 pthread_mutex_unlock(&adev->lock);
7447 return ret;
7448}
7449
Phil Burke0a86d12019-02-16 22:28:11 -08007450// Read offset for the positional timestamp from a persistent vendor property.
7451// This is to workaround apparent inaccuracies in the timing information that
7452// is used by the AAudio timing model. The inaccuracies can cause glitches.
7453static int64_t in_get_mmap_time_offset() {
7454 const int32_t kDefaultOffsetMicros = 0;
7455 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007456 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007457 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7458 return mmap_time_offset_micros * (int64_t)1000;
7459}
7460
Haynes Mathew George16081042017-05-31 17:16:49 -07007461static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7462 int32_t min_size_frames,
7463 struct audio_mmap_buffer_info *info)
7464{
7465 struct stream_in *in = (struct stream_in *)stream;
7466 struct audio_device *adev = in->dev;
7467 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007468 unsigned int offset1 = 0;
7469 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007470 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007471 uint32_t mmap_size = 0;
7472 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007473
7474 pthread_mutex_lock(&adev->lock);
7475 ALOGV("%s in %p", __func__, in);
7476
Sharad Sanglec6f32552018-05-04 16:15:38 +05307477 if (CARD_STATUS_OFFLINE == in->card_status||
7478 CARD_STATUS_OFFLINE == adev->card_status) {
7479 ALOGW("in->card_status or adev->card_status offline, try again");
7480 ret = -EIO;
7481 goto exit;
7482 }
7483
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307484 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007485 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7486 ret = -EINVAL;
7487 goto exit;
7488 }
7489 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7490 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7491 ALOGV("%s in %p", __func__, in);
7492 ret = -ENOSYS;
7493 goto exit;
7494 }
7495 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7496 if (in->pcm_device_id < 0) {
7497 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7498 __func__, in->pcm_device_id, in->usecase);
7499 ret = -EINVAL;
7500 goto exit;
7501 }
7502
7503 adjust_mmap_period_count(&in->config, min_size_frames);
7504
7505 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7506 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7507 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7508 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307509 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307510 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7511 in->card_status = CARD_STATUS_OFFLINE;
7512 adev->card_status = CARD_STATUS_OFFLINE;
7513 ret = -EIO;
7514 goto exit;
7515 }
7516
Haynes Mathew George16081042017-05-31 17:16:49 -07007517 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7518 step = "open";
7519 ret = -ENODEV;
7520 goto exit;
7521 }
7522
7523 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7524 if (ret < 0) {
7525 step = "begin";
7526 goto exit;
7527 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007528
juyuchen626833d2019-06-04 16:48:02 +08007529 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007530 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7531 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7532 info->burst_size_frames = in->config.period_size;
7533 ret = platform_get_mmap_data_fd(adev->platform,
7534 in->pcm_device_id, 1 /*capture*/,
7535 &info->shared_memory_fd,
7536 &mmap_size);
7537 if (ret < 0) {
7538 // Fall back to non exclusive mode
7539 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7540 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007541 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7542 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7543
Arun Mirpuri5d170872019-03-26 13:21:31 -07007544 if (mmap_size < buffer_size) {
7545 step = "mmap";
7546 goto exit;
7547 }
juyuchen626833d2019-06-04 16:48:02 +08007548 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007549 }
7550
7551 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007552
7553 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7554 if (ret < 0) {
7555 step = "commit";
7556 goto exit;
7557 }
7558
Phil Burke0a86d12019-02-16 22:28:11 -08007559 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7560
Haynes Mathew George16081042017-05-31 17:16:49 -07007561 in->standby = false;
7562 ret = 0;
7563
7564 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7565 __func__, info->shared_memory_address, info->buffer_size_frames);
7566
7567exit:
7568 if (ret != 0) {
7569 if (in->pcm == NULL) {
7570 ALOGE("%s: %s - %d", __func__, step, ret);
7571 } else {
7572 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7573 pcm_close(in->pcm);
7574 in->pcm = NULL;
7575 }
7576 }
7577 pthread_mutex_unlock(&adev->lock);
7578 return ret;
7579}
7580
7581static int in_get_mmap_position(const struct audio_stream_in *stream,
7582 struct audio_mmap_position *position)
7583{
7584 struct stream_in *in = (struct stream_in *)stream;
7585 ALOGVV("%s", __func__);
7586 if (position == NULL) {
7587 return -EINVAL;
7588 }
7589 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7590 return -ENOSYS;
7591 }
7592 if (in->pcm == NULL) {
7593 return -ENOSYS;
7594 }
7595 struct timespec ts = { 0, 0 };
7596 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7597 if (ret < 0) {
7598 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7599 return ret;
7600 }
Phil Burke0a86d12019-02-16 22:28:11 -08007601 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7602 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007603 return 0;
7604}
7605
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307606static int in_get_active_microphones(const struct audio_stream_in *stream,
7607 struct audio_microphone_characteristic_t *mic_array,
7608 size_t *mic_count) {
7609 struct stream_in *in = (struct stream_in *)stream;
7610 struct audio_device *adev = in->dev;
7611 ALOGVV("%s", __func__);
7612
7613 lock_input_stream(in);
7614 pthread_mutex_lock(&adev->lock);
7615 int ret = platform_get_active_microphones(adev->platform,
7616 audio_channel_count_from_in_mask(in->channel_mask),
7617 in->usecase, mic_array, mic_count);
7618 pthread_mutex_unlock(&adev->lock);
7619 pthread_mutex_unlock(&in->lock);
7620
7621 return ret;
7622}
7623
7624static int adev_get_microphones(const struct audio_hw_device *dev,
7625 struct audio_microphone_characteristic_t *mic_array,
7626 size_t *mic_count) {
7627 struct audio_device *adev = (struct audio_device *)dev;
7628 ALOGVV("%s", __func__);
7629
7630 pthread_mutex_lock(&adev->lock);
7631 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7632 pthread_mutex_unlock(&adev->lock);
7633
7634 return ret;
7635}
juyuchendb308c22019-01-21 11:57:17 -07007636
7637static void in_update_sink_metadata(struct audio_stream_in *stream,
7638 const struct sink_metadata *sink_metadata) {
7639
7640 if (stream == NULL
7641 || sink_metadata == NULL
7642 || sink_metadata->tracks == NULL) {
7643 return;
7644 }
7645
7646 int error = 0;
7647 struct stream_in *in = (struct stream_in *)stream;
7648 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007649 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007650 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007651
7652 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007653
7654 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007655 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007656
7657 lock_input_stream(in);
7658 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007659 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007660
Zhou Song62ea0282020-03-22 19:53:01 +08007661 is_ha_usecase = adev->ha_proxy_enable ?
7662 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7663 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7664 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007665 && adev->voice_tx_output != NULL) {
7666 /* Use the rx device from afe-proxy record to route voice call because
7667 there is no routing if tx device is on primary hal and rx device
7668 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007669 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007670
7671 if (!voice_is_call_state_active(adev)) {
7672 if (adev->mode == AUDIO_MODE_IN_CALL) {
7673 adev->current_call_output = adev->voice_tx_output;
7674 error = voice_start_call(adev);
7675 if (error != 0)
7676 ALOGE("%s: start voice call failed %d", __func__, error);
7677 }
7678 } else {
7679 adev->current_call_output = adev->voice_tx_output;
7680 voice_update_devices_for_all_voice_usecases(adev);
7681 }
7682 }
7683
7684 pthread_mutex_unlock(&adev->lock);
7685 pthread_mutex_unlock(&in->lock);
7686}
7687
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307688int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007689 audio_io_handle_t handle,
7690 audio_devices_t devices,
7691 audio_output_flags_t flags,
7692 struct audio_config *config,
7693 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007694 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007695{
7696 struct audio_device *adev = (struct audio_device *)dev;
7697 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307698 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007699 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007700 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307701 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007702 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7703 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7704 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7705 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007706 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007707 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7708 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007709 bool force_haptic_path =
7710 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007711 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007712#ifdef AUDIO_GKI_ENABLED
7713 __s32 *generic_dec;
7714#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007715
kunleizdff872d2018-08-20 14:40:33 +08007716 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007717 is_usb_dev = false;
7718 devices = AUDIO_DEVICE_OUT_SPEAKER;
7719 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7720 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007721 if (config->format == AUDIO_FORMAT_DEFAULT)
7722 config->format = AUDIO_FORMAT_PCM_16_BIT;
7723 if (config->sample_rate == 0)
7724 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7725 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7726 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007727 }
7728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007729 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307730
Rahul Sharma99770982019-03-06 17:05:26 +05307731 pthread_mutex_lock(&adev->lock);
7732 if (out_get_stream(adev, handle) != NULL) {
7733 ALOGW("%s, output stream already opened", __func__);
7734 ret = -EEXIST;
7735 }
7736 pthread_mutex_unlock(&adev->lock);
7737 if (ret)
7738 return ret;
7739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007740 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7741
Mingming Yin3a941d42016-02-17 18:08:05 -08007742 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007743 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7744 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307745
7746
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007747 if (!out) {
7748 return -ENOMEM;
7749 }
7750
Haynes Mathew George204045b2015-02-25 20:32:03 -08007751 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007752 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007753 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007754 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007755 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007757 if (devices == AUDIO_DEVICE_NONE)
7758 devices = AUDIO_DEVICE_OUT_SPEAKER;
7759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007760 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007761 list_init(&out->device_list);
7762 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007763 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007764 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007765 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307766 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307767 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7768 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7769 else
7770 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007771 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007772 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007773 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307774 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307775 out->started = 0;
Zhou Song1f93fa52020-11-20 13:57:39 +08007776 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007777 out->hal_output_suspend_supported = 0;
7778 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307779 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307780 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307781 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007782 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007783
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307784 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307785 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007786 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7787
Aalique Grahame22e49102018-12-18 14:23:57 -08007788 if (direct_dev &&
7789 (audio_is_linear_pcm(out->format) ||
7790 config->format == AUDIO_FORMAT_DEFAULT) &&
7791 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7792 audio_format_t req_format = config->format;
7793 audio_channel_mask_t req_channel_mask = config->channel_mask;
7794 uint32_t req_sample_rate = config->sample_rate;
7795
7796 pthread_mutex_lock(&adev->lock);
7797 if (is_hdmi) {
7798 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7799 ret = read_hdmi_sink_caps(out);
7800 if (config->sample_rate == 0)
7801 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7802 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7803 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7804 if (config->format == AUDIO_FORMAT_DEFAULT)
7805 config->format = AUDIO_FORMAT_PCM_16_BIT;
7806 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007807 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7808 &config->format,
7809 &out->supported_formats[0],
7810 MAX_SUPPORTED_FORMATS,
7811 &config->channel_mask,
7812 &out->supported_channel_masks[0],
7813 MAX_SUPPORTED_CHANNEL_MASKS,
7814 &config->sample_rate,
7815 &out->supported_sample_rates[0],
7816 MAX_SUPPORTED_SAMPLE_RATES);
7817 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007818 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007819
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007820 pthread_mutex_unlock(&adev->lock);
7821 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007822 if (ret == -ENOSYS) {
7823 /* ignore and go with default */
7824 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007825 }
7826 // For MMAP NO IRQ, allow conversions in ADSP
7827 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7828 goto error_open;
7829 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007830 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007831 goto error_open;
7832 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007833
7834 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7835 config->sample_rate = req_sample_rate;
7836 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7837 config->channel_mask = req_channel_mask;
7838 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7839 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007840 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007841
7842 out->sample_rate = config->sample_rate;
7843 out->channel_mask = config->channel_mask;
7844 out->format = config->format;
7845 if (is_hdmi) {
7846 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7847 out->config = pcm_config_hdmi_multi;
7848 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7849 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7850 out->config = pcm_config_mmap_playback;
7851 out->stream.start = out_start;
7852 out->stream.stop = out_stop;
7853 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7854 out->stream.get_mmap_position = out_get_mmap_position;
7855 } else {
7856 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7857 out->config = pcm_config_hifi;
7858 }
7859
7860 out->config.rate = out->sample_rate;
7861 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7862 if (is_hdmi) {
7863 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7864 audio_bytes_per_sample(out->format));
7865 }
7866 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007867 }
7868
Derek Chenf6318be2017-06-12 17:16:24 -04007869 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007870 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007871 /* extract car audio stream index */
7872 out->car_audio_stream =
7873 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7874 if (out->car_audio_stream < 0) {
7875 ALOGE("%s: invalid car audio stream %x",
7876 __func__, out->car_audio_stream);
7877 ret = -EINVAL;
7878 goto error_open;
7879 }
Derek Chen5f67a942020-02-24 23:08:13 -08007880 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007881 }
7882
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007883 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007884 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007885 if (!voice_extn_is_compress_voip_supported()) {
7886 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7887 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007888 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307889 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007890 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7891 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007892 out->volume_l = INVALID_OUT_VOLUME;
7893 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007894
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007895 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007896 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007897 uint32_t channel_count =
7898 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307899 out->config.channels = channel_count;
7900
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007901 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7902 out->sample_rate, out->format,
7903 channel_count, false);
7904 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7905 if (frame_size != 0)
7906 out->config.period_size = buffer_size / frame_size;
7907 else
7908 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007909 }
7910 } else {
7911 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7912 voice_extn_compress_voip_is_active(out->dev)) &&
7913 (voice_extn_compress_voip_is_config_supported(config))) {
7914 ret = voice_extn_compress_voip_open_output_stream(out);
7915 if (ret != 0) {
7916 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7917 __func__, ret);
7918 goto error_open;
7919 }
Sujin Panicker19027262019-09-16 18:28:06 +05307920 } else {
7921 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7922 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007923 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007924 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007925 } else if (audio_is_linear_pcm(out->format) &&
7926 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7927 out->channel_mask = config->channel_mask;
7928 out->sample_rate = config->sample_rate;
7929 out->format = config->format;
7930 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7931 // does this change?
7932 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7933 out->config.rate = config->sample_rate;
7934 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7935 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7936 audio_bytes_per_sample(config->format));
7937 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007938 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307939 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307940 pthread_mutex_lock(&adev->lock);
7941 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7942 pthread_mutex_unlock(&adev->lock);
7943
7944 // reject offload during card offline to allow
7945 // fallback to s/w paths
7946 if (offline) {
7947 ret = -ENODEV;
7948 goto error_open;
7949 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007951 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7952 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7953 ALOGE("%s: Unsupported Offload information", __func__);
7954 ret = -EINVAL;
7955 goto error_open;
7956 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007957
Atul Khare3fa6e542017-08-09 00:56:17 +05307958 if (config->offload_info.format == 0)
7959 config->offload_info.format = config->format;
7960 if (config->offload_info.sample_rate == 0)
7961 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007962
Mingming Yin90310102013-11-13 16:57:00 -08007963 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307964 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007965 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007966 ret = -EINVAL;
7967 goto error_open;
7968 }
7969
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007970 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7971 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7972 (audio_extn_passthru_is_passthrough_stream(out)) &&
7973 !((config->sample_rate == 48000) ||
7974 (config->sample_rate == 96000) ||
7975 (config->sample_rate == 192000))) {
7976 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7977 __func__, config->sample_rate, config->offload_info.format);
7978 ret = -EINVAL;
7979 goto error_open;
7980 }
7981
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007982 out->compr_config.codec = (struct snd_codec *)
7983 calloc(1, sizeof(struct snd_codec));
7984
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007985 if (!out->compr_config.codec) {
7986 ret = -ENOMEM;
7987 goto error_open;
7988 }
7989
Dhananjay Kumarac341582017-02-23 23:42:25 +05307990 out->stream.pause = out_pause;
7991 out->stream.resume = out_resume;
7992 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307993 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307994 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007995 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307996 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007997 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307998 } else {
7999 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8000 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008001 }
vivek mehta446c3962015-09-14 10:57:35 -07008002
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308003 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8004 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008005#ifdef AUDIO_GKI_ENABLED
8006 /* out->compr_config.codec->reserved[1] is for flags */
8007 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8008#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308009 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008010#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308011 }
8012
vivek mehta446c3962015-09-14 10:57:35 -07008013 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008014 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008015 config->format == 0 && config->sample_rate == 0 &&
8016 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008017 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008018 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8019 } else {
8020 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8021 ret = -EEXIST;
8022 goto error_open;
8023 }
vivek mehta446c3962015-09-14 10:57:35 -07008024 }
8025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008026 if (config->offload_info.channel_mask)
8027 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008028 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008029 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008030 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008031 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308032 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008033 ret = -EINVAL;
8034 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008035 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008036
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008037 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008038 out->sample_rate = config->offload_info.sample_rate;
8039
Mingming Yin3ee55c62014-08-04 14:23:35 -07008040 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008041
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308042 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308043 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308044 audio_extn_dolby_send_ddp_endp_params(adev);
8045 audio_extn_dolby_set_dmid(adev);
8046 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008048 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008049 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 out->compr_config.codec->bit_rate =
8051 config->offload_info.bit_rate;
8052 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308053 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308055 /* Update bit width only for non passthrough usecases.
8056 * For passthrough usecases, the output will always be opened @16 bit
8057 */
8058 if (!audio_extn_passthru_is_passthrough_stream(out))
8059 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308060
8061 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008062#ifdef AUDIO_GKI_ENABLED
8063 /* out->compr_config.codec->reserved[1] is for flags */
8064 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8065 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8066#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308067 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8068 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008069#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308070
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008071 /*TODO: Do we need to change it for passthrough */
8072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008073
Manish Dewangana6fc5442015-08-24 20:30:31 +05308074 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8075 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308076 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308077 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308078 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8079 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308080
8081 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8082 AUDIO_FORMAT_PCM) {
8083
8084 /*Based on platform support, configure appropriate alsa format for corresponding
8085 *hal input format.
8086 */
8087 out->compr_config.codec->format = hal_format_to_alsa(
8088 config->offload_info.format);
8089
Ashish Jain83a6cc22016-06-28 14:34:17 +05308090 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308091 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308092 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308093
Dhananjay Kumarac341582017-02-23 23:42:25 +05308094 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308095 *hal input format and alsa format might differ based on platform support.
8096 */
8097 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308098 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308099
8100 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8101
Deeraj Soman93155a62019-09-30 19:00:37 +05308102 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8103 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8104 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8105 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8106 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308107
Ashish Jainf1eaa582016-05-23 20:54:24 +05308108 /* Check if alsa session is configured with the same format as HAL input format,
8109 * if not then derive correct fragment size needed to accomodate the
8110 * conversion of HAL input format to alsa format.
8111 */
8112 audio_extn_utils_update_direct_pcm_fragment_size(out);
8113
8114 /*if hal input and output fragment size is different this indicates HAL input format is
8115 *not same as the alsa format
8116 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308117 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308118 /*Allocate a buffer to convert input data to the alsa configured format.
8119 *size of convert buffer is equal to the size required to hold one fragment size
8120 *worth of pcm data, this is because flinger does not write more than fragment_size
8121 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308122 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8123 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308124 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8125 ret = -ENOMEM;
8126 goto error_open;
8127 }
8128 }
8129 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8130 out->compr_config.fragment_size =
8131 audio_extn_passthru_get_buffer_size(&config->offload_info);
8132 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8133 } else {
8134 out->compr_config.fragment_size =
8135 platform_get_compress_offload_buffer_size(&config->offload_info);
8136 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8137 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008138
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308139 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8140 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8141 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008142 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8143#ifdef AUDIO_GKI_ENABLED
8144 generic_dec =
8145 &(out->compr_config.codec->options.generic.reserved[1]);
8146 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8147 AUDIO_OUTPUT_BIT_WIDTH;
8148#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308149 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008150#endif
8151 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008152
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308153 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8154 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8155 }
8156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008157 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8158 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008159
Manish Dewangan69426c82017-01-30 17:35:36 +05308160 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8161 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8162 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8163 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8164 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8165 } else {
8166 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8167 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008168
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308169 memset(&out->channel_map_param, 0,
8170 sizeof(struct audio_out_channel_map_param));
8171
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008172 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308173 out->send_next_track_params = false;
8174 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008175 out->offload_state = OFFLOAD_STATE_IDLE;
8176 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008177 out->writeAt.tv_sec = 0;
8178 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008179
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008180 audio_extn_dts_create_state_notifier_node(out->usecase);
8181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008182 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8183 __func__, config->offload_info.version,
8184 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308185
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308186 /* Check if DSD audio format is supported in codec
8187 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308188 */
8189
8190 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308191 (!platform_check_codec_dsd_support(adev->platform) ||
8192 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308193 ret = -EINVAL;
8194 goto error_open;
8195 }
8196
Ashish Jain5106d362016-05-11 19:23:33 +05308197 /* Disable gapless if any of the following is true
8198 * passthrough playback
8199 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308200 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308201 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308202 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308203 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008204 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308205 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308206 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308207 check_and_set_gapless_mode(adev, false);
8208 } else
8209 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008210
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308211 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008212 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8213 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308214 if (config->format == AUDIO_FORMAT_DSD) {
8215 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008216#ifdef AUDIO_GKI_ENABLED
8217 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8218 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8219#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308220 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008221#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308222 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008223
8224 create_offload_callback_thread(out);
8225
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008226 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008227 switch (config->sample_rate) {
8228 case 0:
8229 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8230 break;
8231 case 8000:
8232 case 16000:
8233 case 48000:
8234 out->sample_rate = config->sample_rate;
8235 break;
8236 default:
8237 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8238 config->sample_rate);
8239 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8240 ret = -EINVAL;
8241 goto error_open;
8242 }
8243 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8244 switch (config->channel_mask) {
8245 case AUDIO_CHANNEL_NONE:
8246 case AUDIO_CHANNEL_OUT_STEREO:
8247 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8248 break;
8249 default:
8250 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8251 config->channel_mask);
8252 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8253 ret = -EINVAL;
8254 goto error_open;
8255 }
8256 switch (config->format) {
8257 case AUDIO_FORMAT_DEFAULT:
8258 case AUDIO_FORMAT_PCM_16_BIT:
8259 out->format = AUDIO_FORMAT_PCM_16_BIT;
8260 break;
8261 default:
8262 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8263 config->format);
8264 config->format = AUDIO_FORMAT_PCM_16_BIT;
8265 ret = -EINVAL;
8266 goto error_open;
8267 }
8268
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308269 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008270 if (ret != 0) {
8271 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008272 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008273 goto error_open;
8274 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008275 } else if (is_single_device_type_equal(&out->device_list,
8276 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008277 switch (config->sample_rate) {
8278 case 0:
8279 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8280 break;
8281 case 8000:
8282 case 16000:
8283 case 48000:
8284 out->sample_rate = config->sample_rate;
8285 break;
8286 default:
8287 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8288 config->sample_rate);
8289 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8290 ret = -EINVAL;
8291 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008292 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008293 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8294 switch (config->channel_mask) {
8295 case AUDIO_CHANNEL_NONE:
8296 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8297 break;
8298 case AUDIO_CHANNEL_OUT_STEREO:
8299 out->channel_mask = config->channel_mask;
8300 break;
8301 default:
8302 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8303 config->channel_mask);
8304 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8305 ret = -EINVAL;
8306 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008307 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008308 switch (config->format) {
8309 case AUDIO_FORMAT_DEFAULT:
8310 out->format = AUDIO_FORMAT_PCM_16_BIT;
8311 break;
8312 case AUDIO_FORMAT_PCM_16_BIT:
8313 out->format = config->format;
8314 break;
8315 default:
8316 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8317 config->format);
8318 config->format = AUDIO_FORMAT_PCM_16_BIT;
8319 ret = -EINVAL;
8320 break;
8321 }
8322 if (ret != 0)
8323 goto error_open;
8324
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008325 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8326 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008327 out->config.rate = out->sample_rate;
8328 out->config.channels =
8329 audio_channel_count_from_out_mask(out->channel_mask);
8330 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008331 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008332 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308333 unsigned int channels = 0;
8334 /*Update config params to default if not set by the caller*/
8335 if (config->sample_rate == 0)
8336 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8337 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8338 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8339 if (config->format == AUDIO_FORMAT_DEFAULT)
8340 config->format = AUDIO_FORMAT_PCM_16_BIT;
8341
8342 channels = audio_channel_count_from_out_mask(out->channel_mask);
8343
Varun Balaraje49253e2017-07-06 19:48:56 +05308344 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8345 out->usecase = get_interactive_usecase(adev);
8346 out->config = pcm_config_low_latency;
8347 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308348 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008349 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8350 out->flags);
8351 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008352 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8353 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8354 out->config = pcm_config_mmap_playback;
8355 out->stream.start = out_start;
8356 out->stream.stop = out_stop;
8357 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8358 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308359 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8360 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008361 out->hal_output_suspend_supported =
8362 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8363 out->dynamic_pm_qos_config_supported =
8364 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8365 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008366 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8367 } else {
8368 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8369 //the mixer path will be a string similar to "low-latency-playback resume"
8370 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8371 strlcat(out->pm_qos_mixer_path,
8372 " resume", MAX_MIXER_PATH_LEN);
8373 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8374 out->pm_qos_mixer_path);
8375 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308376 out->config = pcm_config_low_latency;
8377 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8378 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8379 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308380 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8381 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8382 if (out->config.period_size <= 0) {
8383 ALOGE("Invalid configuration period size is not valid");
8384 ret = -EINVAL;
8385 goto error_open;
8386 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008387 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8388 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8389 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008390 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8391 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8392 out->config = pcm_config_haptics_audio;
8393 if (force_haptic_path)
8394 adev->haptics_config = pcm_config_haptics_audio;
8395 else
8396 adev->haptics_config = pcm_config_haptics;
8397
Meng Wangd08ce322020-04-02 08:59:20 +08008398 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008399 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8400
8401 if (force_haptic_path) {
8402 out->config.channels = 1;
8403 adev->haptics_config.channels = 1;
8404 } else
8405 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 -08008406 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008407 ret = audio_extn_auto_hal_open_output_stream(out);
8408 if (ret) {
8409 ALOGE("%s: Failed to open output stream for bus device", __func__);
8410 ret = -EINVAL;
8411 goto error_open;
8412 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308413 } else {
8414 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008415 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8416 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308417 }
8418 out->hal_ip_format = format = out->format;
8419 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8420 out->hal_op_format = pcm_format_to_hal(out->config.format);
8421 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8422 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008423 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308424 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308425 if (out->hal_ip_format != out->hal_op_format) {
8426 uint32_t buffer_size = out->config.period_size *
8427 format_to_bitwidth_table[out->hal_op_format] *
8428 out->config.channels;
8429 out->convert_buffer = calloc(1, buffer_size);
8430 if (out->convert_buffer == NULL){
8431 ALOGE("Allocation failed for convert buffer for size %d",
8432 out->compr_config.fragment_size);
8433 ret = -ENOMEM;
8434 goto error_open;
8435 }
8436 ALOGD("Convert buffer allocated of size %d", buffer_size);
8437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008438 }
8439
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008440 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8441 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308442
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008443 /* TODO remove this hardcoding and check why width is zero*/
8444 if (out->bit_width == 0)
8445 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308446 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008447 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008448 &out->device_list, out->flags,
8449 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308450 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308451 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008452 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008453 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8454 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008455 if(adev->primary_output == NULL)
8456 adev->primary_output = out;
8457 else {
8458 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008459 ret = -EEXIST;
8460 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008461 }
8462 }
8463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464 /* Check if this usecase is already existing */
8465 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008466 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8467 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008468 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008469 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008470 ret = -EEXIST;
8471 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008472 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474 pthread_mutex_unlock(&adev->lock);
8475
8476 out->stream.common.get_sample_rate = out_get_sample_rate;
8477 out->stream.common.set_sample_rate = out_set_sample_rate;
8478 out->stream.common.get_buffer_size = out_get_buffer_size;
8479 out->stream.common.get_channels = out_get_channels;
8480 out->stream.common.get_format = out_get_format;
8481 out->stream.common.set_format = out_set_format;
8482 out->stream.common.standby = out_standby;
8483 out->stream.common.dump = out_dump;
8484 out->stream.common.set_parameters = out_set_parameters;
8485 out->stream.common.get_parameters = out_get_parameters;
8486 out->stream.common.add_audio_effect = out_add_audio_effect;
8487 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8488 out->stream.get_latency = out_get_latency;
8489 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008490#ifdef NO_AUDIO_OUT
8491 out->stream.write = out_write_for_no_output;
8492#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008494#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008495 out->stream.get_render_position = out_get_render_position;
8496 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008497 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498
Haynes Mathew George16081042017-05-31 17:16:49 -07008499 if (out->realtime)
8500 out->af_period_multiplier = af_period_multiplier;
8501 else
8502 out->af_period_multiplier = 1;
8503
Andy Hunga1f48fa2019-07-01 18:14:53 -07008504 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506 out->standby = 1;
Zhou Song1f93fa52020-11-20 13:57:39 +08008507 out->volume_l = PLAYBACK_GAIN_MAX;
8508 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008509 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008510 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008511
8512 config->format = out->stream.common.get_format(&out->stream.common);
8513 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8514 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308515 register_format(out->format, out->supported_formats);
8516 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8517 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518
Aalique Grahame22e49102018-12-18 14:23:57 -08008519 out->error_log = error_log_create(
8520 ERROR_LOG_ENTRIES,
8521 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8522
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308523 /*
8524 By locking output stream before registering, we allow the callback
8525 to update stream's state only after stream's initial state is set to
8526 adev state.
8527 */
8528 lock_output_stream(out);
8529 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8530 pthread_mutex_lock(&adev->lock);
8531 out->card_status = adev->card_status;
8532 pthread_mutex_unlock(&adev->lock);
8533 pthread_mutex_unlock(&out->lock);
8534
Aalique Grahame22e49102018-12-18 14:23:57 -08008535 stream_app_type_cfg_init(&out->app_type_cfg);
8536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008537 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308538 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008539 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008540
8541 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8542 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8543 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008544 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308545 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008546 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008547 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308548 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8549 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008550 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8551 out->usecase, PCM_PLAYBACK);
8552 hdlr_stream_cfg.flags = out->flags;
8553 hdlr_stream_cfg.type = PCM_PLAYBACK;
8554 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8555 &hdlr_stream_cfg);
8556 if (ret) {
8557 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8558 out->adsp_hdlr_stream_handle = NULL;
8559 }
8560 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308561 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8562 is_direct_passthough, false);
8563 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8564 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008565 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008566 if (ret < 0) {
8567 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8568 out->ip_hdlr_handle = NULL;
8569 }
8570 }
Derek Chenf939fb72018-11-13 13:34:41 -08008571
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008572 ret = io_streams_map_insert(adev, &out->stream.common,
8573 out->handle, AUDIO_PATCH_HANDLE_NONE);
8574 if (ret != 0)
8575 goto error_open;
8576
Derek Chenf939fb72018-11-13 13:34:41 -08008577 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8578 calloc(1, sizeof(streams_output_ctxt_t));
8579 if (out_ctxt == NULL) {
8580 ALOGE("%s fail to allocate output ctxt", __func__);
8581 ret = -ENOMEM;
8582 goto error_open;
8583 }
8584 out_ctxt->output = out;
8585
8586 pthread_mutex_lock(&adev->lock);
8587 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8588 pthread_mutex_unlock(&adev->lock);
8589
Eric Laurent994a6932013-07-17 11:51:42 -07008590 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008591 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008592
8593error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308594 if (out->convert_buffer)
8595 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008596 free(out);
8597 *stream_out = NULL;
8598 ALOGD("%s: exit: ret %d", __func__, ret);
8599 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008600}
8601
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308602void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008603 struct audio_stream_out *stream)
8604{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008605 struct stream_out *out = (struct stream_out *)stream;
8606 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008607 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008608
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008609 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308610
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008611 io_streams_map_remove(adev, out->handle);
8612
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308613 // must deregister from sndmonitor first to prevent races
8614 // between the callback and close_stream
8615 audio_extn_snd_mon_unregister_listener(out);
8616
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008617 /* close adsp hdrl session before standby */
8618 if (out->adsp_hdlr_stream_handle) {
8619 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8620 if (ret)
8621 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8622 out->adsp_hdlr_stream_handle = NULL;
8623 }
8624
Manish Dewangan21a850a2017-08-14 12:03:55 +05308625 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008626 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8627 out->ip_hdlr_handle = NULL;
8628 }
8629
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008630 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308631 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008632 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308633 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308634 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008635 if(ret != 0)
8636 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8637 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008638 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008639 out_standby(&stream->common);
8640
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008641 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008642 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008643 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008644 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008645 if (out->compr_config.codec != NULL)
8646 free(out->compr_config.codec);
8647 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008648
Zhou Song1f93fa52020-11-20 13:57:39 +08008649 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308650
Varun Balaraje49253e2017-07-06 19:48:56 +05308651 if (is_interactive_usecase(out->usecase))
8652 free_interactive_usecase(adev, out->usecase);
8653
Ashish Jain83a6cc22016-06-28 14:34:17 +05308654 if (out->convert_buffer != NULL) {
8655 free(out->convert_buffer);
8656 out->convert_buffer = NULL;
8657 }
8658
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008659 if (adev->voice_tx_output == out)
8660 adev->voice_tx_output = NULL;
8661
Aalique Grahame22e49102018-12-18 14:23:57 -08008662 error_log_destroy(out->error_log);
8663 out->error_log = NULL;
8664
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308665 if (adev->primary_output == out)
8666 adev->primary_output = NULL;
8667
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008668 pthread_cond_destroy(&out->cond);
8669 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008670 pthread_mutex_destroy(&out->pre_lock);
8671 pthread_mutex_destroy(&out->latch_lock);
8672 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008673
8674 pthread_mutex_lock(&adev->lock);
8675 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8676 if (out_ctxt != NULL) {
8677 list_remove(&out_ctxt->list);
8678 free(out_ctxt);
8679 } else {
8680 ALOGW("%s, output stream already closed", __func__);
8681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008682 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008683 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008684 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008685}
8686
8687static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8688{
8689 struct audio_device *adev = (struct audio_device *)dev;
8690 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008691 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008692 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008693 int ret;
8694 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008695 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008696 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008697 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008698
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008699 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008700 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008701
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308702 if (!parms)
8703 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308704
Derek Chen6f293672019-04-01 01:40:24 -07008705 /* notify adev and input/output streams on the snd card status */
8706 adev_snd_mon_cb((void *)adev, parms);
8707
8708 list_for_each(node, &adev->active_outputs_list) {
8709 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8710 streams_output_ctxt_t,
8711 list);
8712 out_snd_mon_cb((void *)out_ctxt->output, parms);
8713 }
8714
8715 list_for_each(node, &adev->active_inputs_list) {
8716 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8717 streams_input_ctxt_t,
8718 list);
8719 in_snd_mon_cb((void *)in_ctxt->input, parms);
8720 }
8721
Zhou Songd6d71752019-05-21 18:08:51 +08008722 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308723 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8724 if (ret >= 0) {
8725 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008726 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308727 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008728 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308729 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008730 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008731 }
8732 }
8733
8734 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008735 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008736 if (!strncmp(value, "false", 5) &&
8737 audio_extn_a2dp_source_is_suspended()) {
8738 struct audio_usecase *usecase;
8739 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008740 list_for_each(node, &adev->usecase_list) {
8741 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008742 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008743 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008744 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008745 reassign_device_list(&usecase->stream.in->device_list,
8746 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008747 select_devices(adev, usecase->id);
8748 }
Zhou Songd6d71752019-05-21 18:08:51 +08008749 }
8750 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308751 }
8752
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008753 status = voice_set_parameters(adev, parms);
8754 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008755 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008756
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008757 status = platform_set_parameters(adev->platform, parms);
8758 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008759 goto done;
8760
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008761 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8762 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008763 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008764 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8765 adev->bluetooth_nrec = true;
8766 else
8767 adev->bluetooth_nrec = false;
8768 }
8769
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008770 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8771 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008772 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8773 adev->screen_off = false;
8774 else
8775 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008776 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008777 }
8778
Eric Laurent4b084132018-10-19 17:33:43 -07008779 ret = str_parms_get_int(parms, "rotation", &val);
8780 if (ret >= 0) {
8781 bool reverse_speakers = false;
8782 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8783 switch (val) {
8784 // FIXME: note that the code below assumes that the speakers are in the correct placement
8785 // relative to the user when the device is rotated 90deg from its default rotation. This
8786 // assumption is device-specific, not platform-specific like this code.
8787 case 270:
8788 reverse_speakers = true;
8789 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8790 break;
8791 case 0:
8792 case 180:
8793 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8794 break;
8795 case 90:
8796 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8797 break;
8798 default:
8799 ALOGE("%s: unexpected rotation of %d", __func__, val);
8800 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008801 }
Eric Laurent4b084132018-10-19 17:33:43 -07008802 if (status == 0) {
8803 // check and set swap
8804 // - check if orientation changed and speaker active
8805 // - set rotation and cache the rotation value
8806 adev->camera_orientation =
8807 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8808 if (!audio_extn_is_maxx_audio_enabled())
8809 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8810 }
8811 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008812
Mingming Yin514a8bc2014-07-29 15:22:21 -07008813 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8814 if (ret >= 0) {
8815 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8816 adev->bt_wb_speech_enabled = true;
8817 else
8818 adev->bt_wb_speech_enabled = false;
8819 }
8820
Zhou Song12c29502019-03-16 10:37:18 +08008821 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8822 if (ret >= 0) {
8823 val = atoi(value);
8824 adev->swb_speech_mode = val;
8825 }
8826
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008827 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8828 if (ret >= 0) {
8829 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308830 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008831 if (audio_is_output_device(val) &&
8832 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008833 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008834 platform_get_controller_stream_from_params(parms, &controller, &stream);
8835 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8836 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008837 if (ret < 0) {
8838 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308839 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008840 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008841 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308842 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008843 /*
8844 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8845 * Per AudioPolicyManager, USB device is higher priority than WFD.
8846 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8847 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8848 * starting voice call on USB
8849 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008850 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308851 if (ret >= 0)
8852 audio_extn_usb_add_device(device, atoi(value));
8853
Zhou Song6f862822017-11-06 17:27:57 +08008854 if (!audio_extn_usb_is_tunnel_supported()) {
8855 ALOGV("detected USB connect .. disable proxy");
8856 adev->allow_afe_proxy_usage = false;
8857 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008858 }
8859 }
8860
8861 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8862 if (ret >= 0) {
8863 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308864 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008865 /*
8866 * The HDMI / Displayport disconnect handling has been moved to
8867 * audio extension to ensure that its parameters are not
8868 * invalidated prior to updating sysfs of the disconnect event
8869 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8870 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308871 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008872 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308873 if (ret >= 0)
8874 audio_extn_usb_remove_device(device, atoi(value));
8875
Zhou Song6f862822017-11-06 17:27:57 +08008876 if (!audio_extn_usb_is_tunnel_supported()) {
8877 ALOGV("detected USB disconnect .. enable proxy");
8878 adev->allow_afe_proxy_usage = true;
8879 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008880 }
8881 }
8882
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008883 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008884
8885 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008886 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308887 struct audio_usecase *usecase;
8888 struct listnode *node;
8889 list_for_each(node, &adev->usecase_list) {
8890 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008891 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8892 continue;
8893
8894 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308895 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308896 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308897 ALOGD("Switching to speaker and muting the stream before select_devices");
8898 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308899 //force device switch to re configure encoder
8900 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308901 ALOGD("Unmuting the stream after select_devices");
Zhou Song1f93fa52020-11-20 13:57:39 +08008902 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308903 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308904 break;
Zhou Song9ebf6792020-09-23 22:49:01 +08008905 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008906 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08008907 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008908 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8909 reassign_device_list(&usecase->stream.out->device_list,
8910 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8911 check_a2dp_restore_l(adev, usecase->stream.out, true);
8912 break;
8913 }
8914 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308915 }
8916 }
8917 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008918
8919 //handle vr audio setparam
8920 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8921 value, sizeof(value));
8922 if (ret >= 0) {
8923 ALOGI("Setting vr mode to be %s", value);
8924 if (!strncmp(value, "true", 4)) {
8925 adev->vr_audio_mode_enabled = true;
8926 ALOGI("Setting vr mode to true");
8927 } else if (!strncmp(value, "false", 5)) {
8928 adev->vr_audio_mode_enabled = false;
8929 ALOGI("Setting vr mode to false");
8930 } else {
8931 ALOGI("wrong vr mode set");
8932 }
8933 }
8934
Eric Laurent4b084132018-10-19 17:33:43 -07008935 //FIXME: to be replaced by proper video capture properties API
8936 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8937 if (ret >= 0) {
8938 int camera_facing = CAMERA_FACING_BACK;
8939 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8940 camera_facing = CAMERA_FACING_FRONT;
8941 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8942 camera_facing = CAMERA_FACING_BACK;
8943 else {
8944 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8945 goto done;
8946 }
8947 adev->camera_orientation =
8948 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8949 struct audio_usecase *usecase;
8950 struct listnode *node;
8951 list_for_each(node, &adev->usecase_list) {
8952 usecase = node_to_item(node, struct audio_usecase, list);
8953 struct stream_in *in = usecase->stream.in;
8954 if (usecase->type == PCM_CAPTURE && in != NULL &&
8955 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8956 select_devices(adev, in->usecase);
8957 }
8958 }
8959 }
8960
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308961 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008962done:
8963 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008964 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308965error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008966 ALOGV("%s: exit with code(%d)", __func__, status);
8967 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008968}
8969
8970static char* adev_get_parameters(const struct audio_hw_device *dev,
8971 const char *keys)
8972{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308973 ALOGD("%s:%s", __func__, keys);
8974
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008975 struct audio_device *adev = (struct audio_device *)dev;
8976 struct str_parms *reply = str_parms_create();
8977 struct str_parms *query = str_parms_create_str(keys);
8978 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308979 char value[256] = {0};
8980 int ret = 0;
8981
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008982 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008983 if (reply) {
8984 str_parms_destroy(reply);
8985 }
8986 if (query) {
8987 str_parms_destroy(query);
8988 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008989 ALOGE("adev_get_parameters: failed to create query or reply");
8990 return NULL;
8991 }
8992
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008993 //handle vr audio getparam
8994
8995 ret = str_parms_get_str(query,
8996 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8997 value, sizeof(value));
8998
8999 if (ret >= 0) {
9000 bool vr_audio_enabled = false;
9001 pthread_mutex_lock(&adev->lock);
9002 vr_audio_enabled = adev->vr_audio_mode_enabled;
9003 pthread_mutex_unlock(&adev->lock);
9004
9005 ALOGI("getting vr mode to %d", vr_audio_enabled);
9006
9007 if (vr_audio_enabled) {
9008 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9009 "true");
9010 goto exit;
9011 } else {
9012 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9013 "false");
9014 goto exit;
9015 }
9016 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009017
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009018 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009019 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009020 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009021 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009022 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009023 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309024 pthread_mutex_unlock(&adev->lock);
9025
Naresh Tannirud7205b62014-06-20 02:54:48 +05309026exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009027 str = str_parms_to_str(reply);
9028 str_parms_destroy(query);
9029 str_parms_destroy(reply);
9030
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309031 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009032 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009033}
9034
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009035static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036{
9037 return 0;
9038}
9039
9040static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9041{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009042 int ret;
9043 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009044
9045 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9046
Haynes Mathew George5191a852013-09-11 14:19:36 -07009047 pthread_mutex_lock(&adev->lock);
9048 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009049 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009050 pthread_mutex_unlock(&adev->lock);
9051 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009052}
9053
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009054static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9055 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009056{
9057 return -ENOSYS;
9058}
9059
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009060static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9061 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009062{
9063 return -ENOSYS;
9064}
9065
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009066static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9067 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009068{
9069 return -ENOSYS;
9070}
9071
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009072static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9073 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009074{
9075 return -ENOSYS;
9076}
9077
9078static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9079{
9080 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009081 struct listnode *node;
9082 struct audio_usecase *usecase = NULL;
9083 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009085 pthread_mutex_lock(&adev->lock);
9086 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309087 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9088 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009089 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009090 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309091 adev->current_call_output = adev->primary_output;
9092 voice_start_call(adev);
9093 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009094 (mode == AUDIO_MODE_NORMAL ||
9095 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009096 list_for_each(node, &adev->usecase_list) {
9097 usecase = node_to_item(node, struct audio_usecase, list);
9098 if (usecase->type == VOICE_CALL)
9099 break;
9100 }
9101 if (usecase &&
9102 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9103 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9104 true);
9105 if (ret != 0) {
9106 /* default service interval was successfully updated,
9107 reopen USB backend with new service interval */
9108 check_usecases_codec_backend(adev,
9109 usecase,
9110 usecase->out_snd_device);
9111 }
9112 }
9113
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009114 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009115 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009116 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009117 // restore device for other active usecases after stop call
9118 list_for_each(node, &adev->usecase_list) {
9119 usecase = node_to_item(node, struct audio_usecase, list);
9120 select_devices(adev, usecase->id);
9121 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123 }
9124 pthread_mutex_unlock(&adev->lock);
9125 return 0;
9126}
9127
9128static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9129{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009130 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009131 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009132
9133 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009134 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009135 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009136
Derek Chend2530072014-11-24 12:39:14 -08009137 if (adev->ext_hw_plugin)
9138 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009139
9140 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009141 pthread_mutex_unlock(&adev->lock);
9142
9143 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144}
9145
9146static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9147{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009148 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149 return 0;
9150}
9151
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009152static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009153 const struct audio_config *config)
9154{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009155 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156
Aalique Grahame22e49102018-12-18 14:23:57 -08009157 /* Don't know if USB HIFI in this context so use true to be conservative */
9158 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9159 true /*is_usb_hifi */) != 0)
9160 return 0;
9161
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009162 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9163 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009164}
9165
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009166static bool adev_input_allow_hifi_record(struct audio_device *adev,
9167 audio_devices_t devices,
9168 audio_input_flags_t flags,
9169 audio_source_t source) {
9170 const bool allowed = true;
9171
9172 if (!audio_is_usb_in_device(devices))
9173 return !allowed;
9174
9175 switch (flags) {
9176 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009177 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009178 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9179 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009180 default:
9181 return !allowed;
9182 }
9183
9184 switch (source) {
9185 case AUDIO_SOURCE_DEFAULT:
9186 case AUDIO_SOURCE_MIC:
9187 case AUDIO_SOURCE_UNPROCESSED:
9188 break;
9189 default:
9190 return !allowed;
9191 }
9192
9193 switch (adev->mode) {
9194 case 0:
9195 break;
9196 default:
9197 return !allowed;
9198 }
9199
9200 return allowed;
9201}
9202
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009203static int adev_update_voice_comm_input_stream(struct stream_in *in,
9204 struct audio_config *config)
9205{
9206 bool valid_rate = (config->sample_rate == 8000 ||
9207 config->sample_rate == 16000 ||
9208 config->sample_rate == 32000 ||
9209 config->sample_rate == 48000);
9210 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9211
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009212 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009213 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009214 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9215 in->config = default_pcm_config_voip_copp;
9216 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9217 DEFAULT_VOIP_BUF_DURATION_MS,
9218 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009219 } else {
9220 ALOGW("%s No valid input in voip, use defaults"
9221 "sample rate %u, channel mask 0x%X",
9222 __func__, config->sample_rate, in->channel_mask);
9223 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009224 in->config.rate = config->sample_rate;
9225 in->sample_rate = config->sample_rate;
9226 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009227 //XXX needed for voice_extn_compress_voip_open_input_stream
9228 in->config.rate = config->sample_rate;
9229 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309230 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009231 voice_extn_compress_voip_is_active(in->dev)) &&
9232 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9233 valid_rate && valid_ch) {
9234 voice_extn_compress_voip_open_input_stream(in);
9235 // update rate entries to match config from AF
9236 in->config.rate = config->sample_rate;
9237 in->sample_rate = config->sample_rate;
9238 } else {
9239 ALOGW("%s compress voip not active, use defaults", __func__);
9240 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009241 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009242 return 0;
9243}
9244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009245static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009246 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009247 audio_devices_t devices,
9248 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009249 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309250 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009251 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009252 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009253{
9254 struct audio_device *adev = (struct audio_device *)dev;
9255 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009256 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009257 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009258 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309259 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009260 bool is_usb_dev = audio_is_usb_in_device(devices);
9261 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9262 devices,
9263 flags,
9264 source);
Andy Hung94320602018-10-29 18:31:12 -07009265 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9266 " sample_rate %u, channel_mask %#x, format %#x",
9267 __func__, flags, is_usb_dev, may_use_hifi_record,
9268 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309269
kunleizdff872d2018-08-20 14:40:33 +08009270 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009271 is_usb_dev = false;
9272 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9273 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9274 __func__, devices);
9275 }
9276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009277 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009278
9279 if (!(is_usb_dev && may_use_hifi_record)) {
9280 if (config->sample_rate == 0)
9281 config->sample_rate = 48000;
9282 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9283 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9284 if (config->format == AUDIO_FORMAT_DEFAULT)
9285 config->format = AUDIO_FORMAT_PCM_16_BIT;
9286
9287 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9288
Aalique Grahame22e49102018-12-18 14:23:57 -08009289 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9290 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009291 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009293
Rahul Sharma99770982019-03-06 17:05:26 +05309294 pthread_mutex_lock(&adev->lock);
9295 if (in_get_stream(adev, handle) != NULL) {
9296 ALOGW("%s, input stream already opened", __func__);
9297 ret = -EEXIST;
9298 }
9299 pthread_mutex_unlock(&adev->lock);
9300 if (ret)
9301 return ret;
9302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009303 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009304
9305 if (!in) {
9306 ALOGE("failed to allocate input stream");
9307 return -ENOMEM;
9308 }
9309
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309310 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309311 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9312 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009313 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009314 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009316 in->stream.common.get_sample_rate = in_get_sample_rate;
9317 in->stream.common.set_sample_rate = in_set_sample_rate;
9318 in->stream.common.get_buffer_size = in_get_buffer_size;
9319 in->stream.common.get_channels = in_get_channels;
9320 in->stream.common.get_format = in_get_format;
9321 in->stream.common.set_format = in_set_format;
9322 in->stream.common.standby = in_standby;
9323 in->stream.common.dump = in_dump;
9324 in->stream.common.set_parameters = in_set_parameters;
9325 in->stream.common.get_parameters = in_get_parameters;
9326 in->stream.common.add_audio_effect = in_add_audio_effect;
9327 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9328 in->stream.set_gain = in_set_gain;
9329 in->stream.read = in_read;
9330 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009331 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309332 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009333 in->stream.set_microphone_direction = in_set_microphone_direction;
9334 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009335 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009336
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009337 list_init(&in->device_list);
9338 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009339 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009340 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009341 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009342 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009343 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009344 in->bit_width = 16;
9345 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009346 in->direction = MIC_DIRECTION_UNSPECIFIED;
9347 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009348 list_init(&in->aec_list);
9349 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009350 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009351
Andy Hung94320602018-10-29 18:31:12 -07009352 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009353 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9354 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9355 /* Force channel config requested to mono if incall
9356 record is being requested for only uplink/downlink */
9357 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9358 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9359 ret = -EINVAL;
9360 goto err_open;
9361 }
9362 }
9363
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009364 if (is_usb_dev && may_use_hifi_record) {
9365 /* HiFi record selects an appropriate format, channel, rate combo
9366 depending on sink capabilities*/
9367 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9368 &config->format,
9369 &in->supported_formats[0],
9370 MAX_SUPPORTED_FORMATS,
9371 &config->channel_mask,
9372 &in->supported_channel_masks[0],
9373 MAX_SUPPORTED_CHANNEL_MASKS,
9374 &config->sample_rate,
9375 &in->supported_sample_rates[0],
9376 MAX_SUPPORTED_SAMPLE_RATES);
9377 if (ret != 0) {
9378 ret = -EINVAL;
9379 goto err_open;
9380 }
9381 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009382 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309383 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309384 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9385 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9386 in->config.format = PCM_FORMAT_S32_LE;
9387 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309388 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9389 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9390 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9391 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9392 bool ret_error = false;
9393 in->bit_width = 24;
9394 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9395 from HAL is 24_packed and 8_24
9396 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9397 24_packed return error indicating supported format is 24_packed
9398 *> In case of any other source requesting 24 bit or float return error
9399 indicating format supported is 16 bit only.
9400
9401 on error flinger will retry with supported format passed
9402 */
9403 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9404 (source != AUDIO_SOURCE_CAMCORDER)) {
9405 config->format = AUDIO_FORMAT_PCM_16_BIT;
9406 if (config->sample_rate > 48000)
9407 config->sample_rate = 48000;
9408 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009409 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9410 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309411 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9412 ret_error = true;
9413 }
9414
9415 if (ret_error) {
9416 ret = -EINVAL;
9417 goto err_open;
9418 }
9419 }
9420
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009421 in->channel_mask = config->channel_mask;
9422 in->format = config->format;
9423
9424 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309425
9426 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9427 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9428 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9429 else {
9430 ret = -EINVAL;
9431 goto err_open;
9432 }
9433 }
9434
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009435 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309436 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9437 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009438 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9439 is_low_latency = true;
9440#if LOW_LATENCY_CAPTURE_USE_CASE
9441 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9442#endif
9443 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009444 if (!in->realtime) {
9445 in->config = pcm_config_audio_capture;
9446 frame_size = audio_stream_in_frame_size(&in->stream);
9447 buffer_size = get_input_buffer_size(config->sample_rate,
9448 config->format,
9449 channel_count,
9450 is_low_latency);
9451 in->config.period_size = buffer_size / frame_size;
9452 in->config.rate = config->sample_rate;
9453 in->af_period_multiplier = 1;
9454 } else {
9455 // period size is left untouched for rt mode playback
9456 in->config = pcm_config_audio_capture_rt;
9457 in->af_period_multiplier = af_period_multiplier;
9458 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009459 }
9460
9461 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9462 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9463 in->realtime = 0;
9464 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9465 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009466 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009467 in->stream.start = in_start;
9468 in->stream.stop = in_stop;
9469 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9470 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009471 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009472 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009473 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9474 in->config = pcm_config_audio_capture;
9475 frame_size = audio_stream_in_frame_size(&in->stream);
9476 buffer_size = get_input_buffer_size(config->sample_rate,
9477 config->format,
9478 channel_count,
9479 false /*is_low_latency*/);
9480 in->config.period_size = buffer_size / frame_size;
9481 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009482 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009483 switch (config->format) {
9484 case AUDIO_FORMAT_PCM_32_BIT:
9485 in->bit_width = 32;
9486 break;
9487 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9488 case AUDIO_FORMAT_PCM_8_24_BIT:
9489 in->bit_width = 24;
9490 break;
9491 default:
9492 in->bit_width = 16;
9493 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009494 } else if (is_single_device_type_equal(&in->device_list,
9495 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9496 is_single_device_type_equal(&in->device_list,
9497 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009498 if (config->sample_rate == 0)
9499 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9500 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9501 config->sample_rate != 8000) {
9502 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9503 ret = -EINVAL;
9504 goto err_open;
9505 }
9506 if (config->format == AUDIO_FORMAT_DEFAULT)
9507 config->format = AUDIO_FORMAT_PCM_16_BIT;
9508 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9509 config->format = AUDIO_FORMAT_PCM_16_BIT;
9510 ret = -EINVAL;
9511 goto err_open;
9512 }
9513
9514 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009515 if (adev->ha_proxy_enable &&
9516 is_single_device_type_equal(&in->device_list,
9517 AUDIO_DEVICE_IN_TELEPHONY_RX))
9518 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009519 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009520 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009521 in->af_period_multiplier = 1;
9522 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9523 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9524 (config->sample_rate == 8000 ||
9525 config->sample_rate == 16000 ||
9526 config->sample_rate == 32000 ||
9527 config->sample_rate == 48000) &&
9528 channel_count == 1) {
9529 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9530 in->config = pcm_config_audio_capture;
9531 frame_size = audio_stream_in_frame_size(&in->stream);
9532 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9533 config->sample_rate,
9534 config->format,
9535 channel_count, false /*is_low_latency*/);
9536 in->config.period_size = buffer_size / frame_size;
9537 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9538 in->config.rate = config->sample_rate;
9539 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009540 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309541 int ret_val;
9542 pthread_mutex_lock(&adev->lock);
9543 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9544 in, config, &channel_mask_updated);
9545 pthread_mutex_unlock(&adev->lock);
9546
9547 if (!ret_val) {
9548 if (channel_mask_updated == true) {
9549 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9550 __func__, config->channel_mask);
9551 ret = -EINVAL;
9552 goto err_open;
9553 }
9554 ALOGD("%s: created multi-channel session succesfully",__func__);
9555 } else if (audio_extn_compr_cap_enabled() &&
9556 audio_extn_compr_cap_format_supported(config->format) &&
9557 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9558 audio_extn_compr_cap_init(in);
9559 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309560 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309561 if (ret)
9562 goto err_open;
9563 } else {
9564 in->config = pcm_config_audio_capture;
9565 in->config.rate = config->sample_rate;
9566 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309567 in->format = config->format;
9568 frame_size = audio_stream_in_frame_size(&in->stream);
9569 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009570 config->format,
9571 channel_count,
9572 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009573 /* prevent division-by-zero */
9574 if (frame_size == 0) {
9575 ALOGE("%s: Error frame_size==0", __func__);
9576 ret = -EINVAL;
9577 goto err_open;
9578 }
9579
Revathi Uddarajud2634032017-12-07 14:42:34 +05309580 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009581 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009582
Revathi Uddarajud2634032017-12-07 14:42:34 +05309583 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9584 /* optionally use VOIP usecase depending on config(s) */
9585 ret = adev_update_voice_comm_input_stream(in, config);
9586 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009587
Revathi Uddarajud2634032017-12-07 14:42:34 +05309588 if (ret) {
9589 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9590 goto err_open;
9591 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009592 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309593
9594 /* assign concurrent capture usecase if record has to caried out from
9595 * actual hardware input source */
9596 if (audio_extn_is_concurrent_capture_enabled() &&
9597 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309598 /* Acquire lock to avoid two concurrent use cases initialized to
9599 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009600
Samyak Jainc37062f2019-04-25 18:41:06 +05309601 if (in->usecase == USECASE_AUDIO_RECORD) {
9602 pthread_mutex_lock(&adev->lock);
9603 if (!(adev->pcm_record_uc_state)) {
9604 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9605 adev->pcm_record_uc_state = 1;
9606 pthread_mutex_unlock(&adev->lock);
9607 } else {
9608 pthread_mutex_unlock(&adev->lock);
9609 /* Assign compress record use case for second record */
9610 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9611 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9612 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9613 if (audio_extn_cin_applicable_stream(in)) {
9614 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309615 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309616 if (ret)
9617 goto err_open;
9618 }
9619 }
9620 }
kunleiz28c73e72019-03-27 17:24:04 +08009621 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009622 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309623 if (audio_extn_ssr_get_stream() != in)
9624 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009625
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009626 in->sample_rate = in->config.rate;
9627
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309628 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9629 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009630 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009631 in->sample_rate, in->bit_width,
9632 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309633 register_format(in->format, in->supported_formats);
9634 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9635 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309636
Aalique Grahame22e49102018-12-18 14:23:57 -08009637 in->error_log = error_log_create(
9638 ERROR_LOG_ENTRIES,
9639 1000000000 /* aggregate consecutive identical errors within one second */);
9640
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009641 /* This stream could be for sound trigger lab,
9642 get sound trigger pcm if present */
9643 audio_extn_sound_trigger_check_and_get_session(in);
9644
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309645 lock_input_stream(in);
9646 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9647 pthread_mutex_lock(&adev->lock);
9648 in->card_status = adev->card_status;
9649 pthread_mutex_unlock(&adev->lock);
9650 pthread_mutex_unlock(&in->lock);
9651
Aalique Grahame22e49102018-12-18 14:23:57 -08009652 stream_app_type_cfg_init(&in->app_type_cfg);
9653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009654 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009655
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009656 ret = io_streams_map_insert(adev, &in->stream.common,
9657 handle, AUDIO_PATCH_HANDLE_NONE);
9658 if (ret != 0)
9659 goto err_open;
9660
Derek Chenf939fb72018-11-13 13:34:41 -08009661 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9662 calloc(1, sizeof(streams_input_ctxt_t));
9663 if (in_ctxt == NULL) {
9664 ALOGE("%s fail to allocate input ctxt", __func__);
9665 ret = -ENOMEM;
9666 goto err_open;
9667 }
9668 in_ctxt->input = in;
9669
9670 pthread_mutex_lock(&adev->lock);
9671 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9672 pthread_mutex_unlock(&adev->lock);
9673
Eric Laurent994a6932013-07-17 11:51:42 -07009674 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009675 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009676
9677err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309678 if (in->usecase == USECASE_AUDIO_RECORD) {
9679 pthread_mutex_lock(&adev->lock);
9680 adev->pcm_record_uc_state = 0;
9681 pthread_mutex_unlock(&adev->lock);
9682 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009683 free(in);
9684 *stream_in = NULL;
9685 return ret;
9686}
9687
9688static void adev_close_input_stream(struct audio_hw_device *dev,
9689 struct audio_stream_in *stream)
9690{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009691 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009692 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009693 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309694
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309695 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009696
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009697 if (in == NULL) {
9698 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9699 return;
9700 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009701 io_streams_map_remove(adev, in->capture_handle);
9702
kunleiz70e57612018-12-28 17:50:23 +08009703 /* must deregister from sndmonitor first to prevent races
9704 * between the callback and close_stream
9705 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309706 audio_extn_snd_mon_unregister_listener(stream);
9707
kunleiz70e57612018-12-28 17:50:23 +08009708 /* Disable echo reference if there are no active input, hfp call
9709 * and sound trigger while closing input stream
9710 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009711 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009712 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009713 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9714 struct listnode out_devices;
9715 list_init(&out_devices);
9716 platform_set_echo_reference(adev, false, &out_devices);
9717 } else
kunleiz70e57612018-12-28 17:50:23 +08009718 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309719
Weiyin Jiang2995f662019-04-17 14:25:12 +08009720 error_log_destroy(in->error_log);
9721 in->error_log = NULL;
9722
Pallavid7c7a272018-01-16 11:22:55 +05309723
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009724 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309725 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009726 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309727 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009728 if (ret != 0)
9729 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9730 __func__, ret);
9731 } else
9732 in_standby(&stream->common);
9733
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009734 pthread_mutex_destroy(&in->lock);
9735 pthread_mutex_destroy(&in->pre_lock);
9736
Revathi Uddarajud2634032017-12-07 14:42:34 +05309737 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309738 if (in->usecase == USECASE_AUDIO_RECORD) {
9739 adev->pcm_record_uc_state = 0;
9740 }
9741
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009742 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9743 adev->enable_voicerx = false;
9744 }
9745
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009746 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009747 audio_extn_ssr_deinit();
9748 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009749
Garmond Leunge2433c32017-09-28 21:51:22 -07009750 if (audio_extn_ffv_get_stream() == in) {
9751 audio_extn_ffv_stream_deinit();
9752 }
9753
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309754 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009755 audio_extn_compr_cap_format_supported(in->config.format))
9756 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309757
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309758 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309759 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009760
Mingming Yinfd7607b2016-01-22 12:48:44 -08009761 if (in->is_st_session) {
9762 ALOGV("%s: sound trigger pcm stop lab", __func__);
9763 audio_extn_sound_trigger_stop_lab(in);
9764 }
Derek Chenf939fb72018-11-13 13:34:41 -08009765 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9766 if (in_ctxt != NULL) {
9767 list_remove(&in_ctxt->list);
9768 free(in_ctxt);
9769 } else {
9770 ALOGW("%s, input stream already closed", __func__);
9771 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009772 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309773 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009774 return;
9775}
9776
Aalique Grahame22e49102018-12-18 14:23:57 -08009777/* verifies input and output devices and their capabilities.
9778 *
9779 * This verification is required when enabling extended bit-depth or
9780 * sampling rates, as not all qcom products support it.
9781 *
9782 * Suitable for calling only on initialization such as adev_open().
9783 * It fills the audio_device use_case_table[] array.
9784 *
9785 * Has a side-effect that it needs to configure audio routing / devices
9786 * in order to power up the devices and read the device parameters.
9787 * It does not acquire any hw device lock. Should restore the devices
9788 * back to "normal state" upon completion.
9789 */
9790static int adev_verify_devices(struct audio_device *adev)
9791{
9792 /* enumeration is a bit difficult because one really wants to pull
9793 * the use_case, device id, etc from the hidden pcm_device_table[].
9794 * In this case there are the following use cases and device ids.
9795 *
9796 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9797 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9798 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9799 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9800 * [USECASE_AUDIO_RECORD] = {0, 0},
9801 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9802 * [USECASE_VOICE_CALL] = {2, 2},
9803 *
9804 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9805 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9806 */
9807
9808 /* should be the usecases enabled in adev_open_input_stream() */
9809 static const int test_in_usecases[] = {
9810 USECASE_AUDIO_RECORD,
9811 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9812 };
9813 /* should be the usecases enabled in adev_open_output_stream()*/
9814 static const int test_out_usecases[] = {
9815 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9816 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9817 };
9818 static const usecase_type_t usecase_type_by_dir[] = {
9819 PCM_PLAYBACK,
9820 PCM_CAPTURE,
9821 };
9822 static const unsigned flags_by_dir[] = {
9823 PCM_OUT,
9824 PCM_IN,
9825 };
9826
9827 size_t i;
9828 unsigned dir;
9829 const unsigned card_id = adev->snd_card;
9830
9831 for (dir = 0; dir < 2; ++dir) {
9832 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9833 const unsigned flags_dir = flags_by_dir[dir];
9834 const size_t testsize =
9835 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9836 const int *testcases =
9837 dir ? test_in_usecases : test_out_usecases;
9838 const audio_devices_t audio_device =
9839 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9840
9841 for (i = 0; i < testsize; ++i) {
9842 const audio_usecase_t audio_usecase = testcases[i];
9843 int device_id;
9844 struct pcm_params **pparams;
9845 struct stream_out out;
9846 struct stream_in in;
9847 struct audio_usecase uc_info;
9848 int retval;
9849
9850 pparams = &adev->use_case_table[audio_usecase];
9851 pcm_params_free(*pparams); /* can accept null input */
9852 *pparams = NULL;
9853
9854 /* find the device ID for the use case (signed, for error) */
9855 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9856 if (device_id < 0)
9857 continue;
9858
9859 /* prepare structures for device probing */
9860 memset(&uc_info, 0, sizeof(uc_info));
9861 uc_info.id = audio_usecase;
9862 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009863 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009864 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009865 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009866 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009867 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009868 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9869 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009870 }
9871 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009872 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009873 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009874 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009875 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009876 uc_info.in_snd_device = SND_DEVICE_NONE;
9877 uc_info.out_snd_device = SND_DEVICE_NONE;
9878 list_add_tail(&adev->usecase_list, &uc_info.list);
9879
9880 /* select device - similar to start_(in/out)put_stream() */
9881 retval = select_devices(adev, audio_usecase);
9882 if (retval >= 0) {
9883 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9884#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009885 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009886 if (*pparams) {
9887 ALOGV("%s: (%s) card %d device %d", __func__,
9888 dir ? "input" : "output", card_id, device_id);
9889 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9890 } else {
9891 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9892 }
9893#endif
9894 }
9895
9896 /* deselect device - similar to stop_(in/out)put_stream() */
9897 /* 1. Get and set stream specific mixer controls */
9898 retval = disable_audio_route(adev, &uc_info);
9899 /* 2. Disable the rx device */
9900 retval = disable_snd_device(adev,
9901 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9902 list_remove(&uc_info.list);
9903 }
9904 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009905 return 0;
9906}
9907
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009908int update_patch(unsigned int num_sources,
9909 const struct audio_port_config *sources,
9910 unsigned int num_sinks,
9911 const struct audio_port_config *sinks,
9912 audio_patch_handle_t handle,
9913 struct audio_patch_info *p_info,
9914 patch_type_t patch_type, bool new_patch)
9915{
9916 ALOGD("%s: enter", __func__);
9917
9918 if (p_info == NULL) {
9919 ALOGE("%s: Invalid patch pointer", __func__);
9920 return -EINVAL;
9921 }
9922
9923 if (new_patch) {
9924 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9925 if (p_info->patch == NULL) {
9926 ALOGE("%s: Could not allocate patch", __func__);
9927 return -ENOMEM;
9928 }
9929 }
9930
9931 p_info->patch->id = handle;
9932 p_info->patch->num_sources = num_sources;
9933 p_info->patch->num_sinks = num_sinks;
9934
9935 for (int i = 0; i < num_sources; i++)
9936 p_info->patch->sources[i] = sources[i];
9937 for (int i = 0; i < num_sinks; i++)
9938 p_info->patch->sinks[i] = sinks[i];
9939
9940 p_info->patch_type = patch_type;
9941 return 0;
9942}
9943
9944audio_patch_handle_t generate_patch_handle()
9945{
9946 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9947 if (++patch_handle < 0)
9948 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9949 return patch_handle;
9950}
9951
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309952int adev_create_audio_patch(struct audio_hw_device *dev,
9953 unsigned int num_sources,
9954 const struct audio_port_config *sources,
9955 unsigned int num_sinks,
9956 const struct audio_port_config *sinks,
9957 audio_patch_handle_t *handle)
9958{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009959 int ret = 0;
9960 struct audio_device *adev = (struct audio_device *)dev;
9961 struct audio_patch_info *p_info = NULL;
9962 patch_type_t patch_type = PATCH_NONE;
9963 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9964 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9965 struct audio_stream_info *s_info = NULL;
9966 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009967 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009968 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9969 bool new_patch = false;
9970 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309971
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009972 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9973 num_sources, num_sinks, *handle);
9974
9975 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9976 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9977 ALOGE("%s: Invalid patch arguments", __func__);
9978 ret = -EINVAL;
9979 goto done;
9980 }
9981
9982 if (num_sources > 1) {
9983 ALOGE("%s: Multiple sources are not supported", __func__);
9984 ret = -EINVAL;
9985 goto done;
9986 }
9987
9988 if (sources == NULL || sinks == NULL) {
9989 ALOGE("%s: Invalid sources or sinks port config", __func__);
9990 ret = -EINVAL;
9991 goto done;
9992 }
9993
9994 ALOGV("%s: source role %d, source type %d", __func__,
9995 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009996 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009997
9998 // Populate source/sink information and fetch stream info
9999 switch (sources[0].type) {
10000 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10001 device_type = sources[0].ext.device.type;
10002 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010003 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010004 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10005 patch_type = PATCH_CAPTURE;
10006 io_handle = sinks[0].ext.mix.handle;
10007 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010008 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010009 __func__, device_type, io_handle);
10010 } else {
10011 // Device to device patch is not implemented.
10012 // This space will need changes if audio HAL
10013 // handles device to device patches in the future.
10014 patch_type = PATCH_DEVICE_LOOPBACK;
10015 }
10016 break;
10017 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10018 io_handle = sources[0].ext.mix.handle;
10019 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010020 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010021 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010022 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010023 }
10024 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010025 ALOGD("%s: Playback patch from mix handle %d to device %x",
10026 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010027 break;
10028 case AUDIO_PORT_TYPE_SESSION:
10029 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010030 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10031 ret = -EINVAL;
10032 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010033 }
10034
10035 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010036
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037 // Generate patch info and update patch
10038 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010039 *handle = generate_patch_handle();
10040 p_info = (struct audio_patch_info *)
10041 calloc(1, sizeof(struct audio_patch_info));
10042 if (p_info == NULL) {
10043 ALOGE("%s: Failed to allocate memory", __func__);
10044 pthread_mutex_unlock(&adev->lock);
10045 ret = -ENOMEM;
10046 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010047 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010048 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010050 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 if (p_info == NULL) {
10052 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10053 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010054 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010055 ret = -EINVAL;
10056 goto done;
10057 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010058 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010060 *handle, p_info, patch_type, new_patch);
10061
10062 // Fetch stream info of associated mix for playback or capture patches
10063 if (p_info->patch_type == PATCH_PLAYBACK ||
10064 p_info->patch_type == PATCH_CAPTURE) {
10065 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10066 if (s_info == NULL) {
10067 ALOGE("%s: Failed to obtain stream info", __func__);
10068 if (new_patch)
10069 free(p_info);
10070 pthread_mutex_unlock(&adev->lock);
10071 ret = -EINVAL;
10072 goto done;
10073 }
10074 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10075 s_info->patch_handle = *handle;
10076 stream = s_info->stream;
10077 }
10078 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079
10080 // Update routing for stream
10081 if (stream != NULL) {
10082 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010083 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010084 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010085 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010086 if (ret < 0) {
10087 pthread_mutex_lock(&adev->lock);
10088 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10089 if (new_patch)
10090 free(p_info);
10091 pthread_mutex_unlock(&adev->lock);
10092 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10093 goto done;
10094 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095 }
10096
10097 // Add new patch to patch map
10098 if (!ret && new_patch) {
10099 pthread_mutex_lock(&adev->lock);
10100 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010101 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010102 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010103 }
10104
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105done:
10106 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010107 num_sources,
10108 sources,
10109 num_sinks,
10110 sinks,
10111 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010112 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010113 num_sources,
10114 sources,
10115 num_sinks,
10116 sinks,
10117 handle);
10118 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010119}
10120
10121int adev_release_audio_patch(struct audio_hw_device *dev,
10122 audio_patch_handle_t handle)
10123{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010124 struct audio_device *adev = (struct audio_device *) dev;
10125 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010126 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010127 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010128
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10130 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10131 ret = -EINVAL;
10132 goto done;
10133 }
10134
10135 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010136 pthread_mutex_lock(&adev->lock);
10137 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010138 if (p_info == NULL) {
10139 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010140 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010141 ret = -EINVAL;
10142 goto done;
10143 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144 struct audio_patch *patch = p_info->patch;
10145 if (patch == NULL) {
10146 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010147 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010148 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149 goto done;
10150 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010151 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10152 switch (patch->sources[0].type) {
10153 case AUDIO_PORT_TYPE_MIX:
10154 io_handle = patch->sources[0].ext.mix.handle;
10155 break;
10156 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010157 if (p_info->patch_type == PATCH_CAPTURE)
10158 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010159 break;
10160 case AUDIO_PORT_TYPE_SESSION:
10161 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010162 pthread_mutex_unlock(&adev->lock);
10163 ret = -EINVAL;
10164 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 }
10166
10167 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010168 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010169 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010170 if (patch_type == PATCH_PLAYBACK ||
10171 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010172 struct audio_stream_info *s_info =
10173 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10174 if (s_info == NULL) {
10175 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10176 pthread_mutex_unlock(&adev->lock);
10177 goto done;
10178 }
10179 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10180 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010181 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010182 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010183
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010184 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010185 struct listnode devices;
10186 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010187 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010188 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010189 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010190 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010191 }
10192
10193 if (ret < 0)
10194 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10195
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010196done:
10197 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10198 audio_extn_auto_hal_release_audio_patch(dev, handle);
10199
10200 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010201 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010202}
10203
10204int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10205{
Derek Chenf13dd492018-11-13 14:53:51 -080010206 int ret = 0;
10207
10208 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10209 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10210 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010211}
10212
10213int adev_set_audio_port_config(struct audio_hw_device *dev,
10214 const struct audio_port_config *config)
10215{
Derek Chenf13dd492018-11-13 14:53:51 -080010216 int ret = 0;
10217
10218 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10219 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10220 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010221}
10222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010223static int adev_dump(const audio_hw_device_t *device __unused,
10224 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010225{
10226 return 0;
10227}
10228
10229static int adev_close(hw_device_t *device)
10230{
Aalique Grahame22e49102018-12-18 14:23:57 -080010231 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010232 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010233
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010234 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010235 return 0;
10236
10237 pthread_mutex_lock(&adev_init_lock);
10238
10239 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010240 if (audio_extn_spkr_prot_is_enabled())
10241 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010242 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010243 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010244 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010245 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010246 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010247 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010248 audio_extn_utils_release_streams_cfg_lists(
10249 &adev->streams_output_cfg_list,
10250 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010251 if (audio_extn_qap_is_enabled())
10252 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010253 if (audio_extn_qaf_is_enabled())
10254 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010255 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010256 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010257 free(adev->snd_dev_ref_cnt);
10258 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010259 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10260 pcm_params_free(adev->use_case_table[i]);
10261 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010262 if (adev->adm_deinit)
10263 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010264 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010265 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010266 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010267 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010268 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010269 if (adev->device_cfg_params) {
10270 free(adev->device_cfg_params);
10271 adev->device_cfg_params = NULL;
10272 }
Derek Chend2530072014-11-24 12:39:14 -080010273 if(adev->ext_hw_plugin)
10274 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010275 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010276 free_map(adev->patch_map);
10277 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010278 free(device);
10279 adev = NULL;
10280 }
10281 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010282 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010283 return 0;
10284}
10285
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010286/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10287 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10288 * just that it _might_ work.
10289 */
10290static int period_size_is_plausible_for_low_latency(int period_size)
10291{
10292 switch (period_size) {
10293 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010294 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010295 case 240:
10296 case 320:
10297 case 480:
10298 return 1;
10299 default:
10300 return 0;
10301 }
10302}
10303
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010304static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10305{
10306 bool is_snd_card_status = false;
10307 bool is_ext_device_status = false;
10308 char value[32];
10309 int card = -1;
10310 card_status_t status;
10311
10312 if (cookie != adev || !parms)
10313 return;
10314
10315 if (!parse_snd_card_status(parms, &card, &status)) {
10316 is_snd_card_status = true;
10317 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10318 is_ext_device_status = true;
10319 } else {
10320 // not a valid event
10321 return;
10322 }
10323
10324 pthread_mutex_lock(&adev->lock);
10325 if (card == adev->snd_card || is_ext_device_status) {
10326 if (is_snd_card_status && adev->card_status != status) {
10327 adev->card_status = status;
10328 platform_snd_card_update(adev->platform, status);
10329 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010330 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010331 if (status == CARD_STATUS_OFFLINE)
10332 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010333 } else if (is_ext_device_status) {
10334 platform_set_parameters(adev->platform, parms);
10335 }
10336 }
10337 pthread_mutex_unlock(&adev->lock);
10338 return;
10339}
10340
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010341/* adev lock held */
10342int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010343{
10344 struct audio_usecase *uc_info;
10345 float left_p;
10346 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010347 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010348
10349 uc_info = get_usecase_from_list(adev, out->usecase);
10350 if (uc_info == NULL) {
10351 ALOGE("%s: Could not find the usecase (%d) in the list",
10352 __func__, out->usecase);
10353 return -EINVAL;
10354 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010355 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010356
Zhou Song1f93fa52020-11-20 13:57:39 +080010357 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10358 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010359
10360 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010361 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010362 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010363 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010364 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010365 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10366 select_devices(adev, uc_info->id);
Zhou Song1f93fa52020-11-20 13:57:39 +080010367
10368 if (is_offload_usecase(out->usecase)) {
10369 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010370 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Song1f93fa52020-11-20 13:57:39 +080010371 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10372 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10373 } else {
10374 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010375 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010376 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010377 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010378 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010379 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010380 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +080010381 // mute stream and switch to speaker if suspended
10382 if (!out->a2dp_muted && !out->standby) {
10383 ALOGD("%s: selecting speaker and muting stream", __func__);
10384 assign_devices(&devices, &out->device_list);
10385 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
10386 left_p = out->volume_l;
10387 right_p = out->volume_r;
10388 out->a2dp_muted = true;
10389 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10391 compress_pause(out->compr);
10392 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song1f93fa52020-11-20 13:57:39 +080010393 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10394 out_set_voip_volume(&out->stream, (float)0, (float)0);
10395 } else {
10396 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10397 /* wait for stale pcm drained before switching to speaker */
10398 uint32_t latency =
10399 (out->config.period_count * out->config.period_size * 1000) /
10400 (out->config.rate);
10401 usleep(latency * 1000);
10402 }
10403 select_devices(adev, out->usecase);
10404 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010405 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10406 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010407 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010408 assign_devices(&out->device_list, &devices);
10409 out->volume_l = left_p;
10410 out->volume_r = right_p;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010411 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010412 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010413 }
10414 ALOGV("%s: exit", __func__);
10415 return 0;
10416}
10417
Haynes Mathew George01156f92018-04-13 15:29:54 -070010418void adev_on_battery_status_changed(bool charging)
10419{
10420 pthread_mutex_lock(&adev->lock);
10421 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10422 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010423 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010424 pthread_mutex_unlock(&adev->lock);
10425}
10426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010427static int adev_open(const hw_module_t *module, const char *name,
10428 hw_device_t **device)
10429{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010430 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010431 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010432 char mixer_ctl_name[128] = {0};
10433 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010434
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010435 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010436 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10437
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010438 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010439 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010440 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010441 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010442 ALOGD("%s: returning existing instance of adev", __func__);
10443 ALOGD("%s: exit", __func__);
10444 pthread_mutex_unlock(&adev_init_lock);
10445 return 0;
10446 }
10447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010448 adev = calloc(1, sizeof(struct audio_device));
10449
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010450 if (!adev) {
10451 pthread_mutex_unlock(&adev_init_lock);
10452 return -ENOMEM;
10453 }
10454
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010455 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10456
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010457 // register audio ext hidl at the earliest
10458 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010459#ifdef DYNAMIC_LOG_ENABLED
10460 register_for_dynamic_logging("hal");
10461#endif
10462
Derek Chenf939fb72018-11-13 13:34:41 -080010463 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010464 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010465 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10466 maj_version = atoi(value);
10467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010468 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010469 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010470 adev->device.common.module = (struct hw_module_t *)module;
10471 adev->device.common.close = adev_close;
10472
10473 adev->device.init_check = adev_init_check;
10474 adev->device.set_voice_volume = adev_set_voice_volume;
10475 adev->device.set_master_volume = adev_set_master_volume;
10476 adev->device.get_master_volume = adev_get_master_volume;
10477 adev->device.set_master_mute = adev_set_master_mute;
10478 adev->device.get_master_mute = adev_get_master_mute;
10479 adev->device.set_mode = adev_set_mode;
10480 adev->device.set_mic_mute = adev_set_mic_mute;
10481 adev->device.get_mic_mute = adev_get_mic_mute;
10482 adev->device.set_parameters = adev_set_parameters;
10483 adev->device.get_parameters = adev_get_parameters;
10484 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10485 adev->device.open_output_stream = adev_open_output_stream;
10486 adev->device.close_output_stream = adev_close_output_stream;
10487 adev->device.open_input_stream = adev_open_input_stream;
10488 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010489 adev->device.create_audio_patch = adev_create_audio_patch;
10490 adev->device.release_audio_patch = adev_release_audio_patch;
10491 adev->device.get_audio_port = adev_get_audio_port;
10492 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010493 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010494 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010495
10496 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010497 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010498 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010499 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010500 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010501 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010502 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010503 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010504 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010505 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010506 /* Init audio and voice feature */
10507 audio_extn_feature_init();
10508 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010509 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010510 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010511 list_init(&adev->active_inputs_list);
10512 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010513 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010514 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10515 audio_extn_utils_hash_eq);
10516 if (!adev->io_streams_map) {
10517 ALOGE("%s: Could not create io streams map", __func__);
10518 ret = -ENOMEM;
10519 goto adev_open_err;
10520 }
10521 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10522 audio_extn_utils_hash_eq);
10523 if (!adev->patch_map) {
10524 ALOGE("%s: Could not create audio patch map", __func__);
10525 ret = -ENOMEM;
10526 goto adev_open_err;
10527 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010528 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010529 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010530 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010531 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010532 adev->perf_lock_opts[0] = 0x101;
10533 adev->perf_lock_opts[1] = 0x20E;
10534 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010535 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010536 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010537 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010538 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010539 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010540
Zhou Song68ebc352019-12-05 17:11:15 +080010541 audio_extn_perf_lock_init();
10542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010543 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010544 adev->platform = platform_init(adev);
10545 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010546 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010547 ret = -EINVAL;
10548 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010549 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010550
Aalique Grahame22e49102018-12-18 14:23:57 -080010551 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010552 if (audio_extn_qap_is_enabled()) {
10553 ret = audio_extn_qap_init(adev);
10554 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010555 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010556 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010557 }
10558 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10559 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10560 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010561
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010562 if (audio_extn_qaf_is_enabled()) {
10563 ret = audio_extn_qaf_init(adev);
10564 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010565 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010566 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010567 }
10568
10569 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10570 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10571 }
10572
Derek Chenae7b0342019-02-08 15:17:04 -080010573 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010574 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10575
Eric Laurentc4aef752013-09-12 17:45:53 -070010576 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10577 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10578 if (adev->visualizer_lib == NULL) {
10579 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10580 } else {
10581 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10582 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010583 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010584 "visualizer_hal_start_output");
10585 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010586 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010587 "visualizer_hal_stop_output");
10588 }
10589 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010590 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010591 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010592 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010593 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010594 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010595 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010596
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010597 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10598 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10599 if (adev->offload_effects_lib == NULL) {
10600 ALOGE("%s: DLOPEN failed for %s", __func__,
10601 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10602 } else {
10603 ALOGV("%s: DLOPEN successful for %s", __func__,
10604 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10605 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010606 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010607 "offload_effects_bundle_hal_start_output");
10608 adev->offload_effects_stop_output =
10609 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10610 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010611 adev->offload_effects_set_hpx_state =
10612 (int (*)(bool))dlsym(adev->offload_effects_lib,
10613 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010614 adev->offload_effects_get_parameters =
10615 (void (*)(struct str_parms *, struct str_parms *))
10616 dlsym(adev->offload_effects_lib,
10617 "offload_effects_bundle_get_parameters");
10618 adev->offload_effects_set_parameters =
10619 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10620 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010621 }
10622 }
10623
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010624 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10625 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10626 if (adev->adm_lib == NULL) {
10627 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10628 } else {
10629 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10630 adev->adm_init = (adm_init_t)
10631 dlsym(adev->adm_lib, "adm_init");
10632 adev->adm_deinit = (adm_deinit_t)
10633 dlsym(adev->adm_lib, "adm_deinit");
10634 adev->adm_register_input_stream = (adm_register_input_stream_t)
10635 dlsym(adev->adm_lib, "adm_register_input_stream");
10636 adev->adm_register_output_stream = (adm_register_output_stream_t)
10637 dlsym(adev->adm_lib, "adm_register_output_stream");
10638 adev->adm_deregister_stream = (adm_deregister_stream_t)
10639 dlsym(adev->adm_lib, "adm_deregister_stream");
10640 adev->adm_request_focus = (adm_request_focus_t)
10641 dlsym(adev->adm_lib, "adm_request_focus");
10642 adev->adm_abandon_focus = (adm_abandon_focus_t)
10643 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010644 adev->adm_set_config = (adm_set_config_t)
10645 dlsym(adev->adm_lib, "adm_set_config");
10646 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10647 dlsym(adev->adm_lib, "adm_request_focus_v2");
10648 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10649 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10650 adev->adm_on_routing_change = (adm_on_routing_change_t)
10651 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010652 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10653 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010654 }
10655 }
10656
Aalique Grahame22e49102018-12-18 14:23:57 -080010657 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010658 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010659 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010660 //initialize this to false for now,
10661 //this will be set to true through set param
10662 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010663
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010664 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010665 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010666
10667 if (k_enable_extended_precision)
10668 adev_verify_devices(adev);
10669
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010670 adev->dsp_bit_width_enforce_mode =
10671 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010672
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010673 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10674 &adev->streams_output_cfg_list,
10675 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010676
Kiran Kandi910e1862013-10-29 13:29:42 -070010677 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010678
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010679 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010680 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010681 trial = atoi(value);
10682 if (period_size_is_plausible_for_low_latency(trial)) {
10683 pcm_config_low_latency.period_size = trial;
10684 pcm_config_low_latency.start_threshold = trial / 4;
10685 pcm_config_low_latency.avail_min = trial / 4;
10686 configured_low_latency_capture_period_size = trial;
10687 }
10688 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010689 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10690 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010691 trial = atoi(value);
10692 if (period_size_is_plausible_for_low_latency(trial)) {
10693 configured_low_latency_capture_period_size = trial;
10694 }
10695 }
10696
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010697 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10698
Eric Laurent4b084132018-10-19 17:33:43 -070010699 adev->camera_orientation = CAMERA_DEFAULT;
10700
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010701 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010702 af_period_multiplier = atoi(value);
10703 if (af_period_multiplier < 0)
10704 af_period_multiplier = 2;
10705 else if (af_period_multiplier > 4)
10706 af_period_multiplier = 4;
10707
10708 ALOGV("new period_multiplier = %d", af_period_multiplier);
10709 }
10710
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010711 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010712
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010713 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010714 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010715 pthread_mutex_unlock(&adev_init_lock);
10716
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010717 if (adev->adm_init)
10718 adev->adm_data = adev->adm_init();
10719
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010720 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010721 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010722
10723 audio_extn_snd_mon_init();
10724 pthread_mutex_lock(&adev->lock);
10725 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10726 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010727 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10728 /*
10729 * if the battery state callback happens before charging can be queried,
10730 * it will be guarded with the adev->lock held in the cb function and so
10731 * the callback value will reflect the latest state
10732 */
10733 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010734 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010735 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010736 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010737 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010738 /* Allocate memory for Device config params */
10739 adev->device_cfg_params = (struct audio_device_config_param*)
10740 calloc(platform_get_max_codec_backend(),
10741 sizeof(struct audio_device_config_param));
10742 if (adev->device_cfg_params == NULL)
10743 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010744
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010745 /*
10746 * Check if new PSPD matrix mixer control is supported. If not
10747 * supported, then set flag so that old mixer ctrl is sent while
10748 * sending pspd coefficients on older kernel version. Query mixer
10749 * control for default pcm id and channel value one.
10750 */
10751 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10752 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10753
10754 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10755 if (!ctl) {
10756 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10757 __func__, mixer_ctl_name);
10758 adev->use_old_pspd_mix_ctrl = true;
10759 }
10760
Eric Laurent994a6932013-07-17 11:51:42 -070010761 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010762 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010763
10764adev_open_err:
10765 free_map(adev->patch_map);
10766 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010767 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010768 pthread_mutex_destroy(&adev->lock);
10769 free(adev);
10770 adev = NULL;
10771 *device = NULL;
10772 pthread_mutex_unlock(&adev_init_lock);
10773 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010774}
10775
10776static struct hw_module_methods_t hal_module_methods = {
10777 .open = adev_open,
10778};
10779
10780struct audio_module HAL_MODULE_INFO_SYM = {
10781 .common = {
10782 .tag = HARDWARE_MODULE_TAG,
10783 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10784 .hal_api_version = HARDWARE_HAL_API_VERSION,
10785 .id = AUDIO_HARDWARE_MODULE_ID,
10786 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010787 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010788 .methods = &hal_module_methods,
10789 },
10790};