blob: c8b9aca4fdd321debde78828e198f577995c06a6 [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 Songbaddf9f2020-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",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530403 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530404 /* For Interactive Audio Streams */
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
412 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700413
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800414 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
415
Derek Chenf6318be2017-06-12 17:16:24 -0400416 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
417
418 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
419 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
420 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
421 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800422 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700423 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530424 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500425 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400426
427 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
428 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
429 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800430 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700431};
432
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700433static const audio_usecase_t offload_usecases[] = {
434 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700435 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
436 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
441 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
442 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700443};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800444
Varun Balaraje49253e2017-07-06 19:48:56 +0530445static const audio_usecase_t interactive_usecases[] = {
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
452 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
453 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
454};
455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456#define STRING_TO_ENUM(string) { #string, string }
457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458struct string_to_enum {
459 const char *name;
460 uint32_t value;
461};
462
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700463static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
470 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800471 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
473 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
474 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
481 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
482 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800483};
484
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700485static const struct string_to_enum formats_name_to_enum_table[] = {
486 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
487 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
488 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700489 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
490 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
491 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700492 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800493 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
494 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700495 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800496};
497
498//list of all supported sample rates by HDMI specification.
499static const int out_hdmi_sample_rates[] = {
500 32000, 44100, 48000, 88200, 96000, 176400, 192000,
501};
502
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700503static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800504 STRING_TO_ENUM(32000),
505 STRING_TO_ENUM(44100),
506 STRING_TO_ENUM(48000),
507 STRING_TO_ENUM(88200),
508 STRING_TO_ENUM(96000),
509 STRING_TO_ENUM(176400),
510 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800511 STRING_TO_ENUM(352800),
512 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700513};
514
Carter Hsu2e429db2019-05-14 18:50:52 +0800515struct in_effect_list {
516 struct listnode list;
517 effect_handle_t handle;
518};
519
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700520static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700521static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700522static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700523//cache last MBDRC cal step level
524static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700525
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530526static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700527static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800528static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530529static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530530
Derek Chen6f293672019-04-01 01:40:24 -0700531static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
532static void in_snd_mon_cb(void * stream, struct str_parms * parms);
533static void out_snd_mon_cb(void * stream, struct str_parms * parms);
534
Zhou Song331c8e52019-08-26 14:16:12 +0800535static int configure_btsco_sample_rate(snd_device_t snd_device);
536
Vatsal Buchac09ae062018-11-14 13:25:08 +0530537#ifdef AUDIO_FEATURE_ENABLED_GCOV
538extern void __gcov_flush();
539static void enable_gcov()
540{
541 __gcov_flush();
542}
543#else
544static void enable_gcov()
545{
546}
547#endif
548
justinweng20fb6d82019-02-21 18:49:00 -0700549static int in_set_microphone_direction(const struct audio_stream_in *stream,
550 audio_microphone_direction_t dir);
551static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
552
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700553static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
554 int flags __unused)
555{
556 int dir = 0;
557 switch (uc_id) {
558 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530559 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700560 dir = 1;
561 case USECASE_AUDIO_PLAYBACK_ULL:
562 break;
563 default:
564 return false;
565 }
566
567 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
568 PCM_PLAYBACK : PCM_CAPTURE);
569 if (adev->adm_is_noirq_avail)
570 return adev->adm_is_noirq_avail(adev->adm_data,
571 adev->snd_card, dev_id, dir);
572 return false;
573}
574
575static void register_out_stream(struct stream_out *out)
576{
577 struct audio_device *adev = out->dev;
578 if (is_offload_usecase(out->usecase) ||
579 !adev->adm_register_output_stream)
580 return;
581
582 // register stream first for backward compatibility
583 adev->adm_register_output_stream(adev->adm_data,
584 out->handle,
585 out->flags);
586
587 if (!adev->adm_set_config)
588 return;
589
590 if (out->realtime)
591 adev->adm_set_config(adev->adm_data,
592 out->handle,
593 out->pcm, &out->config);
594}
595
596static void register_in_stream(struct stream_in *in)
597{
598 struct audio_device *adev = in->dev;
599 if (!adev->adm_register_input_stream)
600 return;
601
602 adev->adm_register_input_stream(adev->adm_data,
603 in->capture_handle,
604 in->flags);
605
606 if (!adev->adm_set_config)
607 return;
608
609 if (in->realtime)
610 adev->adm_set_config(adev->adm_data,
611 in->capture_handle,
612 in->pcm,
613 &in->config);
614}
615
616static void request_out_focus(struct stream_out *out, long ns)
617{
618 struct audio_device *adev = out->dev;
619
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700620 if (adev->adm_request_focus_v2)
621 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, out->handle);
624}
625
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700626static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700627{
628 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700630
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700631 if (adev->adm_request_focus_v2_1)
632 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
633 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700634 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
635 else if (adev->adm_request_focus)
636 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700637
638 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700639}
640
641static void release_out_focus(struct stream_out *out)
642{
643 struct audio_device *adev = out->dev;
644
645 if (adev->adm_abandon_focus)
646 adev->adm_abandon_focus(adev->adm_data, out->handle);
647}
648
649static void release_in_focus(struct stream_in *in)
650{
651 struct audio_device *adev = in->dev;
652 if (adev->adm_abandon_focus)
653 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
654}
655
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530656static int parse_snd_card_status(struct str_parms *parms, int *card,
657 card_status_t *status)
658{
659 char value[32]={0};
660 char state[32]={0};
661
662 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
663 if (ret < 0)
664 return -1;
665
666 // sscanf should be okay as value is of max length 32.
667 // same as sizeof state.
668 if (sscanf(value, "%d,%s", card, state) < 2)
669 return -1;
670
671 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
672 CARD_STATUS_OFFLINE;
673 return 0;
674}
675
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700676static inline void adjust_frames_for_device_delay(struct stream_out *out,
677 uint32_t *dsp_frames) {
678 // Adjustment accounts for A2dp encoder latency with offload usecases
679 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800680 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700681 unsigned long offset =
682 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
683 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
684 }
685}
686
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700687static inline bool free_entry(void *key __unused,
688 void *value, void *context __unused)
689{
690 free(value);
691 return true;
692}
693
694static inline void free_map(Hashmap *map)
695{
696 if (map) {
697 hashmapForEach(map, free_entry, (void *) NULL);
698 hashmapFree(map);
699 }
700}
701
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800702static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703 audio_patch_handle_t patch_handle)
704{
705 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
706 return;
707
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708 struct audio_patch_info *p_info =
709 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
710 if (p_info) {
711 ALOGV("%s: Remove patch %d", __func__, patch_handle);
712 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
713 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700714 free(p_info);
715 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700716}
717
718static inline int io_streams_map_insert(struct audio_device *adev,
719 struct audio_stream *stream,
720 audio_io_handle_t handle,
721 audio_patch_handle_t patch_handle)
722{
723 struct audio_stream_info *s_info =
724 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
725
726 if (s_info == NULL) {
727 ALOGE("%s: Could not allocate stream info", __func__);
728 return -ENOMEM;
729 }
730 s_info->stream = stream;
731 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700732
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *stream_info =
735 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (stream_info != NULL)
737 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800738 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700739 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 return 0;
741}
742
743static inline void io_streams_map_remove(struct audio_device *adev,
744 audio_io_handle_t handle)
745{
746 pthread_mutex_lock(&adev->lock);
747 struct audio_stream_info *s_info =
748 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700749 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800750 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700751 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800752 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700753 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800754done:
755 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700756 return;
757}
758
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800759static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700760 audio_patch_handle_t handle)
761{
762 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700763 p_info = (struct audio_patch_info *)
764 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700765 return p_info;
766}
767
vivek mehtaa76401a2015-04-24 14:12:15 -0700768__attribute__ ((visibility ("default")))
769bool audio_hw_send_gain_dep_calibration(int level) {
770 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700771 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700772
773 pthread_mutex_lock(&adev_init_lock);
774
775 if (adev != NULL && adev->platform != NULL) {
776 pthread_mutex_lock(&adev->lock);
777 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700778
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530779 // cache level info for any of the use case which
780 // was not started.
781 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700782
vivek mehtaa76401a2015-04-24 14:12:15 -0700783 pthread_mutex_unlock(&adev->lock);
784 } else {
785 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
786 }
787
788 pthread_mutex_unlock(&adev_init_lock);
789
790 return ret_val;
791}
792
Ashish Jain5106d362016-05-11 19:23:33 +0530793static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
794{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800795 bool gapless_enabled = false;
796 const char *mixer_ctl_name = "Compress Gapless Playback";
797 struct mixer_ctl *ctl;
798
799 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700800 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530801
802 /*Disable gapless if its AV playback*/
803 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800804
805 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
806 if (!ctl) {
807 ALOGE("%s: Could not get ctl for mixer cmd - %s",
808 __func__, mixer_ctl_name);
809 return -EINVAL;
810 }
811
812 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
813 ALOGE("%s: Could not set gapless mode %d",
814 __func__, gapless_enabled);
815 return -EINVAL;
816 }
817 return 0;
818}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700819
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700820__attribute__ ((visibility ("default")))
821int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
822 int table_size) {
823 int ret_val = 0;
824 ALOGV("%s: enter ... ", __func__);
825
826 pthread_mutex_lock(&adev_init_lock);
827 if (adev == NULL) {
828 ALOGW("%s: adev is NULL .... ", __func__);
829 goto done;
830 }
831
832 pthread_mutex_lock(&adev->lock);
833 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
834 pthread_mutex_unlock(&adev->lock);
835done:
836 pthread_mutex_unlock(&adev_init_lock);
837 ALOGV("%s: exit ... ", __func__);
838 return ret_val;
839}
840
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800841bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800842{
843 bool ret = false;
844 ALOGV("%s: enter ...", __func__);
845
846 pthread_mutex_lock(&adev_init_lock);
847
848 if (adev != NULL && adev->platform != NULL) {
849 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800850 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800851 pthread_mutex_unlock(&adev->lock);
852 }
853
854 pthread_mutex_unlock(&adev_init_lock);
855
856 ALOGV("%s: exit with ret %d", __func__, ret);
857 return ret;
858}
Aalique Grahame22e49102018-12-18 14:23:57 -0800859
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700860static bool is_supported_format(audio_format_t format)
861{
Eric Laurent86e17132013-09-12 17:49:30 -0700862 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530863 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530864 format == AUDIO_FORMAT_AAC_LC ||
865 format == AUDIO_FORMAT_AAC_HE_V1 ||
866 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530867 format == AUDIO_FORMAT_AAC_ADTS_LC ||
868 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
869 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530870 format == AUDIO_FORMAT_AAC_LATM_LC ||
871 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
872 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530873 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
874 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530875 format == AUDIO_FORMAT_PCM_FLOAT ||
876 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700877 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530878 format == AUDIO_FORMAT_AC3 ||
879 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700880 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530881 format == AUDIO_FORMAT_DTS ||
882 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800883 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530884 format == AUDIO_FORMAT_ALAC ||
885 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530886 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530887 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800888 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530889 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700890 format == AUDIO_FORMAT_APTX ||
891 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800892 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700893
894 return false;
895}
896
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700897static inline bool is_mmap_usecase(audio_usecase_t uc_id)
898{
899 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800900 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700901 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
902}
903
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700904static inline bool is_valid_volume(float left, float right)
905{
906 return ((left >= 0.0f && right >= 0.0f) ? true : false);
907}
908
Avinash Vaish71a8b972014-07-24 15:36:33 +0530909static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
910 struct audio_usecase *uc_info)
911{
912 struct listnode *node;
913 struct audio_usecase *usecase;
914
915 if (uc_info == NULL)
916 return -EINVAL;
917
918 /* Re-route all voice usecases on the shared backend other than the
919 specified usecase to new snd devices */
920 list_for_each(node, &adev->usecase_list) {
921 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800922 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530923 enable_audio_route(adev, usecase);
924 }
925 return 0;
926}
927
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530928static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530929{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530930 ALOGV("%s", __func__);
931 audio_route_apply_and_update_path(adev->audio_route,
932 "asrc-mode");
933 adev->asrc_mode_enabled = true;
934}
935
936static void disable_asrc_mode(struct audio_device *adev)
937{
938 ALOGV("%s", __func__);
939 audio_route_reset_and_update_path(adev->audio_route,
940 "asrc-mode");
941 adev->asrc_mode_enabled = false;
942}
943
Saurav Kumarc1411662020-10-14 10:50:45 +0530944static void check_and_configure_headphone(struct audio_device *adev,
945 struct audio_usecase *uc_info,
946 snd_device_t snd_device)
947{
948 struct listnode *node;
949 struct audio_usecase *usecase;
950 int new_backend_idx, usecase_backend_idx;
951 bool spkr_hph_single_be_native_concurrency;
952
953 new_backend_idx = platform_get_backend_index(snd_device);
954 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
955 if ( spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) {
956 list_for_each(node, &adev->usecase_list) {
957 usecase = node_to_item(node, struct audio_usecase, list);
958 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
959 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
960 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
961 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
962 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
963 disable_audio_route(adev, usecase);
964 disable_snd_device(adev, usecase->out_snd_device);
965 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530966 platform_check_and_set_codec_backend_cfg(adev, usecase,
967 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530968 enable_audio_route(adev, usecase);
969 enable_snd_device(adev, usecase->out_snd_device);
970 }
971 }
972 }
973 }
974}
975
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530976/*
977 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
978 * 44.1 or Native DSD backends are enabled for any of current use case.
979 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
980 * - Disable current mix path use case(Headphone backend) and re-enable it with
981 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
982 * e.g. Naitve DSD or Headphone 44.1 -> + 48
983 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530984static void check_and_set_asrc_mode(struct audio_device *adev,
985 struct audio_usecase *uc_info,
986 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530987{
988 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530989 int i, num_new_devices = 0;
990 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
991 /*
992 *Split snd device for new combo use case
993 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
994 */
995 if (platform_split_snd_device(adev->platform,
996 snd_device,
997 &num_new_devices,
998 split_new_snd_devices) == 0) {
999 for (i = 0; i < num_new_devices; i++)
1000 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1001 } else {
1002 int new_backend_idx = platform_get_backend_index(snd_device);
1003 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1004 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1005 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1006 !adev->asrc_mode_enabled) {
1007 struct listnode *node = NULL;
1008 struct audio_usecase *uc = NULL;
1009 struct stream_out *curr_out = NULL;
1010 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1011 int i, num_devices, ret = 0;
1012 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301013
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301014 list_for_each(node, &adev->usecase_list) {
1015 uc = node_to_item(node, struct audio_usecase, list);
1016 curr_out = (struct stream_out*) uc->stream.out;
1017 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1018 /*
1019 *Split snd device for existing combo use case
1020 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1021 */
1022 ret = platform_split_snd_device(adev->platform,
1023 uc->out_snd_device,
1024 &num_devices,
1025 split_snd_devices);
1026 if (ret < 0 || num_devices == 0) {
1027 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1028 split_snd_devices[0] = uc->out_snd_device;
1029 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001030 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301031 for (i = 0; i < num_devices; i++) {
1032 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1033 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1034 if((new_backend_idx == HEADPHONE_BACKEND) &&
1035 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1036 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001037 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301038 __func__);
1039 enable_asrc_mode(adev);
1040 break;
1041 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1042 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1043 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001044 ALOGV("%s: 48K stream detected, disabling and enabling it \
1045 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301046 disable_audio_route(adev, uc);
1047 disable_snd_device(adev, uc->out_snd_device);
1048 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1049 if (new_backend_idx == DSD_NATIVE_BACKEND)
1050 audio_route_apply_and_update_path(adev->audio_route,
1051 "hph-true-highquality-mode");
1052 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1053 (curr_out->bit_width >= 24))
1054 audio_route_apply_and_update_path(adev->audio_route,
1055 "hph-highquality-mode");
1056 enable_asrc_mode(adev);
1057 enable_snd_device(adev, uc->out_snd_device);
1058 enable_audio_route(adev, uc);
1059 break;
1060 }
1061 }
1062 // reset split devices count
1063 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001064 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301065 if (adev->asrc_mode_enabled)
1066 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301067 }
1068 }
1069 }
1070}
1071
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001072static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1073 struct audio_effect_config effect_config,
1074 unsigned int param_value)
1075{
1076 char mixer_ctl_name[] = "Audio Effect";
1077 struct mixer_ctl *ctl;
1078 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001079 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001080
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001081 if (in == NULL) {
1082 ALOGE("%s: active input stream is NULL", __func__);
1083 return -EINVAL;
1084 }
1085
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001086 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1087 if (!ctl) {
1088 ALOGE("%s: Could not get mixer ctl - %s",
1089 __func__, mixer_ctl_name);
1090 return -EINVAL;
1091 }
1092
1093 set_values[0] = 1; //0:Rx 1:Tx
1094 set_values[1] = in->app_type_cfg.app_type;
1095 set_values[2] = (long)effect_config.module_id;
1096 set_values[3] = (long)effect_config.instance_id;
1097 set_values[4] = (long)effect_config.param_id;
1098 set_values[5] = param_value;
1099
1100 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1101
1102 return 0;
1103
1104}
1105
1106static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1107 int effect_type, unsigned int *param_value)
1108{
1109 int ret = 0;
1110 struct audio_effect_config other_effect_config;
1111 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001112 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001113
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001114 if (in == NULL) {
1115 ALOGE("%s: active input stream is NULL", __func__);
1116 return -EINVAL;
1117 }
1118
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001119 usecase = get_usecase_from_list(adev, in->usecase);
1120 if (!usecase)
1121 return -EINVAL;
1122
1123 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1124 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1125 if (ret < 0) {
1126 ALOGE("%s Failed to get effect params %d", __func__, ret);
1127 return ret;
1128 }
1129
1130 if (module_id == other_effect_config.module_id) {
1131 //Same module id for AEC/NS. Values need to be combined
1132 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1133 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1134 *param_value |= other_effect_config.param_value;
1135 }
1136 }
1137
1138 return ret;
1139}
1140
1141static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301142{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001143 struct audio_effect_config effect_config;
1144 struct audio_usecase *usecase = NULL;
1145 int ret = 0;
1146 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001147 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001148
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001149 if(!voice_extn_is_dynamic_ecns_enabled())
1150 return ENOSYS;
1151
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001152 if (!in) {
1153 ALOGE("%s: Invalid input stream", __func__);
1154 return -EINVAL;
1155 }
1156
1157 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1158
1159 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001160 if (usecase == NULL) {
1161 ALOGE("%s: Could not find the usecase (%d) in the list",
1162 __func__, in->usecase);
1163 return -EINVAL;
1164 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001165
1166 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1167 if (ret < 0) {
1168 ALOGE("%s Failed to get module id %d", __func__, ret);
1169 return ret;
1170 }
1171 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1172 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1173
1174 if(enable)
1175 param_value = effect_config.param_value;
1176
1177 /*Special handling for AEC & NS effects Param values need to be
1178 updated if module ids are same*/
1179
1180 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1181 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1182 if (ret < 0)
1183 return ret;
1184 }
1185
1186 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1187
1188 return ret;
1189}
1190
1191static void check_and_enable_effect(struct audio_device *adev)
1192{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001193 if(!voice_extn_is_dynamic_ecns_enabled())
1194 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001195
Eric Laurent637e2d42018-11-15 12:24:31 -08001196 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001197
Eric Laurent637e2d42018-11-15 12:24:31 -08001198 if (in != NULL && !in->standby) {
1199 if (in->enable_aec)
1200 enable_disable_effect(adev, EFFECT_AEC, true);
1201
1202 if (in->enable_ns &&
1203 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1204 enable_disable_effect(adev, EFFECT_NS, true);
1205 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001206 }
1207}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001208
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001209int pcm_ioctl(struct pcm *pcm, int request, ...)
1210{
1211 va_list ap;
1212 void * arg;
1213 int pcm_fd = *(int*)pcm;
1214
1215 va_start(ap, request);
1216 arg = va_arg(ap, void *);
1217 va_end(ap);
1218
1219 return ioctl(pcm_fd, request, arg);
1220}
1221
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001222int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001223 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001226 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301227 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301228 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001229 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301230 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001231
1232 if (usecase == NULL)
1233 return -EINVAL;
1234
1235 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1236
Carter Hsu2e429db2019-05-14 18:50:52 +08001237 if (usecase->type == PCM_CAPTURE) {
1238 struct stream_in *in = usecase->stream.in;
1239 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001241
1242 if (in) {
1243 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001244 list_init(&out_devices);
1245 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001246 struct listnode *node;
1247 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1248 USECASE_AUDIO_PLAYBACK_VOIP);
1249 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001250 assign_devices(&out_devices,
1251 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001252 } else if (adev->primary_output &&
1253 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001254 assign_devices(&out_devices,
1255 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001256 } else {
1257 list_for_each(node, &adev->usecase_list) {
1258 uinfo = node_to_item(node, struct audio_usecase, list);
1259 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001260 assign_devices(&out_devices,
1261 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001262 break;
1263 }
1264 }
1265 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001266
1267 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001268 in->ec_opened = true;
1269 }
1270 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001271 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1272 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1273 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001274 snd_device = usecase->in_snd_device;
1275 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001276 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001277 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001278
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001279#ifdef DS1_DOLBY_DAP_ENABLED
1280 audio_extn_dolby_set_dmid(adev);
1281 audio_extn_dolby_set_endpoint(adev);
1282#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001283 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001284 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301285 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001286 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001287 if (audio_extn_is_maxx_audio_enabled())
1288 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301289 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001290 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1291 out = usecase->stream.out;
1292 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301293 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1294 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301295
1296 if (usecase->type == PCM_CAPTURE) {
1297 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001298 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301299 ALOGD("%s: set custom mtmx params v1", __func__);
1300 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1301 }
1302 } else {
1303 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1304 }
Manish Dewangan58229382017-02-02 15:48:41 +05301305
Andy Hung756ecc12018-10-19 17:47:12 -07001306 // we shouldn't truncate mixer_path
1307 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1308 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1309 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001310 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001311 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301312 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1313 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1314 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1315 if (parms) {
1316 audio_extn_fm_set_parameters(adev, parms);
1317 str_parms_destroy(parms);
1318 }
1319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320 ALOGV("%s: exit", __func__);
1321 return 0;
1322}
1323
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001324int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001325 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001328 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301329 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001330
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301331 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001332 return -EINVAL;
1333
1334 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301335 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001336 snd_device = usecase->in_snd_device;
1337 else
1338 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001339
1340 /* disable island and power mode on supported device for voice call */
1341 if (usecase->type == VOICE_CALL) {
1342 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1343 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1344 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1345 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1346 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1347 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001348 if (voice_is_lte_call_active(adev))
1349 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001350 ALOGD("%s: disable island cfg and power mode in voice tx path",
1351 __func__);
1352 }
1353 }
1354 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1355 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1356 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1357 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1358 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1359 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1360 ALOGD("%s: disable island cfg and power mode in voice rx path",
1361 __func__);
1362 }
1363 }
1364 }
1365
Andy Hung756ecc12018-10-19 17:47:12 -07001366 // we shouldn't truncate mixer_path
1367 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1368 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1369 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001370 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001371 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001372 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001373 if (usecase->type == PCM_CAPTURE) {
1374 struct stream_in *in = usecase->stream.in;
1375 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001376 struct listnode out_devices;
1377 list_init(&out_devices);
1378 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001379 in->ec_opened = false;
1380 }
1381 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001382 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301383 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301384
1385 if (usecase->type == PCM_CAPTURE) {
1386 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001387 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301388 ALOGD("%s: reset custom mtmx params v1", __func__);
1389 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1390 }
1391 } else {
1392 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1393 }
1394
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001395 if ((usecase->type == PCM_PLAYBACK) &&
1396 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301397 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399 ALOGV("%s: exit", __func__);
1400 return 0;
1401}
1402
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001403int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001404 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301406 int i, num_devices = 0;
1407 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001408 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1409
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001410 if (snd_device < SND_DEVICE_MIN ||
1411 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001412 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001413 return -EINVAL;
1414 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001415
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001416 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001417 ALOGE("%s: Invalid sound device returned", __func__);
1418 return -EINVAL;
1419 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001420
1421 adev->snd_dev_ref_cnt[snd_device]++;
1422
1423 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1424 (platform_split_snd_device(adev->platform,
1425 snd_device,
1426 &num_devices,
1427 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001428 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001429 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001430 /* Set backend config for A2DP to ensure slimbus configuration
1431 is correct if A2DP is already active and backend is closed
1432 and re-opened */
1433 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1434 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 return 0;
1436 }
1437
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001438 if (audio_extn_spkr_prot_is_enabled())
1439 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001440
Aalique Grahame22e49102018-12-18 14:23:57 -08001441 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1442
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001443 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1444 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001445 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1446 goto err;
1447 }
1448 audio_extn_dev_arbi_acquire(snd_device);
1449 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001450 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001451 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001452 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001453 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001454 } else if (platform_split_snd_device(adev->platform,
1455 snd_device,
1456 &num_devices,
1457 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301458 for (i = 0; i < num_devices; i++) {
1459 enable_snd_device(adev, new_snd_devices[i]);
1460 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001461 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001462 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001463 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301464
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001465 /* enable island and power mode on supported device */
1466 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1467 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1468 platform_set_island_cfg_on_device(adev, snd_device, true);
1469 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001470 if (voice_is_lte_call_active(adev) &&
1471 (snd_device >= SND_DEVICE_IN_BEGIN &&
1472 snd_device < SND_DEVICE_IN_END))
1473 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001474 ALOGD("%s: enable island cfg and power mode on: %s",
1475 __func__, device_name);
1476 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301477
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301478 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1479 if (audio_extn_a2dp_start_playback() < 0) {
1480 ALOGE(" fail to configure A2dp Source control path ");
1481 goto err;
1482 } else {
1483 adev->a2dp_started = true;
1484 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001485 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001486
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001487 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1488 (audio_extn_a2dp_start_capture() < 0)) {
1489 ALOGE(" fail to configure A2dp Sink control path ");
1490 goto err;
1491 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301492
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001493 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1494 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1495 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1496 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1497 ALOGE(" fail to configure sco control path ");
1498 goto err;
1499 }
Zhou Song12c29502019-03-16 10:37:18 +08001500 }
1501
Zhou Song331c8e52019-08-26 14:16:12 +08001502 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001503 /* due to the possibility of calibration overwrite between listen
1504 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001505 audio_extn_sound_trigger_update_device_status(snd_device,
1506 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301507 audio_extn_listen_update_device_status(snd_device,
1508 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001509 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001510 audio_extn_sound_trigger_update_device_status(snd_device,
1511 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301512 audio_extn_listen_update_device_status(snd_device,
1513 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001514 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001515 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001516 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001517 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301518
1519 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1520 !adev->native_playback_enabled &&
1521 audio_is_true_native_stream_active(adev)) {
1522 ALOGD("%s: %d: napb: enabling native mode in hardware",
1523 __func__, __LINE__);
1524 audio_route_apply_and_update_path(adev->audio_route,
1525 "true-native-mode");
1526 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301527 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301528 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1529 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001530 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001531 ALOGD("%s: init ec ref loopback", __func__);
1532 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001536err:
1537 adev->snd_dev_ref_cnt[snd_device]--;
1538 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539}
1540
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001541int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001542 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301544 int i, num_devices = 0;
1545 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001546 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1547
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001548 if (snd_device < SND_DEVICE_MIN ||
1549 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001550 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001551 return -EINVAL;
1552 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001553
1554 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1555 ALOGE("%s: Invalid sound device returned", __func__);
1556 return -EINVAL;
1557 }
1558
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1560 ALOGE("%s: device ref cnt is already 0", __func__);
1561 return -EINVAL;
1562 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001563
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001565
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001566
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001568 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301569
Aalique Grahame22e49102018-12-18 14:23:57 -08001570 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1571
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001572 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1573 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001574 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001575
1576 // when speaker device is disabled, reset swap.
1577 // will be renabled on usecase start
1578 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001579 } else if (platform_split_snd_device(adev->platform,
1580 snd_device,
1581 &num_devices,
1582 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301583 for (i = 0; i < num_devices; i++) {
1584 disable_snd_device(adev, new_snd_devices[i]);
1585 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001586 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001587 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001588 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001589 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001590
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301591 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301592 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301593 adev->a2dp_started = false;
1594 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001595 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001596 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001597 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301598 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001599 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301600 adev->native_playback_enabled) {
1601 ALOGD("%s: %d: napb: disabling native mode in hardware",
1602 __func__, __LINE__);
1603 audio_route_reset_and_update_path(adev->audio_route,
1604 "true-native-mode");
1605 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001606 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301607 adev->asrc_mode_enabled) {
1608 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301609 disable_asrc_mode(adev);
1610 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001611 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301612 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001613 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001614 ALOGD("%s: deinit ec ref loopback", __func__);
1615 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1616 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001617
1618 audio_extn_utils_release_snd_device(snd_device);
1619 } else {
1620 if (platform_split_snd_device(adev->platform,
1621 snd_device,
1622 &num_devices,
1623 new_snd_devices) == 0) {
1624 for (i = 0; i < num_devices; i++) {
1625 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1626 }
1627 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001628 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630 return 0;
1631}
1632
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001633/*
1634 legend:
1635 uc - existing usecase
1636 new_uc - new usecase
1637 d1, d11, d2 - SND_DEVICE enums
1638 a1, a2 - corresponding ANDROID device enums
1639 B1, B2 - backend strings
1640
1641case 1
1642 uc->dev d1 (a1) B1
1643 new_uc->dev d1 (a1), d2 (a2) B1, B2
1644
1645 resolution: disable and enable uc->dev on d1
1646
1647case 2
1648 uc->dev d1 (a1) B1
1649 new_uc->dev d11 (a1) B1
1650
1651 resolution: need to switch uc since d1 and d11 are related
1652 (e.g. speaker and voice-speaker)
1653 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1654
1655case 3
1656 uc->dev d1 (a1) B1
1657 new_uc->dev d2 (a2) B2
1658
1659 resolution: no need to switch uc
1660
1661case 4
1662 uc->dev d1 (a1) B1
1663 new_uc->dev d2 (a2) B1
1664
1665 resolution: disable enable uc-dev on d2 since backends match
1666 we cannot enable two streams on two different devices if they
1667 share the same backend. e.g. if offload is on speaker device using
1668 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1669 using the same backend, offload must also be switched to voice-handset.
1670
1671case 5
1672 uc->dev d1 (a1) B1
1673 new_uc->dev d1 (a1), d2 (a2) B1
1674
1675 resolution: disable enable uc-dev on d2 since backends match
1676 we cannot enable two streams on two different devices if they
1677 share the same backend.
1678
1679case 6
1680 uc->dev d1 (a1) B1
1681 new_uc->dev d2 (a1) B2
1682
1683 resolution: no need to switch
1684
1685case 7
1686 uc->dev d1 (a1), d2 (a2) B1, B2
1687 new_uc->dev d1 (a1) B1
1688
1689 resolution: no need to switch
1690
Zhou Song4ba65882018-07-09 14:48:07 +08001691case 8
1692 uc->dev d1 (a1) B1
1693 new_uc->dev d11 (a1), d2 (a2) B1, B2
1694 resolution: compared to case 1, for this case, d1 and d11 are related
1695 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301696
1697case 9
1698 uc->dev d1 (a1), d2(a2) B1 B2
1699 new_uc->dev d1 (a1), d22 (a2) B1, B2
1700 resolution: disable enable uc-dev on d2 since backends match
1701 we cannot enable two streams on two different devices if they
1702 share the same backend. This is special case for combo use case
1703 with a2dp and sco devices which uses same backend.
1704 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001705*/
1706static snd_device_t derive_playback_snd_device(void * platform,
1707 struct audio_usecase *uc,
1708 struct audio_usecase *new_uc,
1709 snd_device_t new_snd_device)
1710{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001711 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001712
1713 snd_device_t d1 = uc->out_snd_device;
1714 snd_device_t d2 = new_snd_device;
1715
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001716 list_init(&a1);
1717 list_init(&a2);
1718
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301719 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301720 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001721 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1722 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301723 break;
1724 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001725 assign_devices(&a1, &uc->stream.out->device_list);
1726 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301727 break;
1728 }
1729
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001730 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001731 if (!compare_devices(&a1, &a2) &&
1732 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001733 snd_device_t d3[2];
1734 int num_devices = 0;
1735 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001736 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001737 &num_devices,
1738 d3);
1739 if (ret < 0) {
1740 if (ret != -ENOSYS) {
1741 ALOGW("%s failed to split snd_device %d",
1742 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001743 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001744 }
1745 goto end;
1746 }
1747
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001748 if (platform_check_backends_match(d3[0], d3[1])) {
1749 return d2; // case 5
1750 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301751 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1752 platform_check_backends_match(d1, d2))
1753 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001754 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301755 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001756 // check if d1 is related to any of d3's
1757 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001758 return d1; // case 1
1759 else
1760 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001761 }
1762 } else {
1763 if (platform_check_backends_match(d1, d2)) {
1764 return d2; // case 2, 4
1765 } else {
1766 return d1; // case 6, 3
1767 }
1768 }
1769
1770end:
1771 return d2; // return whatever was calculated before.
1772}
1773
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001774static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301775 struct audio_usecase *uc_info,
1776 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001777{
1778 struct listnode *node;
1779 struct audio_usecase *usecase;
1780 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301781 snd_device_t uc_derive_snd_device;
1782 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001783 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1784 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001785 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301786 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001787 /*
1788 * This function is to make sure that all the usecases that are active on
1789 * the hardware codec backend are always routed to any one device that is
1790 * handled by the hardware codec.
1791 * For example, if low-latency and deep-buffer usecases are currently active
1792 * on speaker and out_set_parameters(headset) is received on low-latency
1793 * output, then we have to make sure deep-buffer is also switched to headset,
1794 * because of the limitation that both the devices cannot be enabled
1795 * at the same time as they share the same backend.
1796 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001797 /*
1798 * This call is to check if we need to force routing for a particular stream
1799 * If there is a backend configuration change for the device when a
1800 * new stream starts, then ADM needs to be closed and re-opened with the new
1801 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001802 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001803 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001804 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1805 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301806 /* For a2dp device reconfigure all active sessions
1807 * with new AFE encoder format based on a2dp state
1808 */
1809 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301810 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1811 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301812 audio_extn_a2dp_is_force_device_switch()) {
1813 force_routing = true;
1814 force_restart_session = true;
1815 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001816
1817 /*
1818 * Island cfg and power mode config needs to set before AFE port start.
1819 * Set force routing in case of voice device was enable before.
1820 */
1821 if (uc_info->type == VOICE_CALL &&
1822 voice_extn_is_voice_power_mode_supported() &&
1823 platform_check_and_update_island_power_status(adev->platform,
1824 uc_info,
1825 snd_device)) {
1826 force_routing = true;
1827 ALOGD("%s:becf: force routing %d for power mode supported device",
1828 __func__, force_routing);
1829 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301830 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1831
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001833 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001834 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001835 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1836 switch_device[i] = false;
1837
1838 list_for_each(node, &adev->usecase_list) {
1839 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001840
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301841 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1842 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301843 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301844 platform_get_snd_device_name(usecase->out_snd_device),
1845 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301846 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1847 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301848 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1849 usecase, uc_info, snd_device);
1850 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001851 (is_codec_backend_out_device_type(&usecase->device_list) ||
1852 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1853 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1854 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1855 is_a2dp_out_device_type(&usecase->device_list) ||
1856 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301857 ((force_restart_session) ||
1858 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301859 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1860 __func__, use_case_table[usecase->id],
1861 platform_get_snd_device_name(usecase->out_snd_device));
1862 disable_audio_route(adev, usecase);
1863 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301864 /* Enable existing usecase on derived playback device */
1865 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301866 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301867 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868 }
1869 }
1870
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301871 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1872 num_uc_to_switch);
1873
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001875 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301877 /* Make sure the previous devices to be disabled first and then enable the
1878 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 list_for_each(node, &adev->usecase_list) {
1880 usecase = node_to_item(node, struct audio_usecase, list);
1881 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001882 /* Check if output sound device to be switched can be split and if any
1883 of the split devices match with derived sound device */
1884 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1885 &num_devices, split_snd_devices) == 0) {
1886 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1887 for (i = 0; i < num_devices; i++) {
1888 /* Disable devices that do not match with derived sound device */
1889 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1890 disable_snd_device(adev, split_snd_devices[i]);
1891 }
1892 } else {
1893 disable_snd_device(adev, usecase->out_snd_device);
1894 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 }
1896 }
1897
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001898 list_for_each(node, &adev->usecase_list) {
1899 usecase = node_to_item(node, struct audio_usecase, list);
1900 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001901 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1902 &num_devices, split_snd_devices) == 0) {
1903 /* Enable derived sound device only if it does not match with
1904 one of the split sound devices. This is because the matching
1905 sound device was not disabled */
1906 bool should_enable = true;
1907 for (i = 0; i < num_devices; i++) {
1908 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1909 should_enable = false;
1910 break;
1911 }
1912 }
1913 if (should_enable)
1914 enable_snd_device(adev, derive_snd_device[usecase->id]);
1915 } else {
1916 enable_snd_device(adev, derive_snd_device[usecase->id]);
1917 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001918 }
1919 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001920
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001921 /* Re-route all the usecases on the shared backend other than the
1922 specified usecase to new snd devices */
1923 list_for_each(node, &adev->usecase_list) {
1924 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301925 /* Update the out_snd_device only before enabling the audio route */
1926 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301927 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301928 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301929 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301930 use_case_table[usecase->id],
1931 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001932 /* Update voc calibration before enabling VoIP route */
1933 if (usecase->type == VOIP_CALL)
1934 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001935 usecase->out_snd_device,
1936 platform_get_input_snd_device(
1937 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301938 &uc_info->device_list,
1939 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301940 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301941 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001942 out_set_voip_volume(&usecase->stream.out->stream,
1943 usecase->stream.out->volume_l,
1944 usecase->stream.out->volume_r);
1945 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301946 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 }
1948 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949 }
1950}
1951
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301952static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001953 struct audio_usecase *uc_info,
1954 snd_device_t snd_device)
1955{
1956 struct listnode *node;
1957 struct audio_usecase *usecase;
1958 bool switch_device[AUDIO_USECASE_MAX];
1959 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001960 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001961 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001962
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301963 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1964 snd_device);
1965 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301966
1967 /*
1968 * Make sure out devices is checked against out codec backend device and
1969 * also in devices against in codec backend. Checking out device against in
1970 * codec backend or vice versa causes issues.
1971 */
1972 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001973 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001974
1975 /*
1976 * Island cfg and power mode config needs to set before AFE port start.
1977 * Set force routing in case of voice device was enable before.
1978 */
1979
1980 if (uc_info->type == VOICE_CALL &&
1981 voice_extn_is_voice_power_mode_supported() &&
1982 platform_check_and_update_island_power_status(adev->platform,
1983 uc_info,
1984 snd_device)) {
1985 force_routing = true;
1986 ALOGD("%s:becf: force routing %d for power mode supported device",
1987 __func__, force_routing);
1988 }
1989
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001990 /*
1991 * This function is to make sure that all the active capture usecases
1992 * are always routed to the same input sound device.
1993 * For example, if audio-record and voice-call usecases are currently
1994 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1995 * is received for voice call then we have to make sure that audio-record
1996 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1997 * because of the limitation that two devices cannot be enabled
1998 * at the same time if they share the same backend.
1999 */
2000 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2001 switch_device[i] = false;
2002
2003 list_for_each(node, &adev->usecase_list) {
2004 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302005 /*
2006 * TODO: Enhance below condition to handle BT sco/USB multi recording
2007 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302008
2009 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2010 (usecase->in_snd_device != snd_device || force_routing));
2011 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2012 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2013 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002014 ((backend_check_cond &&
2015 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002016 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002017 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002018 is_single_device_type_equal(&usecase->device_list,
2019 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002020 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002021 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002022 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302023 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002024 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002025 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002026 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002027 switch_device[usecase->id] = true;
2028 num_uc_to_switch++;
2029 }
2030 }
2031
2032 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002033 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002034
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302035 /* Make sure the previous devices to be disabled first and then enable the
2036 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002037 list_for_each(node, &adev->usecase_list) {
2038 usecase = node_to_item(node, struct audio_usecase, list);
2039 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002040 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002041 }
2042 }
2043
2044 list_for_each(node, &adev->usecase_list) {
2045 usecase = node_to_item(node, struct audio_usecase, list);
2046 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002047 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002048 }
2049 }
2050
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002051 /* Re-route all the usecases on the shared backend other than the
2052 specified usecase to new snd devices */
2053 list_for_each(node, &adev->usecase_list) {
2054 usecase = node_to_item(node, struct audio_usecase, list);
2055 /* Update the in_snd_device only before enabling the audio route */
2056 if (switch_device[usecase->id] ) {
2057 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002058 if (usecase->type != VOICE_CALL) {
2059 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302060 if (usecase->type == VOIP_CALL) {
2061 snd_device_t voip_snd_device;
2062 voip_snd_device = platform_get_output_snd_device(adev->platform,
2063 uc_info->stream.out,
2064 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002065 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302066 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002067 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302068 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302069 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002070 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002071 }
2072 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002073 }
2074}
2075
Mingming Yin3a941d42016-02-17 18:08:05 -08002076static void reset_hdmi_sink_caps(struct stream_out *out) {
2077 int i = 0;
2078
2079 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2080 out->supported_channel_masks[i] = 0;
2081 }
2082 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2083 out->supported_formats[i] = 0;
2084 }
2085 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2086 out->supported_sample_rates[i] = 0;
2087 }
2088}
2089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002091static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092{
Mingming Yin3a941d42016-02-17 18:08:05 -08002093 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002094 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2095 out->extconn.cs.controller,
2096 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097
Mingming Yin3a941d42016-02-17 18:08:05 -08002098 reset_hdmi_sink_caps(out);
2099
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002100 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002101 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002102 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002103 out->extconn.cs.stream);
2104 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002105 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002106 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002107 }
2108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002111 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002112 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002113 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2114 case 6:
2115 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2116 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2117 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2118 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2119 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2120 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 break;
2122 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002123 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002124 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 break;
2126 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002127
2128 // check channel format caps
2129 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002130 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2131 out->extconn.cs.controller,
2132 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002133 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2134 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2135 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2136 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2137 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2138 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2139 }
2140
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002141 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2142 out->extconn.cs.controller,
2143 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002144 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2145 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2146 }
2147
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002148 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2149 out->extconn.cs.controller,
2150 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002151 ALOGV(":%s HDMI supports DTS format", __func__);
2152 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2153 }
2154
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002155 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2156 out->extconn.cs.controller,
2157 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002158 ALOGV(":%s HDMI supports DTS HD format", __func__);
2159 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2160 }
2161
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002162 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2163 out->extconn.cs.controller,
2164 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002165 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2166 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2167 }
2168
Mingming Yin3a941d42016-02-17 18:08:05 -08002169
2170 // check sample rate caps
2171 i = 0;
2172 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002173 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2174 out->extconn.cs.controller,
2175 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002176 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2177 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2178 }
2179 }
2180
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002181 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182}
2183
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002184static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2185 uint32_t *supported_sample_rates __unused,
2186 uint32_t max_rates __unused)
2187{
2188 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2189 supported_sample_rates,
2190 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302191 ssize_t i = 0;
2192
2193 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002194 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2195 supported_sample_rates[i]);
2196 }
2197 return count;
2198}
2199
2200static inline int read_usb_sup_channel_masks(bool is_playback,
2201 audio_channel_mask_t *supported_channel_masks,
2202 uint32_t max_masks)
2203{
2204 int channels = audio_extn_usb_get_max_channels(is_playback);
2205 int channel_count;
2206 uint32_t num_masks = 0;
2207 if (channels > MAX_HIFI_CHANNEL_COUNT)
2208 channels = MAX_HIFI_CHANNEL_COUNT;
2209
2210 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002211 // start from 2 channels as framework currently doesn't support mono.
2212 if (channels >= FCC_2) {
2213 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2214 }
2215 for (channel_count = FCC_2;
2216 channel_count <= channels && num_masks < max_masks;
2217 ++channel_count) {
2218 supported_channel_masks[num_masks++] =
2219 audio_channel_mask_for_index_assignment_from_count(channel_count);
2220 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002221 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002222 // For capture we report all supported channel masks from 1 channel up.
2223 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002224 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2225 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002226 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2227 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2228 if (channel_count <= FCC_2) {
2229 mask = audio_channel_in_mask_from_count(channel_count);
2230 supported_channel_masks[num_masks++] = mask;
2231 }
2232 const audio_channel_mask_t index_mask =
2233 audio_channel_mask_for_index_assignment_from_count(channel_count);
2234 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2235 supported_channel_masks[num_masks++] = index_mask;
2236 }
2237 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002238 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302239
vincenttewf51c94e2019-05-07 10:28:53 +08002240 for (size_t i = 0; i < num_masks; ++i) {
2241 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2242 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302243 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002244 return num_masks;
2245}
2246
2247static inline int read_usb_sup_formats(bool is_playback __unused,
2248 audio_format_t *supported_formats,
2249 uint32_t max_formats __unused)
2250{
2251 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2252 switch (bitwidth) {
2253 case 24:
2254 // XXX : usb.c returns 24 for s24 and s24_le?
2255 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2256 break;
2257 case 32:
2258 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2259 break;
2260 case 16:
2261 default :
2262 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2263 break;
2264 }
2265 ALOGV("%s: %s supported format %d", __func__,
2266 is_playback ? "P" : "C", bitwidth);
2267 return 1;
2268}
2269
2270static inline int read_usb_sup_params_and_compare(bool is_playback,
2271 audio_format_t *format,
2272 audio_format_t *supported_formats,
2273 uint32_t max_formats,
2274 audio_channel_mask_t *mask,
2275 audio_channel_mask_t *supported_channel_masks,
2276 uint32_t max_masks,
2277 uint32_t *rate,
2278 uint32_t *supported_sample_rates,
2279 uint32_t max_rates) {
2280 int ret = 0;
2281 int num_formats;
2282 int num_masks;
2283 int num_rates;
2284 int i;
2285
2286 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2287 max_formats);
2288 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2289 max_masks);
2290
2291 num_rates = read_usb_sup_sample_rates(is_playback,
2292 supported_sample_rates, max_rates);
2293
2294#define LUT(table, len, what, dflt) \
2295 for (i=0; i<len && (table[i] != what); i++); \
2296 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2297
2298 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2299 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2300 LUT(supported_sample_rates, num_rates, *rate, 0);
2301
2302#undef LUT
2303 return ret < 0 ? -EINVAL : 0; // HACK TBD
2304}
2305
Alexy Josephb1379942016-01-29 15:49:38 -08002306audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002307 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002308{
2309 struct audio_usecase *usecase;
2310 struct listnode *node;
2311
2312 list_for_each(node, &adev->usecase_list) {
2313 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002314 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002315 ALOGV("%s: usecase id %d", __func__, usecase->id);
2316 return usecase->id;
2317 }
2318 }
2319 return USECASE_INVALID;
2320}
2321
Alexy Josephb1379942016-01-29 15:49:38 -08002322struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002323 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002324{
2325 struct audio_usecase *usecase;
2326 struct listnode *node;
2327
2328 list_for_each(node, &adev->usecase_list) {
2329 usecase = node_to_item(node, struct audio_usecase, list);
2330 if (usecase->id == uc_id)
2331 return usecase;
2332 }
2333 return NULL;
2334}
2335
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302336/*
2337 * is a true native playback active
2338 */
2339bool audio_is_true_native_stream_active(struct audio_device *adev)
2340{
2341 bool active = false;
2342 int i = 0;
2343 struct listnode *node;
2344
2345 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2346 ALOGV("%s:napb: not in true mode or non hdphones device",
2347 __func__);
2348 active = false;
2349 goto exit;
2350 }
2351
2352 list_for_each(node, &adev->usecase_list) {
2353 struct audio_usecase *uc;
2354 uc = node_to_item(node, struct audio_usecase, list);
2355 struct stream_out *curr_out =
2356 (struct stream_out*) uc->stream.out;
2357
2358 if (curr_out && PCM_PLAYBACK == uc->type) {
2359 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2360 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2361 uc->id, curr_out->sample_rate,
2362 curr_out->bit_width,
2363 platform_get_snd_device_name(uc->out_snd_device));
2364
2365 if (is_offload_usecase(uc->id) &&
2366 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2367 active = true;
2368 ALOGD("%s:napb:native stream detected", __func__);
2369 }
2370 }
2371 }
2372exit:
2373 return active;
2374}
2375
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002376uint32_t adev_get_dsp_bit_width_enforce_mode()
2377{
2378 if (adev == NULL) {
2379 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2380 return 0;
2381 }
2382 return adev->dsp_bit_width_enforce_mode;
2383}
2384
2385static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2386{
2387 char value[PROPERTY_VALUE_MAX];
2388 int trial;
2389 uint32_t dsp_bit_width_enforce_mode = 0;
2390
2391 if (!mixer) {
2392 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2393 __func__);
2394 return 0;
2395 }
2396
2397 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2398 value, NULL) > 0) {
2399 trial = atoi(value);
2400 switch (trial) {
2401 case 16:
2402 dsp_bit_width_enforce_mode = 16;
2403 break;
2404 case 24:
2405 dsp_bit_width_enforce_mode = 24;
2406 break;
2407 case 32:
2408 dsp_bit_width_enforce_mode = 32;
2409 break;
2410 default:
2411 dsp_bit_width_enforce_mode = 0;
2412 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2413 break;
2414 }
2415 }
2416
2417 return dsp_bit_width_enforce_mode;
2418}
2419
2420static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2421 uint32_t enforce_mode,
2422 bool enable)
2423{
2424 struct mixer_ctl *ctl = NULL;
2425 const char *mixer_ctl_name = "ASM Bit Width";
2426 uint32_t asm_bit_width_mode = 0;
2427
2428 if (enforce_mode == 0) {
2429 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2430 return;
2431 }
2432
2433 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2434 if (!ctl) {
2435 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2436 __func__, mixer_ctl_name);
2437 return;
2438 }
2439
2440 if (enable)
2441 asm_bit_width_mode = enforce_mode;
2442 else
2443 asm_bit_width_mode = 0;
2444
2445 ALOGV("%s DSP bit width feature status is %d width=%d",
2446 __func__, enable, asm_bit_width_mode);
2447 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2448 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2449 asm_bit_width_mode);
2450
2451 return;
2452}
2453
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302454/*
2455 * if native DSD playback active
2456 */
2457bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2458{
2459 bool active = false;
2460 struct listnode *node = NULL;
2461 struct audio_usecase *uc = NULL;
2462 struct stream_out *curr_out = NULL;
2463
2464 list_for_each(node, &adev->usecase_list) {
2465 uc = node_to_item(node, struct audio_usecase, list);
2466 curr_out = (struct stream_out*) uc->stream.out;
2467
2468 if (curr_out && PCM_PLAYBACK == uc->type &&
2469 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2470 active = true;
2471 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302472 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302473 }
2474 }
2475 return active;
2476}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302477
2478static bool force_device_switch(struct audio_usecase *usecase)
2479{
2480 bool ret = false;
2481 bool is_it_true_mode = false;
2482
Zhou Song30f2c3e2018-02-08 14:02:15 +08002483 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302484 usecase->type == TRANSCODE_LOOPBACK_RX ||
2485 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002486 return false;
2487 }
2488
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002489 if(usecase->stream.out == NULL) {
2490 ALOGE("%s: stream.out is NULL", __func__);
2491 return false;
2492 }
2493
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302494 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002495 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002496 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2497 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302498 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2499 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2500 (!is_it_true_mode && adev->native_playback_enabled)){
2501 ret = true;
2502 ALOGD("napb: time to toggle native mode");
2503 }
2504 }
2505
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302506 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302507 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2508 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002509 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302510 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302511 ALOGD("Force a2dp device switch to update new encoder config");
2512 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002513 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302514
Florian Pfister1a84f312018-07-19 14:38:18 +02002515 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302516 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2517 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002518 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302519 return ret;
2520}
2521
Aalique Grahame22e49102018-12-18 14:23:57 -08002522static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2523{
2524 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2525}
2526
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302527bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2528{
2529 bool ret=false;
2530 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002531 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2532 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302533 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2534 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002535 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302536 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002537 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2538 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302539 ret = true;
2540
2541 return ret;
2542}
2543
2544bool is_a2dp_device(snd_device_t out_snd_device)
2545{
2546 bool ret=false;
2547 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2548 ret = true;
2549
2550 return ret;
2551}
2552
2553bool is_bt_soc_on(struct audio_device *adev)
2554{
2555 struct mixer_ctl *ctl;
2556 char *mixer_ctl_name = "BT SOC status";
2557 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2558 bool bt_soc_status = true;
2559 if (!ctl) {
2560 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2561 __func__, mixer_ctl_name);
2562 /*This is to ensure we dont break targets which dont have the kernel change*/
2563 return true;
2564 }
2565 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2566 ALOGD("BT SOC status: %d",bt_soc_status);
2567 return bt_soc_status;
2568}
2569
Zhou Song331c8e52019-08-26 14:16:12 +08002570static int configure_btsco_sample_rate(snd_device_t snd_device)
2571{
2572 struct mixer_ctl *ctl = NULL;
2573 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2574 char *rate_str = NULL;
2575 bool is_rx_dev = true;
2576
2577 if (is_btsco_device(snd_device, snd_device)) {
2578 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2579 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2580 if (!ctl_sr_tx || !ctl_sr_rx) {
2581 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2582 if (!ctl_sr)
2583 return -ENOSYS;
2584 }
2585
2586 switch (snd_device) {
2587 case SND_DEVICE_OUT_BT_SCO:
2588 rate_str = "KHZ_8";
2589 break;
2590 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2591 case SND_DEVICE_IN_BT_SCO_MIC:
2592 rate_str = "KHZ_8";
2593 is_rx_dev = false;
2594 break;
2595 case SND_DEVICE_OUT_BT_SCO_WB:
2596 rate_str = "KHZ_16";
2597 break;
2598 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2599 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2600 rate_str = "KHZ_16";
2601 is_rx_dev = false;
2602 break;
2603 default:
2604 return 0;
2605 }
2606
2607 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2608 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2609 return -ENOSYS;
2610 }
2611 return 0;
2612}
2613
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302614int out_standby_l(struct audio_stream *stream);
2615
Eric Laurent637e2d42018-11-15 12:24:31 -08002616struct stream_in *adev_get_active_input(const struct audio_device *adev)
2617{
2618 struct listnode *node;
2619 struct stream_in *last_active_in = NULL;
2620
2621 /* Get last added active input.
2622 * TODO: We may use a priority mechanism to pick highest priority active source */
2623 list_for_each(node, &adev->usecase_list)
2624 {
2625 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2626 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2627 last_active_in = usecase->stream.in;
2628 }
2629
2630 return last_active_in;
2631}
2632
2633struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2634{
2635 struct listnode *node;
2636
2637 /* First check active inputs with voice communication source and then
2638 * any input if audio mode is in communication */
2639 list_for_each(node, &adev->usecase_list)
2640 {
2641 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2642 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2643 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2644 return usecase->stream.in;
2645 }
2646 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2647 return adev_get_active_input(adev);
2648
2649 return NULL;
2650}
2651
Carter Hsu2e429db2019-05-14 18:50:52 +08002652/*
2653 * Aligned with policy.h
2654 */
2655static inline int source_priority(int inputSource)
2656{
2657 switch (inputSource) {
2658 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2659 return 9;
2660 case AUDIO_SOURCE_CAMCORDER:
2661 return 8;
2662 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2663 return 7;
2664 case AUDIO_SOURCE_UNPROCESSED:
2665 return 6;
2666 case AUDIO_SOURCE_MIC:
2667 return 5;
2668 case AUDIO_SOURCE_ECHO_REFERENCE:
2669 return 4;
2670 case AUDIO_SOURCE_FM_TUNER:
2671 return 3;
2672 case AUDIO_SOURCE_VOICE_RECOGNITION:
2673 return 2;
2674 case AUDIO_SOURCE_HOTWORD:
2675 return 1;
2676 default:
2677 break;
2678 }
2679 return 0;
2680}
2681
2682static struct stream_in *get_priority_input(struct audio_device *adev)
2683{
2684 struct listnode *node;
2685 struct audio_usecase *usecase;
2686 int last_priority = 0, priority;
2687 struct stream_in *priority_in = NULL;
2688 struct stream_in *in;
2689
2690 list_for_each(node, &adev->usecase_list) {
2691 usecase = node_to_item(node, struct audio_usecase, list);
2692 if (usecase->type == PCM_CAPTURE) {
2693 in = usecase->stream.in;
2694 if (!in)
2695 continue;
2696 priority = source_priority(in->source);
2697
2698 if (priority > last_priority) {
2699 last_priority = priority;
2700 priority_in = in;
2701 }
2702 }
2703 }
2704 return priority_in;
2705}
2706
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002707int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002709 snd_device_t out_snd_device = SND_DEVICE_NONE;
2710 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 struct audio_usecase *usecase = NULL;
2712 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002713 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002714 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302715 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002716 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002717 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302719 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2720
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002721 usecase = get_usecase_from_list(adev, uc_id);
2722 if (usecase == NULL) {
2723 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2724 return -EINVAL;
2725 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002727 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002728 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002729 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002730 (usecase->type == ICC_CALL) ||
2731 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302732 if(usecase->stream.out == NULL) {
2733 ALOGE("%s: stream.out is NULL", __func__);
2734 return -EINVAL;
2735 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002736 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002737 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2738 uc_id);
2739 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2740 uc_id);
2741 } else {
2742 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302743 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002744 in_snd_device = platform_get_input_snd_device(adev->platform,
2745 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302746 &usecase->stream.out->device_list,
2747 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002748 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002749 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302750 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302751 if (usecase->stream.inout == NULL) {
2752 ALOGE("%s: stream.inout is NULL", __func__);
2753 return -EINVAL;
2754 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002755 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302756 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2757 stream_out.format = usecase->stream.inout->out_config.format;
2758 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302759 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002760 assign_devices(&usecase->device_list,
2761 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302762 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2763 if (usecase->stream.inout == NULL) {
2764 ALOGE("%s: stream.inout is NULL", __func__);
2765 return -EINVAL;
2766 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302767 struct listnode out_devices;
2768 list_init(&out_devices);
2769 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2770 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002771 assign_devices(&usecase->device_list,
2772 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002773 } else {
2774 /*
2775 * If the voice call is active, use the sound devices of voice call usecase
2776 * so that it would not result any device switch. All the usecases will
2777 * be switched to new device when select_devices() is called for voice call
2778 * usecase. This is to avoid switching devices for voice call when
2779 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002780 * choose voice call device only if the use case device is
2781 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002782 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002783 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002784 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002785 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002786 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2787 is_codec_backend_out_device_type(&usecase->device_list)) ||
2788 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2789 is_codec_backend_in_device_type(&usecase->device_list)) ||
2790 is_single_device_type_equal(&vc_usecase->device_list,
2791 AUDIO_DEVICE_OUT_HEARING_AID) ||
2792 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002793 AUDIO_DEVICE_IN_VOICE_CALL) ||
2794 (is_single_device_type_equal(&usecase->device_list,
2795 AUDIO_DEVICE_IN_USB_HEADSET) &&
2796 is_single_device_type_equal(&vc_usecase->device_list,
2797 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002798 in_snd_device = vc_usecase->in_snd_device;
2799 out_snd_device = vc_usecase->out_snd_device;
2800 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002801 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002802 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002803 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002804 if ((voip_usecase != NULL) &&
2805 (usecase->type == PCM_PLAYBACK) &&
2806 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002807 out_snd_device_backend_match = platform_check_backends_match(
2808 voip_usecase->out_snd_device,
2809 platform_get_output_snd_device(
2810 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302811 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002812 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002813 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2814 (is_codec_backend_out_device_type(&usecase->device_list) ||
2815 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002816 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002817 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002818 in_snd_device = voip_usecase->in_snd_device;
2819 out_snd_device = voip_usecase->out_snd_device;
2820 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002821 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002822 hfp_ucid = audio_extn_hfp_get_usecase();
2823 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002824 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002825 in_snd_device = hfp_usecase->in_snd_device;
2826 out_snd_device = hfp_usecase->out_snd_device;
2827 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002828 }
2829 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302830 if (usecase->stream.out == NULL) {
2831 ALOGE("%s: stream.out is NULL", __func__);
2832 return -EINVAL;
2833 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002834 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002835 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002836 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002837 struct stream_out *voip_out = adev->primary_output;
2838 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002839 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002840 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2841 else
2842 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302843 usecase->stream.out,
2844 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002845 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002846
Eric Laurent637e2d42018-11-15 12:24:31 -08002847 if (voip_usecase)
2848 voip_out = voip_usecase->stream.out;
2849
2850 if (usecase->stream.out == voip_out && voip_in != NULL)
2851 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002852 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002853 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302854 if (usecase->stream.in == NULL) {
2855 ALOGE("%s: stream.in is NULL", __func__);
2856 return -EINVAL;
2857 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002858 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002859 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002860 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002861 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002862 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002863 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002864
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002865 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002866 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002867 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2868 USECASE_AUDIO_PLAYBACK_VOIP);
2869
Carter Hsu2e429db2019-05-14 18:50:52 +08002870 usecase->stream.in->enable_ec_port = false;
2871
Zhou Song62ea0282020-03-22 19:53:01 +08002872 bool is_ha_usecase = adev->ha_proxy_enable ?
2873 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2874 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2875 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002876 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002877 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002878 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002879 } else if (adev->primary_output &&
2880 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002881 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002882 } else {
2883 /* forcing speaker o/p device to get matching i/p pair
2884 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002885 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002886 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002887 priority_in = voip_in;
2888 } else {
2889 /* get the input with the highest priority source*/
2890 priority_in = get_priority_input(adev);
2891
2892 if (!priority_in)
2893 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002894 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002895 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2896 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2897 }
2898 else
2899 in_snd_device = platform_get_input_snd_device(adev->platform,
2900 priority_in,
2901 &out_devices,
2902 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002903 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002904 }
2905 }
2906
2907 if (out_snd_device == usecase->out_snd_device &&
2908 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302909
2910 if (!force_device_switch(usecase))
2911 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 }
2913
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002914 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002915 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002916 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002917 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2918 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302919 }
2920
Aalique Grahame22e49102018-12-18 14:23:57 -08002921 if (out_snd_device != SND_DEVICE_NONE &&
2922 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2923 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2924 __func__,
2925 use_case_table[uc_id],
2926 adev->last_logged_snd_device[uc_id][0],
2927 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2928 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2929 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2930 -1,
2931 out_snd_device,
2932 platform_get_snd_device_name(out_snd_device),
2933 platform_get_snd_device_acdb_id(out_snd_device));
2934 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2935 }
2936 if (in_snd_device != SND_DEVICE_NONE &&
2937 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2938 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2939 __func__,
2940 use_case_table[uc_id],
2941 adev->last_logged_snd_device[uc_id][1],
2942 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2943 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2944 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2945 -1,
2946 in_snd_device,
2947 platform_get_snd_device_name(in_snd_device),
2948 platform_get_snd_device_acdb_id(in_snd_device));
2949 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2950 }
2951
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953 /*
2954 * Limitation: While in call, to do a device switch we need to disable
2955 * and enable both RX and TX devices though one of them is same as current
2956 * device.
2957 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002958 if ((usecase->type == VOICE_CALL) &&
2959 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2960 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002961 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002962 }
2963
2964 if (((usecase->type == VOICE_CALL) ||
2965 (usecase->type == VOIP_CALL)) &&
2966 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2967 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302968 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002969 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002970 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002971
2972 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302973 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002974 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002975 }
2976
Aalique Grahame22e49102018-12-18 14:23:57 -08002977 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2978 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002979 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302980 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002981 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2982 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2983 else
2984 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302985 }
2986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002987 /* Disable current sound devices */
2988 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002989 disable_audio_route(adev, usecase);
2990 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 }
2992
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002993 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002994 disable_audio_route(adev, usecase);
2995 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 }
2997
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002998 /* Applicable only on the targets that has external modem.
2999 * New device information should be sent to modem before enabling
3000 * the devices to reduce in-call device switch time.
3001 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003002 if ((usecase->type == VOICE_CALL) &&
3003 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3004 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003005 status = platform_switch_voice_call_enable_device_config(adev->platform,
3006 out_snd_device,
3007 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003008 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003009
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003010 /* Enable new sound devices */
3011 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003012 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303013 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303014 if (platform_check_codec_asrc_support(adev->platform))
3015 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003016 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003017 /* Enable haptics device for haptic usecase */
3018 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3019 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 }
3021
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003022 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303023 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003024 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003025 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003026
Avinash Vaish71a8b972014-07-24 15:36:33 +05303027 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003028 status = platform_switch_voice_call_device_post(adev->platform,
3029 out_snd_device,
3030 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05303031 enable_audio_route_for_voice_usecases(adev, usecase);
3032 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003033
sangwoo170731f2013-06-08 15:36:36 +09003034 usecase->in_snd_device = in_snd_device;
3035 usecase->out_snd_device = out_snd_device;
3036
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303037 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3038 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303039 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003040 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003041 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003042 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3043 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3044 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3045 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3046 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3047 /*
3048 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3049 * configured device sample rate, if not update the COPP rate to be equal to the
3050 * device sample rate, else open COPP at stream sample rate
3051 */
3052 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3053 usecase->stream.out->sample_rate,
3054 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303055 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303056 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3057 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303058 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003059 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3060 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3061 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3062 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003063 }
3064 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003065
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003066 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003067
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003068 /* If input stream is already running then effect needs to be
3069 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003070 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003071 check_and_enable_effect(adev);
3072
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003073 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003074 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303075 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003076 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3077
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003078 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303079 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003080 voice_extn_compress_voip_is_started(adev))
3081 voice_set_sidetone(adev, out_snd_device, true);
3082 }
3083
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003084 /* Applicable only on the targets that has external modem.
3085 * Enable device command should be sent to modem only after
3086 * enabling voice call mixer controls
3087 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003088 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003089 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3090 out_snd_device,
3091 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303092
3093 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003094 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303095 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003096 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303097 if (is_bt_soc_on(adev) == false){
3098 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003099 if (in->pcm != NULL)
3100 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303101 }
3102 }
3103 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3104 && usecase->stream.out->started) {
3105 if (is_bt_soc_on(adev) == false) {
3106 ALOGD("BT SCO/A2DP disconnected while in connection");
3107 out_standby_l(&usecase->stream.out->stream.common);
3108 }
3109 }
3110 } else if ((usecase->stream.out != NULL) &&
3111 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303112 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3113 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003114 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303115 usecase->stream.out->started) {
3116 if (is_bt_soc_on(adev) == false) {
3117 ALOGD("BT SCO/A2dp disconnected while in connection");
3118 out_standby_l(&usecase->stream.out->stream.common);
3119 }
3120 }
3121 }
3122
Yung Ti Su70cb8242018-06-22 17:38:47 +08003123 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003124 struct stream_out *voip_out = voip_usecase->stream.out;
3125 audio_extn_utils_send_app_type_gain(adev,
3126 voip_out->app_type_cfg.app_type,
3127 &voip_out->app_type_cfg.gain[0]);
3128 }
3129
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003130 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 return status;
3133}
3134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135static int stop_input_stream(struct stream_in *in)
3136{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303137 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303139
3140 if (in == NULL) {
3141 ALOGE("%s: stream_in ptr is NULL", __func__);
3142 return -EINVAL;
3143 }
3144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003146 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147
Eric Laurent994a6932013-07-17 11:51:42 -07003148 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003149 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 uc_info = get_usecase_from_list(adev, in->usecase);
3151 if (uc_info == NULL) {
3152 ALOGE("%s: Could not find the usecase (%d) in the list",
3153 __func__, in->usecase);
3154 return -EINVAL;
3155 }
3156
Carter Hsu2e429db2019-05-14 18:50:52 +08003157 priority_in = get_priority_input(adev);
3158
Derek Chenea197282019-01-07 17:35:01 -08003159 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3160 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003161
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003162 /* Close in-call recording streams */
3163 voice_check_and_stop_incall_rec_usecase(adev, in);
3164
Eric Laurent150dbfe2013-02-27 14:31:02 -08003165 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003166 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003167
3168 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003169 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003171 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303172 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3173
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003174 list_remove(&uc_info->list);
3175 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176
Carter Hsu2e429db2019-05-14 18:50:52 +08003177 if (priority_in == in) {
3178 priority_in = get_priority_input(adev);
3179 if (priority_in)
3180 select_devices(adev, priority_in->usecase);
3181 }
3182
Vatsal Buchac09ae062018-11-14 13:25:08 +05303183 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003184 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 return ret;
3186}
3187
3188int start_input_stream(struct stream_in *in)
3189{
3190 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003191 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303193
3194 if (in == NULL) {
3195 ALOGE("%s: stream_in ptr is NULL", __func__);
3196 return -EINVAL;
3197 }
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003200 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003201 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202
Mingming Yin2664a5b2015-09-03 10:53:11 -07003203 if (get_usecase_from_list(adev, usecase) == NULL)
3204 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303205 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3206 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003207
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303208 if (CARD_STATUS_OFFLINE == in->card_status||
3209 CARD_STATUS_OFFLINE == adev->card_status) {
3210 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303211 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303212 goto error_config;
3213 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303214
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003215 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303216 if (!adev->bt_sco_on) {
3217 ALOGE("%s: SCO profile is not ready, return error", __func__);
3218 ret = -EIO;
3219 goto error_config;
3220 }
3221 }
3222
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003223 /* Check if source matches incall recording usecase criteria */
3224 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3225 if (ret)
3226 goto error_config;
3227 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003228 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3229
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303230 if (audio_extn_cin_attached_usecase(in))
3231 audio_extn_cin_acquire_usecase(in);
3232
Mingming Yin2664a5b2015-09-03 10:53:11 -07003233 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3234 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3235 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003236 ret = -EINVAL;
3237 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003238 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003239
Eric Laurentb23d5282013-05-14 15:27:20 -07003240 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241 if (in->pcm_device_id < 0) {
3242 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3243 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003244 ret = -EINVAL;
3245 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003249
3250 if (!uc_info) {
3251 ret = -ENOMEM;
3252 goto error_config;
3253 }
3254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 uc_info->id = in->usecase;
3256 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003257 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003258 list_init(&uc_info->device_list);
3259 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003260 uc_info->in_snd_device = SND_DEVICE_NONE;
3261 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003263 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003264 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303265 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3266 adev->perf_lock_opts,
3267 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003268 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269
Derek Chenea197282019-01-07 17:35:01 -08003270 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3271 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003272
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303273 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3274
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303275 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303276 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303277 if (ret)
3278 goto error_open;
3279 else
3280 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003281 }
3282
Haynes Mathew George16081042017-05-31 17:16:49 -07003283 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003284 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003285 ALOGE("%s: pcm stream not ready", __func__);
3286 goto error_open;
3287 }
3288 ret = pcm_start(in->pcm);
3289 if (ret < 0) {
3290 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3291 goto error_open;
3292 }
3293 } else {
3294 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3295 unsigned int pcm_open_retry_count = 0;
3296
Zhou Song62ea0282020-03-22 19:53:01 +08003297 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3298 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003299 flags |= PCM_MMAP | PCM_NOIRQ;
3300 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3301 } else if (in->realtime) {
3302 flags |= PCM_MMAP | PCM_NOIRQ;
3303 }
3304
Garmond Leunge2433c32017-09-28 21:51:22 -07003305 if (audio_extn_ffv_get_stream() == in) {
3306 ALOGD("%s: ffv stream, update pcm config", __func__);
3307 audio_extn_ffv_update_pcm_config(&config);
3308 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003309 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3310 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3311
3312 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003313 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003314 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003315 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003316 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303317 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303318 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3319 adev->card_status = CARD_STATUS_OFFLINE;
3320 in->card_status = CARD_STATUS_OFFLINE;
3321 ret = -EIO;
3322 goto error_open;
3323 }
3324
Haynes Mathew George16081042017-05-31 17:16:49 -07003325 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3326 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3327 if (in->pcm != NULL) {
3328 pcm_close(in->pcm);
3329 in->pcm = NULL;
3330 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003331 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003332 ret = -EIO;
3333 goto error_open;
3334 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003335 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003336 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3337 continue;
3338 }
3339 break;
3340 }
3341
3342 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003343 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003344 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003345 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003346 if (ret < 0) {
3347 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3348 pcm_close(in->pcm);
3349 in->pcm = NULL;
3350 goto error_open;
3351 }
3352 register_in_stream(in);
3353 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003354 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003355 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003356 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003357 if (ret < 0) {
3358 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003359 pcm_close(in->pcm);
3360 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003361 goto error_open;
3362 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003363 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003364 }
3365
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003366 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003367 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3368 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003369
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003370 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303371 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3372
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303373done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003374 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303375 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303376 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303377 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003378 return ret;
3379
3380error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003381 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303382 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003384
Eric Laurentc8400632013-02-14 19:04:54 -08003385error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003386 if (audio_extn_cin_attached_usecase(in))
3387 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303388 /*
3389 * sleep 50ms to allow sufficient time for kernel
3390 * drivers to recover incases like SSR.
3391 */
3392 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003393 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303394 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003395 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396}
3397
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003398void lock_input_stream(struct stream_in *in)
3399{
3400 pthread_mutex_lock(&in->pre_lock);
3401 pthread_mutex_lock(&in->lock);
3402 pthread_mutex_unlock(&in->pre_lock);
3403}
3404
3405void lock_output_stream(struct stream_out *out)
3406{
3407 pthread_mutex_lock(&out->pre_lock);
3408 pthread_mutex_lock(&out->lock);
3409 pthread_mutex_unlock(&out->pre_lock);
3410}
3411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412/* must be called with out->lock locked */
3413static int send_offload_cmd_l(struct stream_out* out, int command)
3414{
3415 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3416
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003417 if (!cmd) {
3418 ALOGE("failed to allocate mem for command 0x%x", command);
3419 return -ENOMEM;
3420 }
3421
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003422 ALOGVV("%s %d", __func__, command);
3423
3424 cmd->cmd = command;
3425 list_add_tail(&out->offload_cmd_list, &cmd->node);
3426 pthread_cond_signal(&out->offload_cond);
3427 return 0;
3428}
3429
Weiyin Jiang280ea742020-09-08 20:28:22 +08003430/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431static void stop_compressed_output_l(struct stream_out *out)
3432{
3433 out->offload_state = OFFLOAD_STATE_IDLE;
3434 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003435 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003436 if (out->compr != NULL) {
3437 compress_stop(out->compr);
3438 while (out->offload_thread_blocked) {
3439 pthread_cond_wait(&out->cond, &out->lock);
3440 }
3441 }
3442}
3443
Varun Balaraje49253e2017-07-06 19:48:56 +05303444bool is_interactive_usecase(audio_usecase_t uc_id)
3445{
3446 unsigned int i;
3447 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3448 if (uc_id == interactive_usecases[i])
3449 return true;
3450 }
3451 return false;
3452}
3453
3454static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3455{
3456 audio_usecase_t ret_uc = USECASE_INVALID;
3457 unsigned int intract_uc_index;
3458 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3459
3460 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3461 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3462 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3463 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3464 ret_uc = interactive_usecases[intract_uc_index];
3465 break;
3466 }
3467 }
3468
3469 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3470 return ret_uc;
3471}
3472
3473static void free_interactive_usecase(struct audio_device *adev,
3474 audio_usecase_t uc_id)
3475{
3476 unsigned int interact_uc_index;
3477 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3478
3479 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3480 if (interactive_usecases[interact_uc_index] == uc_id) {
3481 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3482 break;
3483 }
3484 }
3485 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3486}
3487
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003488bool is_offload_usecase(audio_usecase_t uc_id)
3489{
3490 unsigned int i;
3491 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3492 if (uc_id == offload_usecases[i])
3493 return true;
3494 }
3495 return false;
3496}
3497
Dhananjay Kumarac341582017-02-23 23:42:25 +05303498static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003499{
vivek mehta446c3962015-09-14 10:57:35 -07003500 audio_usecase_t ret_uc = USECASE_INVALID;
3501 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003502 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003503 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303504 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003505 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3506 else
3507 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003508
vivek mehta446c3962015-09-14 10:57:35 -07003509 pthread_mutex_lock(&adev->lock);
3510 if (get_usecase_from_list(adev, ret_uc) != NULL)
3511 ret_uc = USECASE_INVALID;
3512 pthread_mutex_unlock(&adev->lock);
3513
3514 return ret_uc;
3515 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003516
3517 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003518 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3519 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3520 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3521 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003522 break;
3523 }
3524 }
vivek mehta446c3962015-09-14 10:57:35 -07003525
3526 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3527 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003528}
3529
3530static void free_offload_usecase(struct audio_device *adev,
3531 audio_usecase_t uc_id)
3532{
vivek mehta446c3962015-09-14 10:57:35 -07003533 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003534 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003535
3536 if (!adev->multi_offload_enable)
3537 return;
3538
3539 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3540 if (offload_usecases[offload_uc_index] == uc_id) {
3541 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003542 break;
3543 }
3544 }
3545 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3546}
3547
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003548static void *offload_thread_loop(void *context)
3549{
3550 struct stream_out *out = (struct stream_out *) context;
3551 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003552 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003554 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003555 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3557
3558 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003559 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003560 out->offload_state = OFFLOAD_STATE_IDLE;
3561 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003562 for (;;) {
3563 struct offload_cmd *cmd = NULL;
3564 stream_callback_event_t event;
3565 bool send_callback = false;
3566
3567 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3568 __func__, list_empty(&out->offload_cmd_list),
3569 out->offload_state);
3570 if (list_empty(&out->offload_cmd_list)) {
3571 ALOGV("%s SLEEPING", __func__);
3572 pthread_cond_wait(&out->offload_cond, &out->lock);
3573 ALOGV("%s RUNNING", __func__);
3574 continue;
3575 }
3576
3577 item = list_head(&out->offload_cmd_list);
3578 cmd = node_to_item(item, struct offload_cmd, node);
3579 list_remove(item);
3580
3581 ALOGVV("%s STATE %d CMD %d out->compr %p",
3582 __func__, out->offload_state, cmd->cmd, out->compr);
3583
3584 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3585 free(cmd);
3586 break;
3587 }
3588
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003589 // allow OFFLOAD_CMD_ERROR reporting during standby
3590 // this is needed to handle failures during compress_open
3591 // Note however that on a pause timeout, the stream is closed
3592 // and no offload usecase will be active. Therefore this
3593 // special case is needed for compress_open failures alone
3594 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3595 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003597 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003598 pthread_cond_signal(&out->cond);
3599 continue;
3600 }
3601 out->offload_thread_blocked = true;
3602 pthread_mutex_unlock(&out->lock);
3603 send_callback = false;
3604 switch(cmd->cmd) {
3605 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003606 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003607 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003608 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 send_callback = true;
3610 event = STREAM_CBK_EVENT_WRITE_READY;
3611 break;
3612 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003613 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303614 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003615 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303616 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003617 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303618 if (ret < 0)
3619 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303620 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303621 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003622 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003623 else
3624 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003625 if (-ENETRESET != ret && !(-EINTR == ret &&
3626 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303627 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303628 pthread_mutex_lock(&out->lock);
3629 out->send_new_metadata = 1;
3630 out->send_next_track_params = true;
3631 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303632 event = STREAM_CBK_EVENT_DRAIN_READY;
3633 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3634 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303635 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003636 break;
3637 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003638 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003639 ret = compress_drain(out->compr);
3640 ALOGD("copl(%p):out of compress_drain", out);
3641 // EINTR check avoids drain interruption due to SSR
3642 if (-ENETRESET != ret && !(-EINTR == ret &&
3643 CARD_STATUS_OFFLINE == out->card_status)) {
3644 send_callback = true;
3645 event = STREAM_CBK_EVENT_DRAIN_READY;
3646 } else
3647 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303649 case OFFLOAD_CMD_ERROR:
3650 ALOGD("copl(%p): sending error callback to AF", out);
3651 send_callback = true;
3652 event = STREAM_CBK_EVENT_ERROR;
3653 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 default:
3655 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3656 break;
3657 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003658 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003659 out->offload_thread_blocked = false;
3660 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003661 if (send_callback && out->client_callback) {
3662 ALOGVV("%s: sending client_callback event %d", __func__, event);
3663 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003664 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 free(cmd);
3666 }
3667
3668 pthread_cond_signal(&out->cond);
3669 while (!list_empty(&out->offload_cmd_list)) {
3670 item = list_head(&out->offload_cmd_list);
3671 list_remove(item);
3672 free(node_to_item(item, struct offload_cmd, node));
3673 }
3674 pthread_mutex_unlock(&out->lock);
3675
3676 return NULL;
3677}
3678
3679static int create_offload_callback_thread(struct stream_out *out)
3680{
3681 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3682 list_init(&out->offload_cmd_list);
3683 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3684 offload_thread_loop, out);
3685 return 0;
3686}
3687
3688static int destroy_offload_callback_thread(struct stream_out *out)
3689{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003690 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08003691 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003692 stop_compressed_output_l(out);
3693 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3694
Weiyin Jiang280ea742020-09-08 20:28:22 +08003695 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003696 pthread_mutex_unlock(&out->lock);
3697 pthread_join(out->offload_thread, (void **) NULL);
3698 pthread_cond_destroy(&out->offload_cond);
3699
3700 return 0;
3701}
3702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703static int stop_output_stream(struct stream_out *out)
3704{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303705 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 struct audio_usecase *uc_info;
3707 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003708 bool has_voip_usecase =
3709 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710
Eric Laurent994a6932013-07-17 11:51:42 -07003711 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003712 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 uc_info = get_usecase_from_list(adev, out->usecase);
3714 if (uc_info == NULL) {
3715 ALOGE("%s: Could not find the usecase (%d) in the list",
3716 __func__, out->usecase);
3717 return -EINVAL;
3718 }
3719
Zhou Songbaddf9f2020-11-20 13:57:39 +08003720 out->a2dp_muted = false;
3721
Derek Chenea197282019-01-07 17:35:01 -08003722 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3723 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003724
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003725 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303726 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003727 if (adev->visualizer_stop_output != NULL)
3728 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003729
3730 audio_extn_dts_remove_state_notifier_node(out->usecase);
3731
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003732 if (adev->offload_effects_stop_output != NULL)
3733 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003734 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3735 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3736 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003737 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003738
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003739 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3740 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003741 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003742 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003743
Eric Laurent150dbfe2013-02-27 14:31:02 -08003744 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003745 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003746
3747 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003748 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003749 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3750 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751
Aalique Grahame22e49102018-12-18 14:23:57 -08003752 audio_extn_extspk_update(adev->extspk);
3753
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003754 if (is_offload_usecase(out->usecase)) {
3755 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3756 adev->dsp_bit_width_enforce_mode,
3757 false);
3758 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003759 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003760 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3761 false);
3762
3763 if (ret != 0)
3764 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3765 /* default service interval was successfully updated,
3766 reopen USB backend with new service interval */
3767 ret = 0;
3768 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003769
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003770 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303771 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003772 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303773 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003774 ALOGV("Disable passthrough , reset mixer to pcm");
3775 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003776#ifdef AUDIO_GKI_ENABLED
3777 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3778 out->compr_config.codec->reserved[0] = 0;
3779#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003780 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003781#endif
Mingming Yin21854652016-04-13 11:54:02 -07003782 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003783 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3784 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003785
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303786 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003787 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303788 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303789
Manish Dewangan21a850a2017-08-14 12:03:55 +05303790 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003791 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3792 if (ret < 0)
3793 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3794 }
3795
juyuchen2d415992018-11-16 14:15:16 +08003796 /* 1) media + voip output routing to handset must route media back to
3797 speaker when voip stops.
3798 2) trigger voip input to reroute when voip output changes to
3799 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003800 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003801 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003802 struct listnode *node;
3803 struct audio_usecase *usecase;
3804 list_for_each(node, &adev->usecase_list) {
3805 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003806 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303807 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3808 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003809 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003810 continue;
3811
3812 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3813 __func__, usecase->id, use_case_table[usecase->id],
3814 out->usecase, use_case_table[out->usecase]);
3815 select_devices(adev, usecase->id);
3816 }
3817 }
3818
Garmond Leung5fd0b552018-04-17 11:56:12 -07003819 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003820 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 return ret;
3822}
3823
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003824struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3825 unsigned int flags, unsigned int pcm_open_retry_count,
3826 struct pcm_config *config)
3827{
3828 struct pcm* pcm = NULL;
3829
3830 while (1) {
3831 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3832 if (pcm == NULL || !pcm_is_ready(pcm)) {
3833 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3834 if (pcm != NULL) {
3835 pcm_close(pcm);
3836 pcm = NULL;
3837 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003838 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003839 return NULL;
3840
Weiyin Jiang72197252019-10-09 11:49:32 +08003841 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003842 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3843 continue;
3844 }
3845 break;
3846 }
3847
3848 if (pcm_is_ready(pcm)) {
3849 int ret = pcm_prepare(pcm);
3850 if (ret < 0) {
3851 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3852 pcm_close(pcm);
3853 pcm = NULL;
3854 }
3855 }
3856
3857 return pcm;
3858}
3859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860int start_output_stream(struct stream_out *out)
3861{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 struct audio_usecase *uc_info;
3864 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003865 char mixer_ctl_name[128];
3866 struct mixer_ctl *ctl = NULL;
3867 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303868 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003869 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870
Haynes Mathew George380745d2017-10-04 15:27:45 -07003871 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003872 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3873 ret = -EINVAL;
3874 goto error_config;
3875 }
3876
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003877 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303878 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003879 get_device_types(&out->device_list), is_haptic_usecase);
3880
3881 bool is_speaker_active = compare_device_type(&out->device_list,
3882 AUDIO_DEVICE_OUT_SPEAKER);
3883 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3884 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303885
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303886 if (CARD_STATUS_OFFLINE == out->card_status ||
3887 CARD_STATUS_OFFLINE == adev->card_status) {
3888 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303889 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003890 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303891 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303892
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003893 //Update incall music usecase to reflect correct voice session
3894 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3895 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3896 if (ret != 0) {
3897 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3898 __func__, ret);
3899 goto error_config;
3900 }
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 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003905 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303906 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303907 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003908 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303909 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3910 ret = -EAGAIN;
3911 goto error_config;
3912 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303913 }
3914 }
3915 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003916 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303917 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003918 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303919 //combo usecase just by pass a2dp
3920 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003921 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303922 } else {
3923 ALOGE("%s: SCO profile is not ready, return error", __func__);
3924 ret = -EAGAIN;
3925 goto error_config;
3926 }
3927 }
3928 }
3929
Eric Laurentb23d5282013-05-14 15:27:20 -07003930 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 if (out->pcm_device_id < 0) {
3932 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3933 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003934 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003935 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 }
3937
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003938 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003939 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3940 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003941 if (adev->haptic_pcm_device_id < 0) {
3942 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3943 __func__, adev->haptic_pcm_device_id, out->usecase);
3944 ret = -EINVAL;
3945 goto error_config;
3946 }
3947 }
3948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003950
3951 if (!uc_info) {
3952 ret = -ENOMEM;
3953 goto error_config;
3954 }
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 uc_info->id = out->usecase;
3957 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003958 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003959 list_init(&uc_info->device_list);
3960 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003961 uc_info->in_snd_device = SND_DEVICE_NONE;
3962 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003963
3964 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003965 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003966 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3967 /* USB backend is not reopened immediately.
3968 This is eventually done as part of select_devices */
3969 }
3970
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003971 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972
Wei Wangf7ca6c92017-11-21 14:51:20 -08003973 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303974 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3975 adev->perf_lock_opts,
3976 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303977
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003978 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303979 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303980 if (audio_extn_passthru_is_enabled() &&
3981 audio_extn_passthru_is_passthrough_stream(out)) {
3982 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303983 }
3984 }
3985
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003986 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003987 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303988 if (!a2dp_combo) {
3989 check_a2dp_restore_l(adev, out, false);
3990 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003991 struct listnode dev;
3992 list_init(&dev);
3993 assign_devices(&dev, &out->device_list);
3994 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3995 reassign_device_list(&out->device_list,
3996 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003997 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003998 reassign_device_list(&out->device_list,
3999 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304000 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004001 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304002 }
4003 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304004 select_devices(adev, out->usecase);
4005 if (is_a2dp_out_device_type(&out->device_list) &&
4006 !adev->a2dp_started) {
4007 if (is_speaker_active || is_speaker_safe_active) {
4008 struct listnode dev;
4009 list_init(&dev);
4010 assign_devices(&dev, &out->device_list);
4011 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4012 reassign_device_list(&out->device_list,
4013 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4014 else
4015 reassign_device_list(&out->device_list,
4016 AUDIO_DEVICE_OUT_SPEAKER, "");
4017 select_devices(adev, out->usecase);
4018 assign_devices(&out->device_list, &dev);
4019 } else {
4020 ret = -EINVAL;
4021 goto error_open;
4022 }
4023 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304024 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004025
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004026 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4027 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004028 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004029 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004030
Derek Chenea197282019-01-07 17:35:01 -08004031 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4032 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004033
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004034 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4035 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004036
4037 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004038 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004039 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4040 ALOGE("%s: pcm stream not ready", __func__);
4041 goto error_open;
4042 }
4043 ret = pcm_start(out->pcm);
4044 if (ret < 0) {
4045 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4046 goto error_open;
4047 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004048 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004049 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004050 unsigned int flags = PCM_OUT;
4051 unsigned int pcm_open_retry_count = 0;
4052 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4053 flags |= PCM_MMAP | PCM_NOIRQ;
4054 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004055 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004056 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004057 } else
4058 flags |= PCM_MONOTONIC;
4059
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004060 if ((adev->vr_audio_mode_enabled) &&
4061 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4062 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4063 "PCM_Dev %d Topology", out->pcm_device_id);
4064 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4065 if (!ctl) {
4066 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4067 __func__, mixer_ctl_name);
4068 } else {
4069 //if success use ULLPP
4070 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4071 __func__, mixer_ctl_name, out->pcm_device_id);
4072 //There is a still a possibility that some sessions
4073 // that request for FAST|RAW when 3D audio is active
4074 //can go through ULLPP. Ideally we expects apps to
4075 //listen to audio focus and stop concurrent playback
4076 //Also, we will look for mode flag (voice_in_communication)
4077 //before enabling the realtime flag.
4078 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4079 }
4080 }
4081
Surendar Karka91fa3682018-07-02 18:12:12 +05304082 if (out->realtime)
4083 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4084 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4085
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004086 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4087 flags, pcm_open_retry_count,
4088 &(out->config));
4089 if (out->pcm == NULL) {
4090 ret = -EIO;
4091 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004092 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004093
4094 if (is_haptic_usecase) {
4095 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4096 adev->haptic_pcm_device_id,
4097 flags, pcm_open_retry_count,
4098 &(adev->haptics_config));
4099 // failure to open haptics pcm shouldnt stop audio,
4100 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004101
4102 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4103 ALOGD("%s: enable haptic audio synchronization", __func__);
4104 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4105 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004106 }
4107
Surendar Karka91fa3682018-07-02 18:12:12 +05304108 if (!out->realtime)
4109 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304110 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004111
Zhou Song2b8f28f2017-09-11 10:51:38 +08004112 // apply volume for voip playback after path is set up
4113 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4114 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304115 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4116 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304117 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4118 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004119 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4120 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304121 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004122 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004123 /*
4124 * set custom channel map if:
4125 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4126 * 2. custom channel map has been set by client
4127 * else default channel map of FC/FR/FL can always be set to DSP
4128 */
4129 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4130 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4131 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004132 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4133 adev->dsp_bit_width_enforce_mode,
4134 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004136 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004137 out->compr = compress_open(adev->snd_card,
4138 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004139 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004140 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304141 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304142 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4143 adev->card_status = CARD_STATUS_OFFLINE;
4144 out->card_status = CARD_STATUS_OFFLINE;
4145 ret = -EIO;
4146 goto error_open;
4147 }
4148
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004150 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151 compress_close(out->compr);
4152 out->compr = NULL;
4153 ret = -EIO;
4154 goto error_open;
4155 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304156 /* compress_open sends params of the track, so reset the flag here */
4157 out->is_compr_metadata_avail = false;
4158
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004159 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004160 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004161
Fred Oh3f43e742015-03-04 18:42:34 -08004162 /* Since small bufs uses blocking writes, a write will be blocked
4163 for the default max poll time (20s) in the event of an SSR.
4164 Reduce the poll time to observe and deal with SSR faster.
4165 */
Ashish Jain5106d362016-05-11 19:23:33 +05304166 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004167 compress_set_max_poll_wait(out->compr, 1000);
4168 }
4169
Manish Dewangan69426c82017-01-30 17:35:36 +05304170 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304171 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304172
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004173 audio_extn_dts_create_state_notifier_node(out->usecase);
4174 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4175 popcount(out->channel_mask),
4176 out->playback_started);
4177
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004178#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304179 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004180 audio_extn_dolby_send_ddp_endp_params(adev);
4181#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304182 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4183 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004184 if (adev->visualizer_start_output != NULL)
4185 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4186 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304187 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004188 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004189 }
Derek Chenf13dd492018-11-13 14:53:51 -08004190
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004191 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004192 /* Update cached volume from media to offload/direct stream */
4193 struct listnode *node = NULL;
4194 list_for_each(node, &adev->active_outputs_list) {
4195 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4196 streams_output_ctxt_t,
4197 list);
4198 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4199 out->volume_l = out_ctxt->output->volume_l;
4200 out->volume_r = out_ctxt->output->volume_r;
4201 }
4202 }
4203 out_set_compr_volume(&out->stream,
4204 out->volume_l, out->volume_r);
4205 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004207
4208 if (ret == 0) {
4209 register_out_stream(out);
4210 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004211 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4212 ALOGE("%s: pcm stream not ready", __func__);
4213 goto error_open;
4214 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004215 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004216 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004217 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004218 if (ret < 0)
4219 goto error_open;
4220 }
4221 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004222 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304223 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304224 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004225
vivek mehtad15d2bf2019-05-17 13:35:10 -07004226 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4227 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4228 audio_low_latency_hint_start();
4229 }
4230
Manish Dewangan21a850a2017-08-14 12:03:55 +05304231 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004232 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004233 if (ret < 0)
4234 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4235 }
4236
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004237 // consider a scenario where on pause lower layers are tear down.
4238 // so on resume, swap mixer control need to be sent only when
4239 // backend is active, hence rather than sending from enable device
4240 // sending it from start of streamtream
4241
4242 platform_set_swap_channels(adev, true);
4243
Haynes Mathew George380745d2017-10-04 15:27:45 -07004244 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304245 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004246 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004247error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004248 if (adev->haptic_pcm) {
4249 pcm_close(adev->haptic_pcm);
4250 adev->haptic_pcm = NULL;
4251 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004252 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304253 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004255error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304256 /*
4257 * sleep 50ms to allow sufficient time for kernel
4258 * drivers to recover incases like SSR.
4259 */
4260 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004261error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004262 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304263 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265}
4266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267static int check_input_parameters(uint32_t sample_rate,
4268 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004269 int channel_count,
4270 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004272 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304274 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4275 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4276 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004277 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004278 !audio_extn_compr_cap_format_supported(format) &&
4279 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004280 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004281
Aalique Grahame22e49102018-12-18 14:23:57 -08004282 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4283 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4284 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4285 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4286 return -EINVAL;
4287 }
4288
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004289 switch (channel_count) {
4290 case 1:
4291 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304292 case 3:
4293 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004294 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004295 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304296 case 10:
4297 case 12:
4298 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004299 break;
4300 default:
4301 ret = -EINVAL;
4302 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303
4304 switch (sample_rate) {
4305 case 8000:
4306 case 11025:
4307 case 12000:
4308 case 16000:
4309 case 22050:
4310 case 24000:
4311 case 32000:
4312 case 44100:
4313 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004314 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304315 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004316 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304317 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 break;
4319 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004320 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 }
4322
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324}
4325
Naresh Tanniru04f71882018-06-26 17:46:22 +05304326
4327/** Add a value in a list if not already present.
4328 * @return true if value was successfully inserted or already present,
4329 * false if the list is full and does not contain the value.
4330 */
4331static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4332 for (size_t i = 0; i < list_length; i++) {
4333 if (list[i] == value) return true; // value is already present
4334 if (list[i] == 0) { // no values in this slot
4335 list[i] = value;
4336 return true; // value inserted
4337 }
4338 }
4339 return false; // could not insert value
4340}
4341
4342/** Add channel_mask in supported_channel_masks if not already present.
4343 * @return true if channel_mask was successfully inserted or already present,
4344 * false if supported_channel_masks is full and does not contain channel_mask.
4345 */
4346static void register_channel_mask(audio_channel_mask_t channel_mask,
4347 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4348 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4349 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4350}
4351
4352/** Add format in supported_formats if not already present.
4353 * @return true if format was successfully inserted or already present,
4354 * false if supported_formats is full and does not contain format.
4355 */
4356static void register_format(audio_format_t format,
4357 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4358 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4359 "%s: stream can not declare supporting its format %x", __func__, format);
4360}
4361/** Add sample_rate in supported_sample_rates if not already present.
4362 * @return true if sample_rate was successfully inserted or already present,
4363 * false if supported_sample_rates is full and does not contain sample_rate.
4364 */
4365static void register_sample_rate(uint32_t sample_rate,
4366 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4367 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4368 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4369}
4370
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004371static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4372{
4373 uint32_t high = num1, low = num2, temp = 0;
4374
4375 if (!num1 || !num2)
4376 return 0;
4377
4378 if (num1 < num2) {
4379 high = num2;
4380 low = num1;
4381 }
4382
4383 while (low != 0) {
4384 temp = low;
4385 low = high % low;
4386 high = temp;
4387 }
4388 return (num1 * num2)/high;
4389}
4390
4391static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4392{
4393 uint32_t remainder = 0;
4394
4395 if (!multiplier)
4396 return num;
4397
4398 remainder = num % multiplier;
4399 if (remainder)
4400 num += (multiplier - remainder);
4401
4402 return num;
4403}
4404
Aalique Grahame22e49102018-12-18 14:23:57 -08004405static size_t get_stream_buffer_size(size_t duration_ms,
4406 uint32_t sample_rate,
4407 audio_format_t format,
4408 int channel_count,
4409 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410{
4411 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004412 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413
Aalique Grahame22e49102018-12-18 14:23:57 -08004414 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004415 if (is_low_latency)
4416 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304417
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004418 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004419 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420
Ralf Herzbd08d632018-09-28 15:50:49 +02004421 /* make sure the size is multiple of 32 bytes and additionally multiple of
4422 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004423 * At 48 kHz mono 16-bit PCM:
4424 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4425 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004426 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004427 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004428 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004429
4430 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431}
4432
Aalique Grahame22e49102018-12-18 14:23:57 -08004433static size_t get_input_buffer_size(uint32_t sample_rate,
4434 audio_format_t format,
4435 int channel_count,
4436 bool is_low_latency)
4437{
4438 /* Don't know if USB HIFI in this context so use true to be conservative */
4439 if (check_input_parameters(sample_rate, format, channel_count,
4440 true /*is_usb_hifi */) != 0)
4441 return 0;
4442
4443 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4444 sample_rate,
4445 format,
4446 channel_count,
4447 is_low_latency);
4448}
4449
Derek Chenf6318be2017-06-12 17:16:24 -04004450size_t get_output_period_size(uint32_t sample_rate,
4451 audio_format_t format,
4452 int channel_count,
4453 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304454{
4455 size_t size = 0;
4456 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4457
4458 if ((duration == 0) || (sample_rate == 0) ||
4459 (bytes_per_sample == 0) || (channel_count == 0)) {
4460 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4461 bytes_per_sample, channel_count);
4462 return -EINVAL;
4463 }
4464
4465 size = (sample_rate *
4466 duration *
4467 bytes_per_sample *
4468 channel_count) / 1000;
4469 /*
4470 * To have same PCM samples for all channels, the buffer size requires to
4471 * be multiple of (number of channels * bytes per sample)
4472 * For writes to succeed, the buffer must be written at address which is multiple of 32
4473 */
4474 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4475
4476 return (size/(channel_count * bytes_per_sample));
4477}
4478
Zhou Song48453a02018-01-10 17:50:59 +08004479static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304480{
4481 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004482 uint64_t written_frames = 0;
4483 uint64_t kernel_frames = 0;
4484 uint64_t dsp_frames = 0;
4485 uint64_t signed_frames = 0;
4486 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304487
4488 /* This adjustment accounts for buffering after app processor.
4489 * It is based on estimated DSP latency per use case, rather than exact.
4490 */
George Gao9ba8a142020-07-23 14:30:03 -07004491 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004492 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304493
Zhou Song48453a02018-01-10 17:50:59 +08004494 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004495 written_frames = out->written /
4496 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4497
Ashish Jain5106d362016-05-11 19:23:33 +05304498 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4499 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4500 * hence only estimate.
4501 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004502 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4503 kernel_frames = kernel_buffer_size /
4504 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304505
Weiyin Jiang4813da12020-05-28 00:37:28 +08004506 if (written_frames >= (kernel_frames + dsp_frames))
4507 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304508
Zhou Song48453a02018-01-10 17:50:59 +08004509 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304510 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004511 if (timestamp != NULL )
4512 *timestamp = out->writeAt;
4513 } else if (timestamp != NULL) {
4514 clock_gettime(CLOCK_MONOTONIC, timestamp);
4515 }
4516 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304517
Weiyin Jiang4813da12020-05-28 00:37:28 +08004518 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4519 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304520
4521 return actual_frames_rendered;
4522}
4523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4525{
4526 struct stream_out *out = (struct stream_out *)stream;
4527
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004528 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529}
4530
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004531static int out_set_sample_rate(struct audio_stream *stream __unused,
4532 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533{
4534 return -ENOSYS;
4535}
4536
4537static size_t out_get_buffer_size(const struct audio_stream *stream)
4538{
4539 struct stream_out *out = (struct stream_out *)stream;
4540
Varun Balaraje49253e2017-07-06 19:48:56 +05304541 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304542 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304543 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304544 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4545 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4546 else
4547 return out->compr_config.fragment_size;
4548 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004549 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304550 else if (is_offload_usecase(out->usecase) &&
4551 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304552 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004553
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004554 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004555 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556}
4557
4558static uint32_t out_get_channels(const struct audio_stream *stream)
4559{
4560 struct stream_out *out = (struct stream_out *)stream;
4561
4562 return out->channel_mask;
4563}
4564
4565static audio_format_t out_get_format(const struct audio_stream *stream)
4566{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004567 struct stream_out *out = (struct stream_out *)stream;
4568
4569 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570}
4571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004572static int out_set_format(struct audio_stream *stream __unused,
4573 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574{
4575 return -ENOSYS;
4576}
4577
4578static int out_standby(struct audio_stream *stream)
4579{
4580 struct stream_out *out = (struct stream_out *)stream;
4581 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004582 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004583
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304584 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4585 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004587 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004589 if (adev->adm_deregister_stream)
4590 adev->adm_deregister_stream(adev->adm_data, out->handle);
4591
Weiyin Jiang280ea742020-09-08 20:28:22 +08004592 if (is_offload_usecase(out->usecase)) {
4593 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004594 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004595 pthread_mutex_unlock(&out->latch_lock);
4596 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004597
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004598 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004600 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4601 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304602 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004603 pthread_mutex_unlock(&adev->lock);
4604 pthread_mutex_unlock(&out->lock);
4605 ALOGD("VOIP output entered standby");
4606 return 0;
4607 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004608 if (out->pcm) {
4609 pcm_close(out->pcm);
4610 out->pcm = NULL;
4611 }
Meng Wanga09da002020-04-20 12:56:04 +08004612 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4613 if (adev->haptic_pcm) {
4614 pcm_close(adev->haptic_pcm);
4615 adev->haptic_pcm = NULL;
4616 }
4617
4618 if (adev->haptic_buffer != NULL) {
4619 free(adev->haptic_buffer);
4620 adev->haptic_buffer = NULL;
4621 adev->haptic_buffer_size = 0;
4622 }
4623 adev->haptic_pcm_device_id = 0;
4624 }
4625
Haynes Mathew George16081042017-05-31 17:16:49 -07004626 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4627 do_stop = out->playback_started;
4628 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004629
4630 if (out->mmap_shared_memory_fd >= 0) {
4631 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4632 __func__, out->mmap_shared_memory_fd);
4633 close(out->mmap_shared_memory_fd);
4634 out->mmap_shared_memory_fd = -1;
4635 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004636 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004637 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004638 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304639 out->send_next_track_params = false;
4640 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004641 out->gapless_mdata.encoder_delay = 0;
4642 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004643 if (out->compr != NULL) {
4644 compress_close(out->compr);
4645 out->compr = NULL;
4646 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004647 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004648 if (do_stop) {
4649 stop_output_stream(out);
4650 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304651 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004652 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004653 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 }
4655 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004656 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 return 0;
4658}
4659
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304660static int out_on_error(struct audio_stream *stream)
4661{
4662 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004663 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304664
4665 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004666 // always send CMD_ERROR for offload streams, this
4667 // is needed e.g. when SSR happens within compress_open
4668 // since the stream is active, offload_callback_thread is also active.
4669 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08004670 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004671 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004672 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004673 }
4674 pthread_mutex_unlock(&out->lock);
4675
4676 status = out_standby(&out->stream.common);
4677
4678 lock_output_stream(out);
4679 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004680 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304681 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304682
4683 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4684 ALOGD("Setting previous card status if offline");
4685 out->prev_card_status_offline = true;
4686 }
4687
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304688 pthread_mutex_unlock(&out->lock);
4689
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004690 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304691}
4692
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304693/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004694 * standby implementation without locks, assumes that the callee already
4695 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304696 */
4697int out_standby_l(struct audio_stream *stream)
4698{
4699 struct stream_out *out = (struct stream_out *)stream;
4700 struct audio_device *adev = out->dev;
4701
4702 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4703 stream, out->usecase, use_case_table[out->usecase]);
4704
4705 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004706 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304707 if (adev->adm_deregister_stream)
4708 adev->adm_deregister_stream(adev->adm_data, out->handle);
4709
Weiyin Jiang280ea742020-09-08 20:28:22 +08004710 if (is_offload_usecase(out->usecase)) {
4711 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304712 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004713 pthread_mutex_unlock(&out->latch_lock);
4714 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304715
4716 out->standby = true;
4717 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4718 voice_extn_compress_voip_close_output_stream(stream);
4719 out->started = 0;
4720 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004721 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304722 return 0;
4723 } else if (!is_offload_usecase(out->usecase)) {
4724 if (out->pcm) {
4725 pcm_close(out->pcm);
4726 out->pcm = NULL;
4727 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004728 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4729 if (adev->haptic_pcm) {
4730 pcm_close(adev->haptic_pcm);
4731 adev->haptic_pcm = NULL;
4732 }
4733
4734 if (adev->haptic_buffer != NULL) {
4735 free(adev->haptic_buffer);
4736 adev->haptic_buffer = NULL;
4737 adev->haptic_buffer_size = 0;
4738 }
4739 adev->haptic_pcm_device_id = 0;
4740 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304741 } else {
4742 ALOGD("copl(%p):standby", out);
4743 out->send_next_track_params = false;
4744 out->is_compr_metadata_avail = false;
4745 out->gapless_mdata.encoder_delay = 0;
4746 out->gapless_mdata.encoder_padding = 0;
4747 if (out->compr != NULL) {
4748 compress_close(out->compr);
4749 out->compr = NULL;
4750 }
4751 }
4752 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004753 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304754 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004755 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304756 return 0;
4757}
4758
Aalique Grahame22e49102018-12-18 14:23:57 -08004759static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760{
Aalique Grahame22e49102018-12-18 14:23:57 -08004761 struct stream_out *out = (struct stream_out *)stream;
4762
4763 // We try to get the lock for consistency,
4764 // but it isn't necessary for these variables.
4765 // If we're not in standby, we may be blocked on a write.
4766 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4767 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4768 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4769
Andy Hunga1f48fa2019-07-01 18:14:53 -07004770 char buffer[256]; // for statistics formatting
4771 if (!is_offload_usecase(out->usecase)) {
4772 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4773 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4774 }
4775
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004776 if (out->start_latency_ms.n > 0) {
4777 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4778 dprintf(fd, " Start latency ms: %s\n", buffer);
4779 }
4780
Aalique Grahame22e49102018-12-18 14:23:57 -08004781 if (locked) {
4782 pthread_mutex_unlock(&out->lock);
4783 }
4784
4785 // dump error info
4786 (void)error_log_dump(
4787 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789 return 0;
4790}
4791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004792static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4793{
4794 int ret = 0;
4795 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004796
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004797 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004798 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004799 return -EINVAL;
4800 }
4801
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304802 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004803
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004804 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4805 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304806 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004807 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4809 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304810 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004811 }
4812
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004813 ALOGV("%s new encoder delay %u and padding %u", __func__,
4814 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4815
4816 return 0;
4817}
4818
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004819static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4820{
4821 return out == adev->primary_output || out == adev->voice_tx_output;
4822}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004823
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304824// note: this call is safe only if the stream_cb is
4825// removed first in close_output_stream (as is done now).
4826static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4827{
4828 if (!stream || !parms)
4829 return;
4830
4831 struct stream_out *out = (struct stream_out *)stream;
4832 struct audio_device *adev = out->dev;
4833
4834 card_status_t status;
4835 int card;
4836 if (parse_snd_card_status(parms, &card, &status) < 0)
4837 return;
4838
4839 pthread_mutex_lock(&adev->lock);
4840 bool valid_cb = (card == adev->snd_card);
4841 pthread_mutex_unlock(&adev->lock);
4842
4843 if (!valid_cb)
4844 return;
4845
4846 lock_output_stream(out);
4847 if (out->card_status != status)
4848 out->card_status = status;
4849 pthread_mutex_unlock(&out->lock);
4850
4851 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4852 use_case_table[out->usecase],
4853 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4854
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304855 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304856 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304857 if (voice_is_call_state_active(adev) &&
4858 out == adev->primary_output) {
4859 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4860 pthread_mutex_lock(&adev->lock);
4861 voice_stop_call(adev);
4862 adev->mode = AUDIO_MODE_NORMAL;
4863 pthread_mutex_unlock(&adev->lock);
4864 }
4865 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304866 return;
4867}
4868
Kevin Rocardfce19002017-08-07 19:21:36 -07004869static int get_alive_usb_card(struct str_parms* parms) {
4870 int card;
4871 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4872 !audio_extn_usb_alive(card)) {
4873 return card;
4874 }
4875 return -ENODEV;
4876}
4877
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004879 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880{
4881 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004882 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004883 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004884 bool bypass_a2dp = false;
4885 bool reconfig = false;
4886 unsigned long service_interval = 0;
4887
4888 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004889 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4890
4891 list_init(&new_devices);
4892 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004893
4894 lock_output_stream(out);
4895 pthread_mutex_lock(&adev->lock);
4896
4897 /*
4898 * When HDMI cable is unplugged the music playback is paused and
4899 * the policy manager sends routing=0. But the audioflinger continues
4900 * to write data until standby time (3sec). As the HDMI core is
4901 * turned off, the write gets blocked.
4902 * Avoid this by routing audio to speaker until standby.
4903 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004904 if (is_single_device_type_equal(&out->device_list,
4905 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004906 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004907 !audio_extn_passthru_is_passthrough_stream(out) &&
4908 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004909 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004910 }
4911 /*
4912 * When A2DP is disconnected the
4913 * music playback is paused and the policy manager sends routing=0
4914 * But the audioflinger continues to write data until standby time
4915 * (3sec). As BT is turned off, the write gets blocked.
4916 * Avoid this by routing audio to speaker until standby.
4917 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004918 if (is_a2dp_out_device_type(&out->device_list) &&
4919 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004920 !audio_extn_a2dp_source_is_ready() &&
4921 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004922 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004923 }
4924 /*
4925 * When USB headset is disconnected the music platback paused
4926 * and the policy manager send routing=0. But if the USB is connected
4927 * back before the standby time, AFE is not closed and opened
4928 * when USB is connected back. So routing to speker will guarantee
4929 * AFE reconfiguration and AFE will be opend once USB is connected again
4930 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004931 if (is_usb_out_device_type(&out->device_list) &&
4932 list_empty(&new_devices) &&
4933 !audio_extn_usb_connected(NULL)) {
4934 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4935 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004936 /* To avoid a2dp to sco overlapping / BT device improper state
4937 * check with BT lib about a2dp streaming support before routing
4938 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004939 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004940 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004941 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4942 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004943 //combo usecase just by pass a2dp
4944 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4945 bypass_a2dp = true;
4946 } else {
4947 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4948 /* update device to a2dp and don't route as BT returned error
4949 * However it is still possible a2dp routing called because
4950 * of current active device disconnection (like wired headset)
4951 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004952 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004953 pthread_mutex_unlock(&adev->lock);
4954 pthread_mutex_unlock(&out->lock);
4955 goto error;
4956 }
4957 }
4958 }
4959
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004960 // Workaround: If routing to an non existing usb device, fail gracefully
4961 // The routing request will otherwise block during 10 second
4962 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004963 if (is_usb_out_device_type(&new_devices)) {
4964 struct str_parms *parms =
4965 str_parms_create_str(get_usb_device_address(&new_devices));
4966 if (!parms)
4967 goto error;
4968 if ((card = get_alive_usb_card(parms)) >= 0) {
4969 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4970 pthread_mutex_unlock(&adev->lock);
4971 pthread_mutex_unlock(&out->lock);
4972 str_parms_destroy(parms);
4973 ret = -ENOSYS;
4974 goto error;
4975 }
4976 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004977 }
4978
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004979 // Workaround: If routing to an non existing hdmi device, fail gracefully
4980 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4981 (platform_get_edid_info_v2(adev->platform,
4982 out->extconn.cs.controller,
4983 out->extconn.cs.stream) != 0)) {
4984 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4985 pthread_mutex_unlock(&adev->lock);
4986 pthread_mutex_unlock(&out->lock);
4987 ret = -ENOSYS;
4988 goto error;
4989 }
4990
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004991 /*
4992 * select_devices() call below switches all the usecases on the same
4993 * backend to the new device. Refer to check_usecases_codec_backend() in
4994 * the select_devices(). But how do we undo this?
4995 *
4996 * For example, music playback is active on headset (deep-buffer usecase)
4997 * and if we go to ringtones and select a ringtone, low-latency usecase
4998 * will be started on headset+speaker. As we can't enable headset+speaker
4999 * and headset devices at the same time, select_devices() switches the music
5000 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5001 * So when the ringtone playback is completed, how do we undo the same?
5002 *
5003 * We are relying on the out_set_parameters() call on deep-buffer output,
5004 * once the ringtone playback is ended.
5005 * NOTE: We should not check if the current devices are same as new devices.
5006 * Because select_devices() must be called to switch back the music
5007 * playback to headset.
5008 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005009 if (!list_empty(&new_devices)) {
5010 bool same_dev = compare_devices(&out->device_list, &new_devices);
5011 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005012
5013 if (output_drives_call(adev, out)) {
5014 if (!voice_is_call_state_active(adev)) {
5015 if (adev->mode == AUDIO_MODE_IN_CALL) {
5016 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 ret = voice_start_call(adev);
5018 }
5019 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005020 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005021 adev->current_call_output = out;
5022 voice_update_devices_for_all_voice_usecases(adev);
5023 }
5024 }
5025
Mingshu Pang971ff702020-09-09 15:28:22 +08005026 if (is_usb_out_device_type(&out->device_list)) {
5027 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5028 audio_extn_usb_set_service_interval(true /*playback*/,
5029 service_interval,
5030 &reconfig);
5031 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5032 }
5033
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005034 if (!out->standby) {
5035 if (!same_dev) {
5036 ALOGV("update routing change");
5037 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5038 adev->perf_lock_opts,
5039 adev->perf_lock_opts_size);
5040 if (adev->adm_on_routing_change)
5041 adev->adm_on_routing_change(adev->adm_data,
5042 out->handle);
5043 }
5044 if (!bypass_a2dp) {
5045 select_devices(adev, out->usecase);
5046 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005047 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5048 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005050 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005051 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005052 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005053 }
5054
5055 if (!same_dev) {
5056 // on device switch force swap, lower functions will make sure
5057 // to check if swap is allowed or not.
5058 platform_set_swap_channels(adev, true);
5059 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5060 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005061 pthread_mutex_lock(&out->latch_lock);
5062 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5063 if (out->a2dp_muted) {
5064 out->a2dp_muted = false;
5065 if (is_offload_usecase(out->usecase))
5066 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5067 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5068 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005069 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005070 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005071 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5072 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5073 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005074 }
5075 }
5076
5077 pthread_mutex_unlock(&adev->lock);
5078 pthread_mutex_unlock(&out->lock);
5079
5080 /*handles device and call state changes*/
5081 audio_extn_extspk_update(adev->extspk);
5082
5083error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005084 ALOGV("%s: exit: code(%d)", __func__, ret);
5085 return ret;
5086}
5087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5089{
5090 struct stream_out *out = (struct stream_out *)stream;
5091 struct audio_device *adev = out->dev;
5092 struct str_parms *parms;
5093 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005094 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005095 int ext_controller = -1;
5096 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005097
sangwoobc677242013-08-08 16:53:43 +09005098 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005099 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305101 if (!parms)
5102 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005103
5104 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5105 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005106 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005107 out->extconn.cs.controller = ext_controller;
5108 out->extconn.cs.stream = ext_stream;
5109 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5110 use_case_table[out->usecase], out->extconn.cs.controller,
5111 out->extconn.cs.stream);
5112 }
5113
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005114 if (out == adev->primary_output) {
5115 pthread_mutex_lock(&adev->lock);
5116 audio_extn_set_parameters(adev, parms);
5117 pthread_mutex_unlock(&adev->lock);
5118 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005119 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005120 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005121 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005122
5123 audio_extn_dts_create_state_notifier_node(out->usecase);
5124 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5125 popcount(out->channel_mask),
5126 out->playback_started);
5127
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005128 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005129 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005130
Surendar Karkaf51b5842018-04-26 11:28:38 +05305131 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5132 sizeof(value));
5133 if (err >= 0) {
5134 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5135 audio_extn_send_dual_mono_mixing_coefficients(out);
5136 }
5137
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305138 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5139 if (err >= 0) {
5140 strlcpy(out->profile, value, sizeof(out->profile));
5141 ALOGV("updating stream profile with value '%s'", out->profile);
5142 lock_output_stream(out);
5143 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5144 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005145 &out->device_list, out->flags,
5146 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305147 out->sample_rate, out->bit_width,
5148 out->channel_mask, out->profile,
5149 &out->app_type_cfg);
5150 pthread_mutex_unlock(&out->lock);
5151 }
5152
Alexy Joseph98988832017-01-13 14:56:59 -08005153 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005154 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5155 // and vendor.audio.hal.output.suspend.supported is set to true
5156 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005157 //check suspend parameter only for low latency and if the property
5158 //is enabled
5159 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5160 ALOGI("%s: got suspend_playback %s", __func__, value);
5161 lock_output_stream(out);
5162 if (!strncmp(value, "false", 5)) {
5163 //suspend_playback=false is supposed to set QOS value back to 75%
5164 //the mixer control sent with value Enable will achieve that
5165 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5166 } else if (!strncmp (value, "true", 4)) {
5167 //suspend_playback=true is supposed to remove QOS value
5168 //resetting the mixer control will set the default value
5169 //for the mixer control which is Disable and this removes the QOS vote
5170 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5171 } else {
5172 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5173 " got %s", __func__, value);
5174 ret = -1;
5175 }
5176
5177 if (ret != 0) {
5178 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5179 __func__, out->pm_qos_mixer_path, ret);
5180 }
5181
5182 pthread_mutex_unlock(&out->lock);
5183 }
5184 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005185
Alexy Joseph98988832017-01-13 14:56:59 -08005186 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305188error:
Eric Laurent994a6932013-07-17 11:51:42 -07005189 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190 return ret;
5191}
5192
Paul McLeana50b7332018-12-17 08:24:21 -07005193static int in_set_microphone_direction(const struct audio_stream_in *stream,
5194 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005195 struct stream_in *in = (struct stream_in *)stream;
5196
5197 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5198
5199 in->direction = dir;
5200
5201 if (in->standby)
5202 return 0;
5203
5204 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005205}
5206
5207static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005208 struct stream_in *in = (struct stream_in *)stream;
5209
5210 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5211
5212 if (zoom > 1.0 || zoom < -1.0)
5213 return -EINVAL;
5214
5215 in->zoom = zoom;
5216
5217 if (in->standby)
5218 return 0;
5219
5220 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005221}
5222
5223
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005224static bool stream_get_parameter_channels(struct str_parms *query,
5225 struct str_parms *reply,
5226 audio_channel_mask_t *supported_channel_masks) {
5227 int ret = -1;
5228 char value[512];
5229 bool first = true;
5230 size_t i, j;
5231
5232 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5233 ret = 0;
5234 value[0] = '\0';
5235 i = 0;
5236 while (supported_channel_masks[i] != 0) {
5237 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5238 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5239 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305240 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005241
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305242 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005243 first = false;
5244 break;
5245 }
5246 }
5247 i++;
5248 }
5249 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5250 }
5251 return ret == 0;
5252}
5253
5254static bool stream_get_parameter_formats(struct str_parms *query,
5255 struct str_parms *reply,
5256 audio_format_t *supported_formats) {
5257 int ret = -1;
5258 char value[256];
5259 size_t i, j;
5260 bool first = true;
5261
5262 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5263 ret = 0;
5264 value[0] = '\0';
5265 i = 0;
5266 while (supported_formats[i] != 0) {
5267 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5268 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5269 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305270 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005271 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305272 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005273 first = false;
5274 break;
5275 }
5276 }
5277 i++;
5278 }
5279 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5280 }
5281 return ret == 0;
5282}
5283
5284static bool stream_get_parameter_rates(struct str_parms *query,
5285 struct str_parms *reply,
5286 uint32_t *supported_sample_rates) {
5287
5288 int i;
5289 char value[256];
5290 int ret = -1;
5291 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5292 ret = 0;
5293 value[0] = '\0';
5294 i=0;
5295 int cursor = 0;
5296 while (supported_sample_rates[i]) {
5297 int avail = sizeof(value) - cursor;
5298 ret = snprintf(value + cursor, avail, "%s%d",
5299 cursor > 0 ? "|" : "",
5300 supported_sample_rates[i]);
5301 if (ret < 0 || ret >= avail) {
5302 // if cursor is at the last element of the array
5303 // overwrite with \0 is duplicate work as
5304 // snprintf already put a \0 in place.
5305 // else
5306 // we had space to write the '|' at value[cursor]
5307 // (which will be overwritten) or no space to fill
5308 // the first element (=> cursor == 0)
5309 value[cursor] = '\0';
5310 break;
5311 }
5312 cursor += ret;
5313 ++i;
5314 }
5315 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5316 value);
5317 }
5318 return ret >= 0;
5319}
5320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005321static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5322{
5323 struct stream_out *out = (struct stream_out *)stream;
5324 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005325 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005326 char value[256];
5327 struct str_parms *reply = str_parms_create();
5328 size_t i, j;
5329 int ret;
5330 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005331
5332 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005333 if (reply) {
5334 str_parms_destroy(reply);
5335 }
5336 if (query) {
5337 str_parms_destroy(query);
5338 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005339 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5340 return NULL;
5341 }
5342
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005343 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005344 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5345 if (ret >= 0) {
5346 value[0] = '\0';
5347 i = 0;
5348 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005349 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5350 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005352 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005354 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005355 first = false;
5356 break;
5357 }
5358 }
5359 i++;
5360 }
5361 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5362 str = str_parms_to_str(reply);
5363 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005364 voice_extn_out_get_parameters(out, query, reply);
5365 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005366 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005367
Alexy Joseph62142aa2015-11-16 15:10:34 -08005368
5369 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5370 if (ret >= 0) {
5371 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305372 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5373 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005374 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305375 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005376 } else {
5377 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305378 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005379 }
5380 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005381 if (str)
5382 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005383 str = str_parms_to_str(reply);
5384 }
5385
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005386 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5387 if (ret >= 0) {
5388 value[0] = '\0';
5389 i = 0;
5390 first = true;
5391 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005392 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5393 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005394 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005395 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005396 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005397 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005398 first = false;
5399 break;
5400 }
5401 }
5402 i++;
5403 }
5404 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005405 if (str)
5406 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005407 str = str_parms_to_str(reply);
5408 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005409
5410 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5411 if (ret >= 0) {
5412 value[0] = '\0';
5413 i = 0;
5414 first = true;
5415 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005416 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5417 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005418 if (!first) {
5419 strlcat(value, "|", sizeof(value));
5420 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005421 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005422 first = false;
5423 break;
5424 }
5425 }
5426 i++;
5427 }
5428 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5429 if (str)
5430 free(str);
5431 str = str_parms_to_str(reply);
5432 }
5433
Alexy Joseph98988832017-01-13 14:56:59 -08005434 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5435 //only low latency track supports suspend_resume
5436 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005437 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005438 if (str)
5439 free(str);
5440 str = str_parms_to_str(reply);
5441 }
5442
5443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444 str_parms_destroy(query);
5445 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005446 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005447 return str;
5448}
5449
5450static uint32_t out_get_latency(const struct audio_stream_out *stream)
5451{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005452 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005454 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455
Alexy Josephaa54c872014-12-03 02:46:47 -08005456 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305457 lock_output_stream(out);
5458 latency = audio_extn_utils_compress_get_dsp_latency(out);
5459 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005460 } else if ((out->realtime) ||
5461 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005462 // since the buffer won't be filled up faster than realtime,
5463 // return a smaller number
5464 if (out->config.rate)
5465 period_ms = (out->af_period_multiplier * out->config.period_size *
5466 1000) / (out->config.rate);
5467 else
5468 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005469 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005470 } else {
5471 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005472 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005473 }
5474
Zhou Songd2537a02020-06-11 22:04:46 +08005475 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005476 latency += audio_extn_a2dp_get_encoder_latency();
5477
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305478 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005479 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005480}
5481
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305482static float AmpToDb(float amplification)
5483{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305484 float db = DSD_VOLUME_MIN_DB;
5485 if (amplification > 0) {
5486 db = 20 * log10(amplification);
5487 if(db < DSD_VOLUME_MIN_DB)
5488 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305489 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305490 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305491}
5492
Arun Mirpuri5d170872019-03-26 13:21:31 -07005493static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5494 float right)
5495{
5496 struct stream_out *out = (struct stream_out *)stream;
5497 long volume = 0;
5498 char mixer_ctl_name[128] = "";
5499 struct audio_device *adev = out->dev;
5500 struct mixer_ctl *ctl = NULL;
5501 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5502 PCM_PLAYBACK);
5503
5504 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5505 "Playback %d Volume", pcm_device_id);
5506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5507 if (!ctl) {
5508 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5509 __func__, mixer_ctl_name);
5510 return -EINVAL;
5511 }
5512 if (left != right)
5513 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5514 __func__, left, right);
5515 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5516 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5517 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5518 __func__, mixer_ctl_name, volume);
5519 return -EINVAL;
5520 }
5521 return 0;
5522}
5523
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305524static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5525 float right)
5526{
5527 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305528 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305529 char mixer_ctl_name[128];
5530 struct audio_device *adev = out->dev;
5531 struct mixer_ctl *ctl;
5532 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5533 PCM_PLAYBACK);
5534
5535 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5536 "Compress Playback %d Volume", pcm_device_id);
5537 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5538 if (!ctl) {
5539 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5540 __func__, mixer_ctl_name);
5541 return -EINVAL;
5542 }
5543 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5544 __func__, mixer_ctl_name, left, right);
5545 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5546 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5547 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5548
5549 return 0;
5550}
5551
Zhou Song2b8f28f2017-09-11 10:51:38 +08005552static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5553 float right)
5554{
5555 struct stream_out *out = (struct stream_out *)stream;
5556 char mixer_ctl_name[] = "App Type Gain";
5557 struct audio_device *adev = out->dev;
5558 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305559 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005560
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005561 if (!is_valid_volume(left, right)) {
5562 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5563 __func__, left, right);
5564 return -EINVAL;
5565 }
5566
Zhou Song2b8f28f2017-09-11 10:51:38 +08005567 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5568 if (!ctl) {
5569 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5570 __func__, mixer_ctl_name);
5571 return -EINVAL;
5572 }
5573
5574 set_values[0] = 0; //0: Rx Session 1:Tx Session
5575 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305576 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5577 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005578
5579 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5580 return 0;
5581}
5582
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305583static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5584 float right)
5585{
5586 struct stream_out *out = (struct stream_out *)stream;
5587 /* Volume control for pcm playback */
5588 if (left != right) {
5589 return -EINVAL;
5590 } else {
5591 char mixer_ctl_name[128];
5592 struct audio_device *adev = out->dev;
5593 struct mixer_ctl *ctl;
5594 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5595 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5596 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5597 if (!ctl) {
5598 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5599 return -EINVAL;
5600 }
5601
5602 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5603 int ret = mixer_ctl_set_value(ctl, 0, volume);
5604 if (ret < 0) {
5605 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5606 return -EINVAL;
5607 }
5608
5609 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5610
5611 return 0;
5612 }
5613}
5614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005615static int out_set_volume(struct audio_stream_out *stream, float left,
5616 float right)
5617{
Eric Laurenta9024de2013-04-04 09:19:12 -07005618 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005619 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305620 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005621
Arun Mirpuri5d170872019-03-26 13:21:31 -07005622 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005623 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5624 /* only take left channel into account: the API is for stereo anyway */
5625 out->muted = (left == 0.0f);
5626 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005627 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305628 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005629 /*
5630 * Set mute or umute on HDMI passthrough stream.
5631 * Only take left channel into account.
5632 * Mute is 0 and unmute 1
5633 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305634 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305635 } else if (out->format == AUDIO_FORMAT_DSD){
5636 char mixer_ctl_name[128] = "DSD Volume";
5637 struct audio_device *adev = out->dev;
5638 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5639
5640 if (!ctl) {
5641 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5642 __func__, mixer_ctl_name);
5643 return -EINVAL;
5644 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305645 volume[0] = (long)(AmpToDb(left));
5646 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305647 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5648 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005649 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005650 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005651 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5652 struct listnode *node = NULL;
5653 list_for_each(node, &adev->active_outputs_list) {
5654 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5655 streams_output_ctxt_t,
5656 list);
5657 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5658 out->volume_l = out_ctxt->output->volume_l;
5659 out->volume_r = out_ctxt->output->volume_r;
5660 }
5661 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005662 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005663 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005664 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5665 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005666 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005667 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005668 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005669 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005670 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5671 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305672 ret = out_set_compr_volume(stream, left, right);
5673 out->volume_l = left;
5674 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005675 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305676 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005677 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005678 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005679 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5680 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005681 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005682 if (!out->standby) {
5683 audio_extn_utils_send_app_type_gain(out->dev,
5684 out->app_type_cfg.app_type,
5685 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005686 if (!out->a2dp_muted)
5687 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005688 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005689 out->volume_l = left;
5690 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005691 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005692 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005693 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5694 ALOGV("%s: MMAP set volume called", __func__);
5695 if (!out->standby)
5696 ret = out_set_mmap_volume(stream, left, right);
5697 out->volume_l = left;
5698 out->volume_r = right;
5699 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305700 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305701 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5702 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005703 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305704 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005705 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305706 ret = out_set_pcm_volume(stream, left, right);
5707 else
5708 out->apply_volume = true;
5709
5710 out->volume_l = left;
5711 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005712 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305713 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005714 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5715 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005716 pthread_mutex_lock(&out->latch_lock);
5717 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005718 ret = out_set_pcm_volume(stream, left, right);
5719 out->volume_l = left;
5720 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005721 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005722 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005723 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725 return -ENOSYS;
5726}
5727
Zhou Songc9672822017-08-16 16:01:39 +08005728static void update_frames_written(struct stream_out *out, size_t bytes)
5729{
5730 size_t bpf = 0;
5731
5732 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5733 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5734 bpf = 1;
5735 else if (!is_offload_usecase(out->usecase))
5736 bpf = audio_bytes_per_sample(out->format) *
5737 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005738
5739 pthread_mutex_lock(&out->position_query_lock);
5740 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005741 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005742 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5743 }
5744 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005745}
5746
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005747int split_and_write_audio_haptic_data(struct stream_out *out,
5748 const void *buffer, size_t bytes_to_write)
5749{
5750 struct audio_device *adev = out->dev;
5751
5752 int ret = 0;
5753 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5754 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5755 size_t frame_size = channel_count * bytes_per_sample;
5756 size_t frame_count = bytes_to_write / frame_size;
5757
5758 bool force_haptic_path =
5759 property_get_bool("vendor.audio.test_haptic", false);
5760
5761 // extract Haptics data from Audio buffer
5762 bool alloc_haptic_buffer = false;
5763 int haptic_channel_count = adev->haptics_config.channels;
5764 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5765 size_t audio_frame_size = frame_size - haptic_frame_size;
5766 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5767
5768 if (adev->haptic_buffer == NULL) {
5769 alloc_haptic_buffer = true;
5770 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5771 free(adev->haptic_buffer);
5772 adev->haptic_buffer_size = 0;
5773 alloc_haptic_buffer = true;
5774 }
5775
5776 if (alloc_haptic_buffer) {
5777 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005778 if(adev->haptic_buffer == NULL) {
5779 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5780 return -ENOMEM;
5781 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005782 adev->haptic_buffer_size = total_haptic_buffer_size;
5783 }
5784
5785 size_t src_index = 0, aud_index = 0, hap_index = 0;
5786 uint8_t *audio_buffer = (uint8_t *)buffer;
5787 uint8_t *haptic_buffer = adev->haptic_buffer;
5788
5789 // This is required for testing only. This works for stereo data only.
5790 // One channel is fed to audio stream and other to haptic stream for testing.
5791 if (force_haptic_path)
5792 audio_frame_size = haptic_frame_size = bytes_per_sample;
5793
5794 for (size_t i = 0; i < frame_count; i++) {
5795 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5796 audio_frame_size);
5797 aud_index += audio_frame_size;
5798 src_index += audio_frame_size;
5799
5800 if (adev->haptic_pcm)
5801 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5802 haptic_frame_size);
5803 hap_index += haptic_frame_size;
5804 src_index += haptic_frame_size;
5805
5806 // This is required for testing only.
5807 // Discard haptic channel data.
5808 if (force_haptic_path)
5809 src_index += haptic_frame_size;
5810 }
5811
5812 // write to audio pipeline
5813 ret = pcm_write(out->pcm, (void *)audio_buffer,
5814 frame_count * audio_frame_size);
5815
5816 // write to haptics pipeline
5817 if (adev->haptic_pcm)
5818 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5819 frame_count * haptic_frame_size);
5820
5821 return ret;
5822}
5823
Aalique Grahame22e49102018-12-18 14:23:57 -08005824#ifdef NO_AUDIO_OUT
5825static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5826 const void *buffer __unused, size_t bytes)
5827{
5828 struct stream_out *out = (struct stream_out *)stream;
5829
5830 /* No Output device supported other than BT for playback.
5831 * Sleep for the amount of buffer duration
5832 */
5833 lock_output_stream(out);
5834 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5835 (const struct audio_stream_out *)&out->stream) /
5836 out_get_sample_rate(&out->stream.common));
5837 pthread_mutex_unlock(&out->lock);
5838 return bytes;
5839}
5840#endif
5841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005842static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5843 size_t bytes)
5844{
5845 struct stream_out *out = (struct stream_out *)stream;
5846 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005847 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305848 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005849 const size_t frame_size = audio_stream_out_frame_size(stream);
5850 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305851 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005852 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005853
Haynes Mathew George380745d2017-10-04 15:27:45 -07005854 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005855 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305856
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305857 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005858
Dhananjay Kumarac341582017-02-23 23:42:25 +05305859 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305860 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305861 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5862 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005863 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305864 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305865 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305866 ALOGD(" %s: sound card is not active/SSR state", __func__);
5867 ret= -EIO;
5868 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305869 }
5870 }
5871
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305872 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305873 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305874 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305875 goto exit;
5876 }
5877
Haynes Mathew George16081042017-05-31 17:16:49 -07005878 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5879 ret = -EINVAL;
5880 goto exit;
5881 }
5882
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005883 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305884 !out->is_iec61937_info_available) {
5885
5886 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5887 out->is_iec61937_info_available = true;
5888 } else if (audio_extn_passthru_is_enabled()) {
5889 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305890 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305891
5892 if((out->format == AUDIO_FORMAT_DTS) ||
5893 (out->format == AUDIO_FORMAT_DTS_HD)) {
5894 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5895 buffer, bytes);
5896 if (ret) {
5897 if (ret != -ENOSYS) {
5898 out->is_iec61937_info_available = false;
5899 ALOGD("iec61937 transmission info not yet updated retry");
5900 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305901 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305902 /* if stream has started and after that there is
5903 * stream config change (iec transmission config)
5904 * then trigger select_device to update backend configuration.
5905 */
5906 out->stream_config_changed = true;
5907 pthread_mutex_lock(&adev->lock);
5908 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305909 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005910 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305911 ret = -EINVAL;
5912 goto exit;
5913 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305914 pthread_mutex_unlock(&adev->lock);
5915 out->stream_config_changed = false;
5916 out->is_iec61937_info_available = true;
5917 }
5918 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305919
Meng Wang4c32fb42020-01-16 17:57:11 +08005920#ifdef AUDIO_GKI_ENABLED
5921 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5922 compr_passthr = out->compr_config.codec->reserved[0];
5923#else
5924 compr_passthr = out->compr_config.codec->compr_passthr;
5925#endif
5926
Garmond Leung317cbf12017-09-13 16:20:50 -07005927 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005928 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305929 (out->is_iec61937_info_available == true)) {
5930 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5931 ret = -EINVAL;
5932 goto exit;
5933 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305934 }
5935 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305936
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005937 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005938 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005939 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5940 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005941 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305942 ret = -EIO;
5943 goto exit;
5944 }
5945 }
5946 }
5947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005948 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005949 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005950 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5951
Eric Laurent150dbfe2013-02-27 14:31:02 -08005952 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005953 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5954 ret = voice_extn_compress_voip_start_output_stream(out);
5955 else
5956 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005957 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005958 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005959 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005960 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005961 goto exit;
5962 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305963 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005964 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005965
5966 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005967 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005968 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305969 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005970 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005971 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305972
5973 if ((out->is_iec61937_info_available == true) &&
5974 (audio_extn_passthru_is_passthrough_stream(out))&&
5975 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5976 ret = -EINVAL;
5977 goto exit;
5978 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305979 if (out->set_dual_mono)
5980 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005981
5982 // log startup time in ms.
5983 simple_stats_log(
5984 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005986
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005987 if (adev->is_channel_status_set == false &&
5988 compare_device_type(&out->device_list,
5989 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005990 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305991 adev->is_channel_status_set = true;
5992 }
5993
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305994 if ((adev->use_old_pspd_mix_ctrl == true) &&
5995 (out->pspd_coeff_sent == false)) {
5996 /*
5997 * Need to resend pspd coefficients after stream started for
5998 * older kernel version as it does not save the coefficients
5999 * and also stream has to be started for coeff to apply.
6000 */
6001 usecase = get_usecase_from_list(adev, out->usecase);
6002 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306003 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306004 out->pspd_coeff_sent = true;
6005 }
6006 }
6007
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006008 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006009 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006010 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006011 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006012 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6013 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306014 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6015 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006016 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306017 out->send_next_track_params = false;
6018 out->is_compr_metadata_avail = false;
6019 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006020 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306021 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306022 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006023
Ashish Jain83a6cc22016-06-28 14:34:17 +05306024 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306025 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306026 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306027 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006028 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306029 return -EINVAL;
6030 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306031 audio_format_t dst_format = out->hal_op_format;
6032 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306033
Dieter Luecking5d57def2018-09-07 14:23:37 +02006034 /* prevent division-by-zero */
6035 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6036 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6037 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6038 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306039 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006040 ATRACE_END();
6041 return -EINVAL;
6042 }
6043
Ashish Jainf1eaa582016-05-23 20:54:24 +05306044 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6045 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6046
Ashish Jain83a6cc22016-06-28 14:34:17 +05306047 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306048 dst_format,
6049 buffer,
6050 src_format,
6051 frames);
6052
Ashish Jain83a6cc22016-06-28 14:34:17 +05306053 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306054 bytes_to_write);
6055
6056 /*Convert written bytes in audio flinger format*/
6057 if (ret > 0)
6058 ret = ((ret * format_to_bitwidth_table[out->format]) /
6059 format_to_bitwidth_table[dst_format]);
6060 }
6061 } else
6062 ret = compress_write(out->compr, buffer, bytes);
6063
Zhou Songc9672822017-08-16 16:01:39 +08006064 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6065 update_frames_written(out, bytes);
6066
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306067 if (ret < 0)
6068 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006069 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306070 /*msg to cb thread only if non blocking write is enabled*/
6071 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306072 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006073 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306074 } else if (-ENETRESET == ret) {
6075 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306076 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306077 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306078 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006079 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306080 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006081 }
Ashish Jain5106d362016-05-11 19:23:33 +05306082
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306083 /* Call compr start only when non-zero bytes of data is there to be rendered */
6084 if (!out->playback_started && ret > 0) {
6085 int status = compress_start(out->compr);
6086 if (status < 0) {
6087 ret = status;
6088 ALOGE("%s: compr start failed with err %d", __func__, errno);
6089 goto exit;
6090 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006091 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006092 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006093 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006094 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006095 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006096
6097 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6098 popcount(out->channel_mask),
6099 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006100 }
6101 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006102 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006103 return ret;
6104 } else {
6105 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006106 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006107 if (out->muted)
6108 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006109 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6110 __func__, frames, frame_size, bytes_to_write);
6111
Aalique Grahame22e49102018-12-18 14:23:57 -08006112 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006113 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6114 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6115 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006116 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6117 int16_t *src = (int16_t *)buffer;
6118 int16_t *dst = (int16_t *)buffer;
6119
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006120 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006121 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006122 "out_write called for %s use case with wrong properties",
6123 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006124
6125 /*
6126 * FIXME: this can be removed once audio flinger mixer supports
6127 * mono output
6128 */
6129
6130 /*
6131 * Code below goes over each frame in the buffer and adds both
6132 * L and R samples and then divides by 2 to convert to mono
6133 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006134 if (channel_count == 2) {
6135 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6136 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6137 }
6138 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006139 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006140 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006141
6142 // Note: since out_get_presentation_position() is called alternating with out_write()
6143 // by AudioFlinger, we can check underruns using the prior timestamp read.
6144 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6145 if (out->last_fifo_valid) {
6146 // compute drain to see if there is an underrun.
6147 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306148 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6149 int64_t frames_by_time =
6150 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6151 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006152 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6153
6154 if (underrun > 0) {
6155 simple_stats_log(&out->fifo_underruns, underrun);
6156
6157 ALOGW("%s: underrun(%lld) "
6158 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6159 __func__,
6160 (long long)out->fifo_underruns.n,
6161 (long long)frames_by_time,
6162 (long long)out->last_fifo_frames_remaining);
6163 }
6164 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6165 }
6166
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306167 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006168
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006169 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006170
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006171 if (out->config.rate)
6172 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6173 out->config.rate;
6174
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006175 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006176 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6177
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006178 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006179 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006180 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306181 out->convert_buffer != NULL) {
6182
6183 memcpy_by_audio_format(out->convert_buffer,
6184 out->hal_op_format,
6185 buffer,
6186 out->hal_ip_format,
6187 out->config.period_size * out->config.channels);
6188
6189 ret = pcm_write(out->pcm, out->convert_buffer,
6190 (out->config.period_size *
6191 out->config.channels *
6192 format_to_bitwidth_table[out->hal_op_format]));
6193 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306194 /*
6195 * To avoid underrun in DSP when the application is not pumping
6196 * data at required rate, check for the no. of bytes and ignore
6197 * pcm_write if it is less than actual buffer size.
6198 * It is a work around to a change in compress VOIP driver.
6199 */
6200 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6201 bytes < (out->config.period_size * out->config.channels *
6202 audio_bytes_per_sample(out->format))) {
6203 size_t voip_buf_size =
6204 out->config.period_size * out->config.channels *
6205 audio_bytes_per_sample(out->format);
6206 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6207 __func__, bytes, voip_buf_size);
6208 usleep(((uint64_t)voip_buf_size - bytes) *
6209 1000000 / audio_stream_out_frame_size(stream) /
6210 out_get_sample_rate(&out->stream.common));
6211 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006212 } else {
6213 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6214 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6215 else
6216 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6217 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306218 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006219
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006220 release_out_focus(out);
6221
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306222 if (ret < 0)
6223 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006224 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306225 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227 }
6228
6229exit:
Zhou Songc9672822017-08-16 16:01:39 +08006230 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306231 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306232 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006234 pthread_mutex_unlock(&out->lock);
6235
6236 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006237 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006238 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306239 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306240 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306241 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306242 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306243 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306244 out->standby = true;
6245 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306246 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006247 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6248 /* prevent division-by-zero */
6249 uint32_t stream_size = audio_stream_out_frame_size(stream);
6250 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006251
Dieter Luecking5d57def2018-09-07 14:23:37 +02006252 if ((stream_size == 0) || (srate == 0)) {
6253 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6254 ATRACE_END();
6255 return -EINVAL;
6256 }
6257 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6258 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006259 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306260 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006261 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006262 return ret;
6263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006264 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006265 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 return bytes;
6267}
6268
6269static int out_get_render_position(const struct audio_stream_out *stream,
6270 uint32_t *dsp_frames)
6271{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006272 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006273
6274 if (dsp_frames == NULL)
6275 return -EINVAL;
6276
6277 *dsp_frames = 0;
6278 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006279 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306280
6281 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6282 * this operation and adev_close_output_stream(where out gets reset).
6283 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306284 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006285 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306286 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006287 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306288 return 0;
6289 }
6290
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006291 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306292 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306293 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006294 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306295 if (ret < 0)
6296 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006297 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306298 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006299 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306300 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;
6303 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306304 } else if(ret < 0) {
6305 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306306 ret = -EINVAL;
6307 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306308 /*
6309 * Handle corner case where compress session is closed during SSR
6310 * and timestamp is queried
6311 */
6312 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306313 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306314 } else if (out->prev_card_status_offline) {
6315 ALOGE("ERROR: previously sound card was offline,return error");
6316 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306317 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306318 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006319 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306320 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306321 pthread_mutex_unlock(&out->lock);
6322 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006323 } else if (audio_is_linear_pcm(out->format)) {
6324 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006325 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006326 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006327 } else
6328 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006329}
6330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006331static int out_add_audio_effect(const struct audio_stream *stream __unused,
6332 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006333{
6334 return 0;
6335}
6336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006337static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6338 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006339{
6340 return 0;
6341}
6342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006343static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6344 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006345{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306346 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006347}
6348
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006349static int out_get_presentation_position(const struct audio_stream_out *stream,
6350 uint64_t *frames, struct timespec *timestamp)
6351{
6352 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306353 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006354 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006355
Ashish Jain5106d362016-05-11 19:23:33 +05306356 /* below piece of code is not guarded against any lock because audioFliner serializes
6357 * this operation and adev_close_output_stream( where out gets reset).
6358 */
6359 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306360 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006361 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306362 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6363 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6364 return 0;
6365 }
6366
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006367 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006368
Ashish Jain5106d362016-05-11 19:23:33 +05306369 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6370 ret = compress_get_tstamp(out->compr, &dsp_frames,
6371 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006372 // Adjustment accounts for A2dp encoder latency with offload usecases
6373 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006374 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006375 unsigned long offset =
6376 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6377 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6378 }
Ashish Jain5106d362016-05-11 19:23:33 +05306379 ALOGVV("%s rendered frames %ld sample_rate %d",
6380 __func__, dsp_frames, out->sample_rate);
6381 *frames = dsp_frames;
6382 if (ret < 0)
6383 ret = -errno;
6384 if (-ENETRESET == ret) {
6385 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306386 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306387 ret = -EINVAL;
6388 } else
6389 ret = 0;
6390 /* this is the best we can do */
6391 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006392 } else {
6393 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006394 unsigned int avail;
6395 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006396 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006397 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006398
Andy Hunga1f48fa2019-07-01 18:14:53 -07006399 if (out->kernel_buffer_size > avail) {
6400 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6401 } else {
6402 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6403 __func__, avail, out->kernel_buffer_size);
6404 avail = out->kernel_buffer_size;
6405 frames_temp = out->last_fifo_frames_remaining = 0;
6406 }
6407 out->last_fifo_valid = true;
6408 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6409
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006410 if (out->written >= frames_temp)
6411 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006412
Andy Hunga1f48fa2019-07-01 18:14:53 -07006413 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6414 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6415
Weiyin Jiangd4633762018-03-16 12:05:03 +08006416 // This adjustment accounts for buffering after app processor.
6417 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006418 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006419 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006420 if (signed_frames >= frames_temp)
6421 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006422
Weiyin Jiangd4633762018-03-16 12:05:03 +08006423 // Adjustment accounts for A2dp encoder latency with non offload usecases
6424 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006425 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006426 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6427 if (signed_frames >= frames_temp)
6428 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006429 }
6430
6431 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006432 *frames = signed_frames;
6433 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006434 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006435 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6436 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006437 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306438 *frames = out->written;
6439 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306440 if (is_offload_usecase(out->usecase))
6441 ret = -EINVAL;
6442 else
6443 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006444 }
6445 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006446 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006447 return ret;
6448}
6449
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006450static int out_set_callback(struct audio_stream_out *stream,
6451 stream_callback_t callback, void *cookie)
6452{
6453 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006454 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455
6456 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006457 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006458 out->client_callback = callback;
6459 out->client_cookie = cookie;
6460 if (out->adsp_hdlr_stream_handle) {
6461 ret = audio_extn_adsp_hdlr_stream_set_callback(
6462 out->adsp_hdlr_stream_handle,
6463 callback,
6464 cookie);
6465 if (ret)
6466 ALOGW("%s:adsp hdlr callback registration failed %d",
6467 __func__, ret);
6468 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006469 pthread_mutex_unlock(&out->lock);
6470 return 0;
6471}
6472
6473static int out_pause(struct audio_stream_out* stream)
6474{
6475 struct stream_out *out = (struct stream_out *)stream;
6476 int status = -ENOSYS;
6477 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006478 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006479 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306480 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006481 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006482 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006483 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306484 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306485 status = compress_pause(out->compr);
6486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006487 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006488
Mingming Yin21854652016-04-13 11:54:02 -07006489 if (audio_extn_passthru_is_active()) {
6490 ALOGV("offload use case, pause passthru");
6491 audio_extn_passthru_on_pause(out);
6492 }
6493
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306494 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006495 audio_extn_dts_notify_playback_state(out->usecase, 0,
6496 out->sample_rate, popcount(out->channel_mask),
6497 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006498 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006499 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006500 pthread_mutex_unlock(&out->lock);
6501 }
6502 return status;
6503}
6504
6505static int out_resume(struct audio_stream_out* stream)
6506{
6507 struct stream_out *out = (struct stream_out *)stream;
6508 int status = -ENOSYS;
6509 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006510 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006511 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306512 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006513 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006514 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006515 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306516 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306517 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006518 }
6519 if (!status) {
6520 out->offload_state = OFFLOAD_STATE_PLAYING;
6521 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306522 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006523 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6524 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006525 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006526 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006527 pthread_mutex_unlock(&out->lock);
6528 }
6529 return status;
6530}
6531
6532static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6533{
6534 struct stream_out *out = (struct stream_out *)stream;
6535 int status = -ENOSYS;
6536 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006537 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006538 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006539 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6540 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6541 else
6542 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6543 pthread_mutex_unlock(&out->lock);
6544 }
6545 return status;
6546}
6547
6548static int out_flush(struct audio_stream_out* stream)
6549{
6550 struct stream_out *out = (struct stream_out *)stream;
6551 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006552 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006553 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006554 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006555 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006556 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6557 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006558 } else {
6559 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6560 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006561 out->written = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006562 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006563 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006564 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006565 return 0;
6566 }
6567 return -ENOSYS;
6568}
6569
Haynes Mathew George16081042017-05-31 17:16:49 -07006570static int out_stop(const struct audio_stream_out* stream)
6571{
6572 struct stream_out *out = (struct stream_out *)stream;
6573 struct audio_device *adev = out->dev;
6574 int ret = -ENOSYS;
6575
6576 ALOGV("%s", __func__);
6577 pthread_mutex_lock(&adev->lock);
6578 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6579 out->playback_started && out->pcm != NULL) {
6580 pcm_stop(out->pcm);
6581 ret = stop_output_stream(out);
6582 out->playback_started = false;
6583 }
6584 pthread_mutex_unlock(&adev->lock);
6585 return ret;
6586}
6587
6588static int out_start(const struct audio_stream_out* stream)
6589{
6590 struct stream_out *out = (struct stream_out *)stream;
6591 struct audio_device *adev = out->dev;
6592 int ret = -ENOSYS;
6593
6594 ALOGV("%s", __func__);
6595 pthread_mutex_lock(&adev->lock);
6596 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6597 !out->playback_started && out->pcm != NULL) {
6598 ret = start_output_stream(out);
6599 if (ret == 0) {
6600 out->playback_started = true;
6601 }
6602 }
6603 pthread_mutex_unlock(&adev->lock);
6604 return ret;
6605}
6606
6607/*
6608 * Modify config->period_count based on min_size_frames
6609 */
6610static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6611{
6612 int periodCountRequested = (min_size_frames + config->period_size - 1)
6613 / config->period_size;
6614 int periodCount = MMAP_PERIOD_COUNT_MIN;
6615
6616 ALOGV("%s original config.period_size = %d config.period_count = %d",
6617 __func__, config->period_size, config->period_count);
6618
6619 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6620 periodCount *= 2;
6621 }
6622 config->period_count = periodCount;
6623
6624 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6625}
6626
Phil Burkfe17efd2019-03-25 10:23:35 -07006627// Read offset for the positional timestamp from a persistent vendor property.
6628// This is to workaround apparent inaccuracies in the timing information that
6629// is used by the AAudio timing model. The inaccuracies can cause glitches.
6630static int64_t get_mmap_out_time_offset() {
6631 const int32_t kDefaultOffsetMicros = 0;
6632 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006633 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006634 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6635 return mmap_time_offset_micros * (int64_t)1000;
6636}
6637
Haynes Mathew George16081042017-05-31 17:16:49 -07006638static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6639 int32_t min_size_frames,
6640 struct audio_mmap_buffer_info *info)
6641{
6642 struct stream_out *out = (struct stream_out *)stream;
6643 struct audio_device *adev = out->dev;
6644 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006645 unsigned int offset1 = 0;
6646 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006647 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006648 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006649 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006650
Arun Mirpuri5d170872019-03-26 13:21:31 -07006651 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306652 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006653 pthread_mutex_lock(&adev->lock);
6654
Sharad Sanglec6f32552018-05-04 16:15:38 +05306655 if (CARD_STATUS_OFFLINE == out->card_status ||
6656 CARD_STATUS_OFFLINE == adev->card_status) {
6657 ALOGW("out->card_status or adev->card_status offline, try again");
6658 ret = -EIO;
6659 goto exit;
6660 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306661 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006662 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6663 ret = -EINVAL;
6664 goto exit;
6665 }
6666 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6667 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6668 ret = -ENOSYS;
6669 goto exit;
6670 }
6671 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6672 if (out->pcm_device_id < 0) {
6673 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6674 __func__, out->pcm_device_id, out->usecase);
6675 ret = -EINVAL;
6676 goto exit;
6677 }
6678
6679 adjust_mmap_period_count(&out->config, min_size_frames);
6680
Arun Mirpuri5d170872019-03-26 13:21:31 -07006681 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006682 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6683 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6684 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306685 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306686 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6687 out->card_status = CARD_STATUS_OFFLINE;
6688 adev->card_status = CARD_STATUS_OFFLINE;
6689 ret = -EIO;
6690 goto exit;
6691 }
6692
Haynes Mathew George16081042017-05-31 17:16:49 -07006693 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6694 step = "open";
6695 ret = -ENODEV;
6696 goto exit;
6697 }
6698 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6699 if (ret < 0) {
6700 step = "begin";
6701 goto exit;
6702 }
juyuchen626833d2019-06-04 16:48:02 +08006703
6704 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006705 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006706 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006707 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006708 ret = platform_get_mmap_data_fd(adev->platform,
6709 out->pcm_device_id, 0 /*playback*/,
6710 &info->shared_memory_fd,
6711 &mmap_size);
6712 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006713 // Fall back to non exclusive mode
6714 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6715 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006716 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6717 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6718
Arun Mirpuri5d170872019-03-26 13:21:31 -07006719 if (mmap_size < buffer_size) {
6720 step = "mmap";
6721 goto exit;
6722 }
juyuchen626833d2019-06-04 16:48:02 +08006723 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006724 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006725 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006726 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006727
6728 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6729 if (ret < 0) {
6730 step = "commit";
6731 goto exit;
6732 }
6733
Phil Burkfe17efd2019-03-25 10:23:35 -07006734 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6735
Haynes Mathew George16081042017-05-31 17:16:49 -07006736 out->standby = false;
6737 ret = 0;
6738
Arun Mirpuri5d170872019-03-26 13:21:31 -07006739 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006740 __func__, info->shared_memory_address, info->buffer_size_frames);
6741
6742exit:
6743 if (ret != 0) {
6744 if (out->pcm == NULL) {
6745 ALOGE("%s: %s - %d", __func__, step, ret);
6746 } else {
6747 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6748 pcm_close(out->pcm);
6749 out->pcm = NULL;
6750 }
6751 }
6752 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306753 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006754 return ret;
6755}
6756
6757static int out_get_mmap_position(const struct audio_stream_out *stream,
6758 struct audio_mmap_position *position)
6759{
6760 struct stream_out *out = (struct stream_out *)stream;
6761 ALOGVV("%s", __func__);
6762 if (position == NULL) {
6763 return -EINVAL;
6764 }
6765 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006766 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006767 return -ENOSYS;
6768 }
6769 if (out->pcm == NULL) {
6770 return -ENOSYS;
6771 }
6772
6773 struct timespec ts = { 0, 0 };
6774 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6775 if (ret < 0) {
6776 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6777 return ret;
6778 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006779 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6780 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006781 return 0;
6782}
6783
6784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785/** audio_stream_in implementation **/
6786static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6787{
6788 struct stream_in *in = (struct stream_in *)stream;
6789
6790 return in->config.rate;
6791}
6792
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006793static int in_set_sample_rate(struct audio_stream *stream __unused,
6794 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006795{
6796 return -ENOSYS;
6797}
6798
6799static size_t in_get_buffer_size(const struct audio_stream *stream)
6800{
6801 struct stream_in *in = (struct stream_in *)stream;
6802
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006803 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6804 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006805 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6806 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306807 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306808 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006809
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006810 return in->config.period_size * in->af_period_multiplier *
6811 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006812}
6813
6814static uint32_t in_get_channels(const struct audio_stream *stream)
6815{
6816 struct stream_in *in = (struct stream_in *)stream;
6817
6818 return in->channel_mask;
6819}
6820
6821static audio_format_t in_get_format(const struct audio_stream *stream)
6822{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006823 struct stream_in *in = (struct stream_in *)stream;
6824
6825 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006826}
6827
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006828static int in_set_format(struct audio_stream *stream __unused,
6829 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006830{
6831 return -ENOSYS;
6832}
6833
6834static int in_standby(struct audio_stream *stream)
6835{
6836 struct stream_in *in = (struct stream_in *)stream;
6837 struct audio_device *adev = in->dev;
6838 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306839 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6840 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006841 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306842
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006843 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006844 if (!in->standby && in->is_st_session) {
6845 ALOGD("%s: sound trigger pcm stop lab", __func__);
6846 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006847 if (adev->num_va_sessions > 0)
6848 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006849 in->standby = 1;
6850 }
6851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006853 if (adev->adm_deregister_stream)
6854 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6855
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006856 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006857 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006858 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006859 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006860 voice_extn_compress_voip_close_input_stream(stream);
6861 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006862 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6863 do_stop = in->capture_started;
6864 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006865 if (in->mmap_shared_memory_fd >= 0) {
6866 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6867 __func__, in->mmap_shared_memory_fd);
6868 close(in->mmap_shared_memory_fd);
6869 in->mmap_shared_memory_fd = -1;
6870 }
Zhou Songa8895042016-07-05 17:54:22 +08006871 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306872 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306873 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006874 }
6875
Arun Mirpuri5d170872019-03-26 13:21:31 -07006876 if (in->pcm) {
6877 ATRACE_BEGIN("pcm_in_close");
6878 pcm_close(in->pcm);
6879 ATRACE_END();
6880 in->pcm = NULL;
6881 }
6882
Carter Hsu2e429db2019-05-14 18:50:52 +08006883 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006884 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006885
George Gao3018ede2019-10-23 13:23:00 -07006886 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6887 if (adev->num_va_sessions > 0)
6888 adev->num_va_sessions--;
6889 }
Quinn Malef6050362019-01-30 15:55:40 -08006890
Eric Laurent150dbfe2013-02-27 14:31:02 -08006891 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006892 }
6893 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006894 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006895 return status;
6896}
6897
Aalique Grahame22e49102018-12-18 14:23:57 -08006898static int in_dump(const struct audio_stream *stream,
6899 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006900{
Aalique Grahame22e49102018-12-18 14:23:57 -08006901 struct stream_in *in = (struct stream_in *)stream;
6902
6903 // We try to get the lock for consistency,
6904 // but it isn't necessary for these variables.
6905 // If we're not in standby, we may be blocked on a read.
6906 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6907 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6908 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6909 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6910
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006911 char buffer[256]; // for statistics formatting
6912 if (in->start_latency_ms.n > 0) {
6913 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6914 dprintf(fd, " Start latency ms: %s\n", buffer);
6915 }
6916
Aalique Grahame22e49102018-12-18 14:23:57 -08006917 if (locked) {
6918 pthread_mutex_unlock(&in->lock);
6919 }
6920
6921 // dump error info
6922 (void)error_log_dump(
6923 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006925 return 0;
6926}
6927
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306928static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6929{
6930 if (!stream || !parms)
6931 return;
6932
6933 struct stream_in *in = (struct stream_in *)stream;
6934 struct audio_device *adev = in->dev;
6935
6936 card_status_t status;
6937 int card;
6938 if (parse_snd_card_status(parms, &card, &status) < 0)
6939 return;
6940
6941 pthread_mutex_lock(&adev->lock);
6942 bool valid_cb = (card == adev->snd_card);
6943 pthread_mutex_unlock(&adev->lock);
6944
6945 if (!valid_cb)
6946 return;
6947
6948 lock_input_stream(in);
6949 if (in->card_status != status)
6950 in->card_status = status;
6951 pthread_mutex_unlock(&in->lock);
6952
6953 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6954 use_case_table[in->usecase],
6955 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6956
6957 // a better solution would be to report error back to AF and let
6958 // it put the stream to standby
6959 if (status == CARD_STATUS_OFFLINE)
6960 in_standby(&in->stream.common);
6961
6962 return;
6963}
6964
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006965int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006966 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006967 audio_source_t source)
6968{
6969 struct audio_device *adev = in->dev;
6970 int ret = 0;
6971
6972 lock_input_stream(in);
6973 pthread_mutex_lock(&adev->lock);
6974
6975 /* no audio source uses val == 0 */
6976 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6977 in->source = source;
6978 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6979 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6980 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6981 (in->config.rate == 8000 || in->config.rate == 16000 ||
6982 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6983 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6984 ret = voice_extn_compress_voip_open_input_stream(in);
6985 if (ret != 0) {
6986 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6987 __func__, ret);
6988 }
6989 }
6990 }
6991
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006992 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6993 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006994 // Workaround: If routing to an non existing usb device, fail gracefully
6995 // The routing request will otherwise block during 10 second
6996 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006997 struct str_parms *usb_addr =
6998 str_parms_create_str(get_usb_device_address(devices));
6999 if (is_usb_in_device_type(devices) && usb_addr &&
7000 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007001 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
7002 ret = -ENOSYS;
7003 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007004 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007005 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007006 if (!in->standby && !in->is_st_session) {
7007 ALOGV("update input routing change");
7008 // inform adm before actual routing to prevent glitches.
7009 if (adev->adm_on_routing_change) {
7010 adev->adm_on_routing_change(adev->adm_data,
7011 in->capture_handle);
7012 ret = select_devices(adev, in->usecase);
7013 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7014 adev->adm_routing_changed = true;
7015 }
7016 }
7017 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007018 if (usb_addr)
7019 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007020 }
7021 pthread_mutex_unlock(&adev->lock);
7022 pthread_mutex_unlock(&in->lock);
7023
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007024 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007025 return ret;
7026}
7027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007028static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7029{
7030 struct stream_in *in = (struct stream_in *)stream;
7031 struct audio_device *adev = in->dev;
7032 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007033 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307034 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007035
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307036 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007037 parms = str_parms_create_str(kvpairs);
7038
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307039 if (!parms)
7040 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007041 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007042 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007043
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307044 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7045 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307046 strlcpy(in->profile, value, sizeof(in->profile));
7047 ALOGV("updating stream profile with value '%s'", in->profile);
7048 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7049 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007050 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307051 in->sample_rate, in->bit_width,
7052 in->profile, &in->app_type_cfg);
7053 }
7054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007055 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007056 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007057
7058 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307059error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307060 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061}
7062
7063static char* in_get_parameters(const struct audio_stream *stream,
7064 const char *keys)
7065{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007066 struct stream_in *in = (struct stream_in *)stream;
7067 struct str_parms *query = str_parms_create_str(keys);
7068 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007069 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007070
7071 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007072 if (reply) {
7073 str_parms_destroy(reply);
7074 }
7075 if (query) {
7076 str_parms_destroy(query);
7077 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007078 ALOGE("in_get_parameters: failed to create query or reply");
7079 return NULL;
7080 }
7081
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007082 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007083
7084 voice_extn_in_get_parameters(in, query, reply);
7085
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007086 stream_get_parameter_channels(query, reply,
7087 &in->supported_channel_masks[0]);
7088 stream_get_parameter_formats(query, reply,
7089 &in->supported_formats[0]);
7090 stream_get_parameter_rates(query, reply,
7091 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007092 str = str_parms_to_str(reply);
7093 str_parms_destroy(query);
7094 str_parms_destroy(reply);
7095
7096 ALOGV("%s: exit: returns - %s", __func__, str);
7097 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007098}
7099
Aalique Grahame22e49102018-12-18 14:23:57 -08007100static int in_set_gain(struct audio_stream_in *stream,
7101 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007102{
Aalique Grahame22e49102018-12-18 14:23:57 -08007103 struct stream_in *in = (struct stream_in *)stream;
7104 char mixer_ctl_name[128];
7105 struct mixer_ctl *ctl;
7106 int ctl_value;
7107
7108 ALOGV("%s: gain %f", __func__, gain);
7109
7110 if (stream == NULL)
7111 return -EINVAL;
7112
7113 /* in_set_gain() only used to silence MMAP capture for now */
7114 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7115 return -ENOSYS;
7116
7117 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7118
7119 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7120 if (!ctl) {
7121 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7122 __func__, mixer_ctl_name);
7123 return -ENOSYS;
7124 }
7125
7126 if (gain < RECORD_GAIN_MIN)
7127 gain = RECORD_GAIN_MIN;
7128 else if (gain > RECORD_GAIN_MAX)
7129 gain = RECORD_GAIN_MAX;
7130 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7131
7132 mixer_ctl_set_value(ctl, 0, ctl_value);
7133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134 return 0;
7135}
7136
7137static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7138 size_t bytes)
7139{
7140 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307141
7142 if (in == NULL) {
7143 ALOGE("%s: stream_in ptr is NULL", __func__);
7144 return -EINVAL;
7145 }
7146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307148 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307149 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007150
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007151 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307152
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007153 if (in->is_st_session) {
7154 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7155 /* Read from sound trigger HAL */
7156 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007157 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007158 if (adev->num_va_sessions < UINT_MAX)
7159 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007160 in->standby = 0;
7161 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007162 pthread_mutex_unlock(&in->lock);
7163 return bytes;
7164 }
7165
Haynes Mathew George16081042017-05-31 17:16:49 -07007166 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7167 ret = -ENOSYS;
7168 goto exit;
7169 }
7170
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007171 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7172 !in->standby && adev->adm_routing_changed) {
7173 ret = -ENOSYS;
7174 goto exit;
7175 }
7176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007178 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7179
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007180 pthread_mutex_lock(&adev->lock);
7181 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7182 ret = voice_extn_compress_voip_start_input_stream(in);
7183 else
7184 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007185 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7186 if (adev->num_va_sessions < UINT_MAX)
7187 adev->num_va_sessions++;
7188 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007189 pthread_mutex_unlock(&adev->lock);
7190 if (ret != 0) {
7191 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007192 }
7193 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007194
7195 // log startup time in ms.
7196 simple_stats_log(
7197 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307200 /* Avoid read if capture_stopped is set */
7201 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7202 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7203 ret = -EINVAL;
7204 goto exit;
7205 }
7206
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007207 // what's the duration requested by the client?
7208 long ns = 0;
7209
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307210 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007211 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7212 in->config.rate;
7213
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007214 ret = request_in_focus(in, ns);
7215 if (ret != 0)
7216 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007217 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007218
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307219 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307220 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7221 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307222 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007223 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307224 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007225 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007226 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007227 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007228 } else if (audio_extn_ffv_get_stream() == in) {
7229 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307230 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007231 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307232 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7233 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7234 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7235 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307236 ret = -EINVAL;
7237 goto exit;
7238 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307239 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307240 ret = -errno;
7241 }
7242 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307243 /* bytes read is always set to bytes for non compress usecases */
7244 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245 }
7246
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007247 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249 /*
Quinn Malef6050362019-01-30 15:55:40 -08007250 * Instead of writing zeroes here, we could trust the hardware to always
7251 * provide zeroes when muted. This is also muted with voice recognition
7252 * usecases so that other clients do not have access to voice recognition
7253 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007254 */
Quinn Malef6050362019-01-30 15:55:40 -08007255 if ((ret == 0 && voice_get_mic_mute(adev) &&
7256 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007257 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7258 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007259 (adev->num_va_sessions &&
7260 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7261 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7262 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007263 memset(buffer, 0, bytes);
7264
7265exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307266 frame_size = audio_stream_in_frame_size(stream);
7267 if (frame_size > 0)
7268 in->frames_read += bytes_read/frame_size;
7269
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007270 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307271 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007272 pthread_mutex_unlock(&in->lock);
7273
7274 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307275 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307276 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307277 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307278 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307279 in->standby = true;
7280 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307281 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307282 bytes_read = bytes;
7283 memset(buffer, 0, bytes);
7284 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007286 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7287 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007288 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307289 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307290 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307292 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007293}
7294
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007295static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007296{
7297 return 0;
7298}
7299
Aalique Grahame22e49102018-12-18 14:23:57 -08007300static int in_get_capture_position(const struct audio_stream_in *stream,
7301 int64_t *frames, int64_t *time)
7302{
7303 if (stream == NULL || frames == NULL || time == NULL) {
7304 return -EINVAL;
7305 }
7306 struct stream_in *in = (struct stream_in *)stream;
7307 int ret = -ENOSYS;
7308
7309 lock_input_stream(in);
7310 // note: ST sessions do not close the alsa pcm driver synchronously
7311 // on standby. Therefore, we may return an error even though the
7312 // pcm stream is still opened.
7313 if (in->standby) {
7314 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7315 "%s stream in standby but pcm not NULL for non ST session", __func__);
7316 goto exit;
7317 }
7318 if (in->pcm) {
7319 struct timespec timestamp;
7320 unsigned int avail;
7321 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7322 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007323 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007324 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007325 ret = 0;
7326 }
7327 }
7328exit:
7329 pthread_mutex_unlock(&in->lock);
7330 return ret;
7331}
7332
Carter Hsu2e429db2019-05-14 18:50:52 +08007333static int in_update_effect_list(bool add, effect_handle_t effect,
7334 struct listnode *head)
7335{
7336 struct listnode *node;
7337 struct in_effect_list *elist = NULL;
7338 struct in_effect_list *target = NULL;
7339 int ret = 0;
7340
7341 if (!head)
7342 return ret;
7343
7344 list_for_each(node, head) {
7345 elist = node_to_item(node, struct in_effect_list, list);
7346 if (elist->handle == effect) {
7347 target = elist;
7348 break;
7349 }
7350 }
7351
7352 if (add) {
7353 if (target) {
7354 ALOGD("effect %p already exist", effect);
7355 return ret;
7356 }
7357
7358 target = (struct in_effect_list *)
7359 calloc(1, sizeof(struct in_effect_list));
7360
7361 if (!target) {
7362 ALOGE("%s:fail to allocate memory", __func__);
7363 return -ENOMEM;
7364 }
7365
7366 target->handle = effect;
7367 list_add_tail(head, &target->list);
7368 } else {
7369 if (target) {
7370 list_remove(&target->list);
7371 free(target);
7372 }
7373 }
7374
7375 return ret;
7376}
7377
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007378static int add_remove_audio_effect(const struct audio_stream *stream,
7379 effect_handle_t effect,
7380 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007381{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007382 struct stream_in *in = (struct stream_in *)stream;
7383 int status = 0;
7384 effect_descriptor_t desc;
7385
7386 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007387 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7388
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007389 if (status != 0)
7390 return status;
7391
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007392 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007393 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007394 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007395 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7396 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007397 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007398
7399 in_update_effect_list(enable, effect, &in->aec_list);
7400 enable = !list_empty(&in->aec_list);
7401 if (enable == in->enable_aec)
7402 goto exit;
7403
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007404 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007405 ALOGD("AEC enable %d", enable);
7406
Aalique Grahame22e49102018-12-18 14:23:57 -08007407 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7408 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7409 in->dev->enable_voicerx = enable;
7410 struct audio_usecase *usecase;
7411 struct listnode *node;
7412 list_for_each(node, &in->dev->usecase_list) {
7413 usecase = node_to_item(node, struct audio_usecase, list);
7414 if (usecase->type == PCM_PLAYBACK)
7415 select_devices(in->dev, usecase->id);
7416 }
7417 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007418 if (!in->standby) {
7419 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7420 select_devices(in->dev, in->usecase);
7421 }
7422
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007423 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007424 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7425
7426 in_update_effect_list(enable, effect, &in->ns_list);
7427 enable = !list_empty(&in->ns_list);
7428 if (enable == in->enable_ns)
7429 goto exit;
7430
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007431 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007432 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007433 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007434 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7435 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007436 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7437 select_devices(in->dev, in->usecase);
7438 } else
7439 select_devices(in->dev, in->usecase);
7440 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007441 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007442exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007443 pthread_mutex_unlock(&in->dev->lock);
7444 pthread_mutex_unlock(&in->lock);
7445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007446 return 0;
7447}
7448
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007449static int in_add_audio_effect(const struct audio_stream *stream,
7450 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007451{
Eric Laurent994a6932013-07-17 11:51:42 -07007452 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007453 return add_remove_audio_effect(stream, effect, true);
7454}
7455
7456static int in_remove_audio_effect(const struct audio_stream *stream,
7457 effect_handle_t effect)
7458{
Eric Laurent994a6932013-07-17 11:51:42 -07007459 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007460 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007461}
7462
Derek Chenf939fb72018-11-13 13:34:41 -08007463streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7464 audio_io_handle_t input)
7465{
7466 struct listnode *node;
7467
7468 list_for_each(node, &dev->active_inputs_list) {
7469 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7470 streams_input_ctxt_t,
7471 list);
7472 if (in_ctxt->input->capture_handle == input) {
7473 return in_ctxt;
7474 }
7475 }
7476 return NULL;
7477}
7478
7479streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7480 audio_io_handle_t output)
7481{
7482 struct listnode *node;
7483
7484 list_for_each(node, &dev->active_outputs_list) {
7485 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7486 streams_output_ctxt_t,
7487 list);
7488 if (out_ctxt->output->handle == output) {
7489 return out_ctxt;
7490 }
7491 }
7492 return NULL;
7493}
7494
Haynes Mathew George16081042017-05-31 17:16:49 -07007495static int in_stop(const struct audio_stream_in* stream)
7496{
7497 struct stream_in *in = (struct stream_in *)stream;
7498 struct audio_device *adev = in->dev;
7499
7500 int ret = -ENOSYS;
7501 ALOGV("%s", __func__);
7502 pthread_mutex_lock(&adev->lock);
7503 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7504 in->capture_started && in->pcm != NULL) {
7505 pcm_stop(in->pcm);
7506 ret = stop_input_stream(in);
7507 in->capture_started = false;
7508 }
7509 pthread_mutex_unlock(&adev->lock);
7510 return ret;
7511}
7512
7513static int in_start(const struct audio_stream_in* stream)
7514{
7515 struct stream_in *in = (struct stream_in *)stream;
7516 struct audio_device *adev = in->dev;
7517 int ret = -ENOSYS;
7518
7519 ALOGV("%s in %p", __func__, in);
7520 pthread_mutex_lock(&adev->lock);
7521 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7522 !in->capture_started && in->pcm != NULL) {
7523 if (!in->capture_started) {
7524 ret = start_input_stream(in);
7525 if (ret == 0) {
7526 in->capture_started = true;
7527 }
7528 }
7529 }
7530 pthread_mutex_unlock(&adev->lock);
7531 return ret;
7532}
7533
Phil Burke0a86d12019-02-16 22:28:11 -08007534// Read offset for the positional timestamp from a persistent vendor property.
7535// This is to workaround apparent inaccuracies in the timing information that
7536// is used by the AAudio timing model. The inaccuracies can cause glitches.
7537static int64_t in_get_mmap_time_offset() {
7538 const int32_t kDefaultOffsetMicros = 0;
7539 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007540 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007541 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7542 return mmap_time_offset_micros * (int64_t)1000;
7543}
7544
Haynes Mathew George16081042017-05-31 17:16:49 -07007545static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7546 int32_t min_size_frames,
7547 struct audio_mmap_buffer_info *info)
7548{
7549 struct stream_in *in = (struct stream_in *)stream;
7550 struct audio_device *adev = in->dev;
7551 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007552 unsigned int offset1 = 0;
7553 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007554 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007555 uint32_t mmap_size = 0;
7556 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007557
7558 pthread_mutex_lock(&adev->lock);
7559 ALOGV("%s in %p", __func__, in);
7560
Sharad Sanglec6f32552018-05-04 16:15:38 +05307561 if (CARD_STATUS_OFFLINE == in->card_status||
7562 CARD_STATUS_OFFLINE == adev->card_status) {
7563 ALOGW("in->card_status or adev->card_status offline, try again");
7564 ret = -EIO;
7565 goto exit;
7566 }
7567
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307568 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007569 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7570 ret = -EINVAL;
7571 goto exit;
7572 }
7573 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7574 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7575 ALOGV("%s in %p", __func__, in);
7576 ret = -ENOSYS;
7577 goto exit;
7578 }
7579 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7580 if (in->pcm_device_id < 0) {
7581 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7582 __func__, in->pcm_device_id, in->usecase);
7583 ret = -EINVAL;
7584 goto exit;
7585 }
7586
7587 adjust_mmap_period_count(&in->config, min_size_frames);
7588
7589 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7590 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7591 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7592 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307593 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307594 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7595 in->card_status = CARD_STATUS_OFFLINE;
7596 adev->card_status = CARD_STATUS_OFFLINE;
7597 ret = -EIO;
7598 goto exit;
7599 }
7600
Haynes Mathew George16081042017-05-31 17:16:49 -07007601 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7602 step = "open";
7603 ret = -ENODEV;
7604 goto exit;
7605 }
7606
7607 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7608 if (ret < 0) {
7609 step = "begin";
7610 goto exit;
7611 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007612
juyuchen626833d2019-06-04 16:48:02 +08007613 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007614 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7615 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7616 info->burst_size_frames = in->config.period_size;
7617 ret = platform_get_mmap_data_fd(adev->platform,
7618 in->pcm_device_id, 1 /*capture*/,
7619 &info->shared_memory_fd,
7620 &mmap_size);
7621 if (ret < 0) {
7622 // Fall back to non exclusive mode
7623 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7624 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007625 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7626 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7627
Arun Mirpuri5d170872019-03-26 13:21:31 -07007628 if (mmap_size < buffer_size) {
7629 step = "mmap";
7630 goto exit;
7631 }
juyuchen626833d2019-06-04 16:48:02 +08007632 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007633 }
7634
7635 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007636
7637 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7638 if (ret < 0) {
7639 step = "commit";
7640 goto exit;
7641 }
7642
Phil Burke0a86d12019-02-16 22:28:11 -08007643 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7644
Haynes Mathew George16081042017-05-31 17:16:49 -07007645 in->standby = false;
7646 ret = 0;
7647
7648 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7649 __func__, info->shared_memory_address, info->buffer_size_frames);
7650
7651exit:
7652 if (ret != 0) {
7653 if (in->pcm == NULL) {
7654 ALOGE("%s: %s - %d", __func__, step, ret);
7655 } else {
7656 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7657 pcm_close(in->pcm);
7658 in->pcm = NULL;
7659 }
7660 }
7661 pthread_mutex_unlock(&adev->lock);
7662 return ret;
7663}
7664
7665static int in_get_mmap_position(const struct audio_stream_in *stream,
7666 struct audio_mmap_position *position)
7667{
7668 struct stream_in *in = (struct stream_in *)stream;
7669 ALOGVV("%s", __func__);
7670 if (position == NULL) {
7671 return -EINVAL;
7672 }
7673 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7674 return -ENOSYS;
7675 }
7676 if (in->pcm == NULL) {
7677 return -ENOSYS;
7678 }
7679 struct timespec ts = { 0, 0 };
7680 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7681 if (ret < 0) {
7682 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7683 return ret;
7684 }
Phil Burke0a86d12019-02-16 22:28:11 -08007685 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7686 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007687 return 0;
7688}
7689
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307690static int in_get_active_microphones(const struct audio_stream_in *stream,
7691 struct audio_microphone_characteristic_t *mic_array,
7692 size_t *mic_count) {
7693 struct stream_in *in = (struct stream_in *)stream;
7694 struct audio_device *adev = in->dev;
7695 ALOGVV("%s", __func__);
7696
7697 lock_input_stream(in);
7698 pthread_mutex_lock(&adev->lock);
7699 int ret = platform_get_active_microphones(adev->platform,
7700 audio_channel_count_from_in_mask(in->channel_mask),
7701 in->usecase, mic_array, mic_count);
7702 pthread_mutex_unlock(&adev->lock);
7703 pthread_mutex_unlock(&in->lock);
7704
7705 return ret;
7706}
7707
7708static int adev_get_microphones(const struct audio_hw_device *dev,
7709 struct audio_microphone_characteristic_t *mic_array,
7710 size_t *mic_count) {
7711 struct audio_device *adev = (struct audio_device *)dev;
7712 ALOGVV("%s", __func__);
7713
7714 pthread_mutex_lock(&adev->lock);
7715 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7716 pthread_mutex_unlock(&adev->lock);
7717
7718 return ret;
7719}
juyuchendb308c22019-01-21 11:57:17 -07007720
7721static void in_update_sink_metadata(struct audio_stream_in *stream,
7722 const struct sink_metadata *sink_metadata) {
7723
7724 if (stream == NULL
7725 || sink_metadata == NULL
7726 || sink_metadata->tracks == NULL) {
7727 return;
7728 }
7729
7730 int error = 0;
7731 struct stream_in *in = (struct stream_in *)stream;
7732 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007733 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007734 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007735
7736 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007737
7738 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007739 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007740
7741 lock_input_stream(in);
7742 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007743 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007744
Zhou Song62ea0282020-03-22 19:53:01 +08007745 is_ha_usecase = adev->ha_proxy_enable ?
7746 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7747 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7748 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007749 && adev->voice_tx_output != NULL) {
7750 /* Use the rx device from afe-proxy record to route voice call because
7751 there is no routing if tx device is on primary hal and rx device
7752 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007753 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007754
7755 if (!voice_is_call_state_active(adev)) {
7756 if (adev->mode == AUDIO_MODE_IN_CALL) {
7757 adev->current_call_output = adev->voice_tx_output;
7758 error = voice_start_call(adev);
7759 if (error != 0)
7760 ALOGE("%s: start voice call failed %d", __func__, error);
7761 }
7762 } else {
7763 adev->current_call_output = adev->voice_tx_output;
7764 voice_update_devices_for_all_voice_usecases(adev);
7765 }
7766 }
7767
7768 pthread_mutex_unlock(&adev->lock);
7769 pthread_mutex_unlock(&in->lock);
7770}
7771
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307772int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007773 audio_io_handle_t handle,
7774 audio_devices_t devices,
7775 audio_output_flags_t flags,
7776 struct audio_config *config,
7777 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007778 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007779{
7780 struct audio_device *adev = (struct audio_device *)dev;
7781 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307782 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007783 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007784 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307785 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007786 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7787 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7788 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7789 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007790 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007791 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7792 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007793 bool force_haptic_path =
7794 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007795 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007796#ifdef AUDIO_GKI_ENABLED
7797 __s32 *generic_dec;
7798#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007799
kunleizdff872d2018-08-20 14:40:33 +08007800 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007801 is_usb_dev = false;
7802 devices = AUDIO_DEVICE_OUT_SPEAKER;
7803 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7804 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007805 if (config->format == AUDIO_FORMAT_DEFAULT)
7806 config->format = AUDIO_FORMAT_PCM_16_BIT;
7807 if (config->sample_rate == 0)
7808 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7809 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7810 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007811 }
7812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007813 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307814
Rahul Sharma99770982019-03-06 17:05:26 +05307815 pthread_mutex_lock(&adev->lock);
7816 if (out_get_stream(adev, handle) != NULL) {
7817 ALOGW("%s, output stream already opened", __func__);
7818 ret = -EEXIST;
7819 }
7820 pthread_mutex_unlock(&adev->lock);
7821 if (ret)
7822 return ret;
7823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007824 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7825
Mingming Yin3a941d42016-02-17 18:08:05 -08007826 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007827 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7828 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307829
7830
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007831 if (!out) {
7832 return -ENOMEM;
7833 }
7834
Haynes Mathew George204045b2015-02-25 20:32:03 -08007835 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007836 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007837 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007838 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007839 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007841 if (devices == AUDIO_DEVICE_NONE)
7842 devices = AUDIO_DEVICE_OUT_SPEAKER;
7843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007844 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007845 list_init(&out->device_list);
7846 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007847 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007848 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007849 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307850 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307851 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7852 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7853 else
7854 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007855 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007856 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007857 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307858 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307859 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007860 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007861 out->hal_output_suspend_supported = 0;
7862 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307863 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307864 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307865 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007866 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007867
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307868 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307869 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007870 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7871
Aalique Grahame22e49102018-12-18 14:23:57 -08007872 if (direct_dev &&
7873 (audio_is_linear_pcm(out->format) ||
7874 config->format == AUDIO_FORMAT_DEFAULT) &&
7875 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7876 audio_format_t req_format = config->format;
7877 audio_channel_mask_t req_channel_mask = config->channel_mask;
7878 uint32_t req_sample_rate = config->sample_rate;
7879
7880 pthread_mutex_lock(&adev->lock);
7881 if (is_hdmi) {
7882 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7883 ret = read_hdmi_sink_caps(out);
7884 if (config->sample_rate == 0)
7885 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7886 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7887 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7888 if (config->format == AUDIO_FORMAT_DEFAULT)
7889 config->format = AUDIO_FORMAT_PCM_16_BIT;
7890 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007891 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7892 &config->format,
7893 &out->supported_formats[0],
7894 MAX_SUPPORTED_FORMATS,
7895 &config->channel_mask,
7896 &out->supported_channel_masks[0],
7897 MAX_SUPPORTED_CHANNEL_MASKS,
7898 &config->sample_rate,
7899 &out->supported_sample_rates[0],
7900 MAX_SUPPORTED_SAMPLE_RATES);
7901 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007902 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007903
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007904 pthread_mutex_unlock(&adev->lock);
7905 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007906 if (ret == -ENOSYS) {
7907 /* ignore and go with default */
7908 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007909 }
7910 // For MMAP NO IRQ, allow conversions in ADSP
7911 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7912 goto error_open;
7913 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007914 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007915 goto error_open;
7916 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007917
7918 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7919 config->sample_rate = req_sample_rate;
7920 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7921 config->channel_mask = req_channel_mask;
7922 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7923 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007924 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007925
7926 out->sample_rate = config->sample_rate;
7927 out->channel_mask = config->channel_mask;
7928 out->format = config->format;
7929 if (is_hdmi) {
7930 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7931 out->config = pcm_config_hdmi_multi;
7932 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7933 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7934 out->config = pcm_config_mmap_playback;
7935 out->stream.start = out_start;
7936 out->stream.stop = out_stop;
7937 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7938 out->stream.get_mmap_position = out_get_mmap_position;
7939 } else {
7940 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7941 out->config = pcm_config_hifi;
7942 }
7943
7944 out->config.rate = out->sample_rate;
7945 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7946 if (is_hdmi) {
7947 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7948 audio_bytes_per_sample(out->format));
7949 }
7950 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007951 }
7952
Derek Chenf6318be2017-06-12 17:16:24 -04007953 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007954 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007955 /* extract car audio stream index */
7956 out->car_audio_stream =
7957 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7958 if (out->car_audio_stream < 0) {
7959 ALOGE("%s: invalid car audio stream %x",
7960 __func__, out->car_audio_stream);
7961 ret = -EINVAL;
7962 goto error_open;
7963 }
Derek Chen5f67a942020-02-24 23:08:13 -08007964 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007965 }
7966
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007967 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007968 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007969 if (!voice_extn_is_compress_voip_supported()) {
7970 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7971 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007972 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307973 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007974 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7975 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007976 out->volume_l = INVALID_OUT_VOLUME;
7977 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007978
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007979 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007980 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007981 uint32_t channel_count =
7982 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307983 out->config.channels = channel_count;
7984
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007985 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7986 out->sample_rate, out->format,
7987 channel_count, false);
7988 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7989 if (frame_size != 0)
7990 out->config.period_size = buffer_size / frame_size;
7991 else
7992 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007993 }
7994 } else {
7995 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7996 voice_extn_compress_voip_is_active(out->dev)) &&
7997 (voice_extn_compress_voip_is_config_supported(config))) {
7998 ret = voice_extn_compress_voip_open_output_stream(out);
7999 if (ret != 0) {
8000 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8001 __func__, ret);
8002 goto error_open;
8003 }
Sujin Panicker19027262019-09-16 18:28:06 +05308004 } else {
8005 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8006 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008007 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008008 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008009 } else if (audio_is_linear_pcm(out->format) &&
8010 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8011 out->channel_mask = config->channel_mask;
8012 out->sample_rate = config->sample_rate;
8013 out->format = config->format;
8014 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8015 // does this change?
8016 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8017 out->config.rate = config->sample_rate;
8018 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8019 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8020 audio_bytes_per_sample(config->format));
8021 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008022 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308023 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308024 pthread_mutex_lock(&adev->lock);
8025 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8026 pthread_mutex_unlock(&adev->lock);
8027
8028 // reject offload during card offline to allow
8029 // fallback to s/w paths
8030 if (offline) {
8031 ret = -ENODEV;
8032 goto error_open;
8033 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008034
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008035 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8036 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8037 ALOGE("%s: Unsupported Offload information", __func__);
8038 ret = -EINVAL;
8039 goto error_open;
8040 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008041
Atul Khare3fa6e542017-08-09 00:56:17 +05308042 if (config->offload_info.format == 0)
8043 config->offload_info.format = config->format;
8044 if (config->offload_info.sample_rate == 0)
8045 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008046
Mingming Yin90310102013-11-13 16:57:00 -08008047 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308048 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008049 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 ret = -EINVAL;
8051 goto error_open;
8052 }
8053
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008054 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8055 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8056 (audio_extn_passthru_is_passthrough_stream(out)) &&
8057 !((config->sample_rate == 48000) ||
8058 (config->sample_rate == 96000) ||
8059 (config->sample_rate == 192000))) {
8060 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8061 __func__, config->sample_rate, config->offload_info.format);
8062 ret = -EINVAL;
8063 goto error_open;
8064 }
8065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008066 out->compr_config.codec = (struct snd_codec *)
8067 calloc(1, sizeof(struct snd_codec));
8068
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008069 if (!out->compr_config.codec) {
8070 ret = -ENOMEM;
8071 goto error_open;
8072 }
8073
Dhananjay Kumarac341582017-02-23 23:42:25 +05308074 out->stream.pause = out_pause;
8075 out->stream.resume = out_resume;
8076 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308077 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308078 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008079 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308080 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008081 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308082 } else {
8083 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8084 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008085 }
vivek mehta446c3962015-09-14 10:57:35 -07008086
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308087 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8088 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008089#ifdef AUDIO_GKI_ENABLED
8090 /* out->compr_config.codec->reserved[1] is for flags */
8091 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8092#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308093 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008094#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308095 }
8096
vivek mehta446c3962015-09-14 10:57:35 -07008097 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008098 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008099 config->format == 0 && config->sample_rate == 0 &&
8100 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008101 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008102 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8103 } else {
8104 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8105 ret = -EEXIST;
8106 goto error_open;
8107 }
vivek mehta446c3962015-09-14 10:57:35 -07008108 }
8109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008110 if (config->offload_info.channel_mask)
8111 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008112 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008113 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008114 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008115 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308116 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008117 ret = -EINVAL;
8118 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008119 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008120
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008121 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008122 out->sample_rate = config->offload_info.sample_rate;
8123
Mingming Yin3ee55c62014-08-04 14:23:35 -07008124 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008125
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308126 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308127 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308128 audio_extn_dolby_send_ddp_endp_params(adev);
8129 audio_extn_dolby_set_dmid(adev);
8130 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008132 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008133 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008134 out->compr_config.codec->bit_rate =
8135 config->offload_info.bit_rate;
8136 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308137 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008138 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308139 /* Update bit width only for non passthrough usecases.
8140 * For passthrough usecases, the output will always be opened @16 bit
8141 */
8142 if (!audio_extn_passthru_is_passthrough_stream(out))
8143 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308144
8145 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008146#ifdef AUDIO_GKI_ENABLED
8147 /* out->compr_config.codec->reserved[1] is for flags */
8148 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8149 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8150#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308151 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8152 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008153#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308154
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008155 /*TODO: Do we need to change it for passthrough */
8156 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008157
Manish Dewangana6fc5442015-08-24 20:30:31 +05308158 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8159 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308160 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308161 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308162 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8163 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308164
8165 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8166 AUDIO_FORMAT_PCM) {
8167
8168 /*Based on platform support, configure appropriate alsa format for corresponding
8169 *hal input format.
8170 */
8171 out->compr_config.codec->format = hal_format_to_alsa(
8172 config->offload_info.format);
8173
Ashish Jain83a6cc22016-06-28 14:34:17 +05308174 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308175 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308176 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308177
Dhananjay Kumarac341582017-02-23 23:42:25 +05308178 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308179 *hal input format and alsa format might differ based on platform support.
8180 */
8181 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308182 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308183
8184 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8185
Deeraj Soman93155a62019-09-30 19:00:37 +05308186 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8187 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8188 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8189 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8190 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308191
Ashish Jainf1eaa582016-05-23 20:54:24 +05308192 /* Check if alsa session is configured with the same format as HAL input format,
8193 * if not then derive correct fragment size needed to accomodate the
8194 * conversion of HAL input format to alsa format.
8195 */
8196 audio_extn_utils_update_direct_pcm_fragment_size(out);
8197
8198 /*if hal input and output fragment size is different this indicates HAL input format is
8199 *not same as the alsa format
8200 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308201 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308202 /*Allocate a buffer to convert input data to the alsa configured format.
8203 *size of convert buffer is equal to the size required to hold one fragment size
8204 *worth of pcm data, this is because flinger does not write more than fragment_size
8205 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308206 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8207 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308208 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8209 ret = -ENOMEM;
8210 goto error_open;
8211 }
8212 }
8213 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8214 out->compr_config.fragment_size =
8215 audio_extn_passthru_get_buffer_size(&config->offload_info);
8216 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8217 } else {
8218 out->compr_config.fragment_size =
8219 platform_get_compress_offload_buffer_size(&config->offload_info);
8220 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8221 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008222
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308223 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8224 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8225 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008226 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8227#ifdef AUDIO_GKI_ENABLED
8228 generic_dec =
8229 &(out->compr_config.codec->options.generic.reserved[1]);
8230 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8231 AUDIO_OUTPUT_BIT_WIDTH;
8232#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308233 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008234#endif
8235 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008236
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308237 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8238 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8239 }
8240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008241 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8242 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008243
Manish Dewangan69426c82017-01-30 17:35:36 +05308244 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8245 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8246 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8247 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8248 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8249 } else {
8250 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8251 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008252
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308253 memset(&out->channel_map_param, 0,
8254 sizeof(struct audio_out_channel_map_param));
8255
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008256 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308257 out->send_next_track_params = false;
8258 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008259 out->offload_state = OFFLOAD_STATE_IDLE;
8260 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008261 out->writeAt.tv_sec = 0;
8262 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008263
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008264 audio_extn_dts_create_state_notifier_node(out->usecase);
8265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008266 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8267 __func__, config->offload_info.version,
8268 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308269
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308270 /* Check if DSD audio format is supported in codec
8271 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308272 */
8273
8274 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308275 (!platform_check_codec_dsd_support(adev->platform) ||
8276 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308277 ret = -EINVAL;
8278 goto error_open;
8279 }
8280
Ashish Jain5106d362016-05-11 19:23:33 +05308281 /* Disable gapless if any of the following is true
8282 * passthrough playback
8283 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308284 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308285 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308286 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308287 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008288 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308289 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308290 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308291 check_and_set_gapless_mode(adev, false);
8292 } else
8293 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008294
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308295 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008296 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8297 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308298 if (config->format == AUDIO_FORMAT_DSD) {
8299 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008300#ifdef AUDIO_GKI_ENABLED
8301 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8302 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8303#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308304 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008305#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308306 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008307
8308 create_offload_callback_thread(out);
8309
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008310 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008311 switch (config->sample_rate) {
8312 case 0:
8313 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8314 break;
8315 case 8000:
8316 case 16000:
8317 case 48000:
8318 out->sample_rate = config->sample_rate;
8319 break;
8320 default:
8321 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8322 config->sample_rate);
8323 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8324 ret = -EINVAL;
8325 goto error_open;
8326 }
8327 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8328 switch (config->channel_mask) {
8329 case AUDIO_CHANNEL_NONE:
8330 case AUDIO_CHANNEL_OUT_STEREO:
8331 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8332 break;
8333 default:
8334 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8335 config->channel_mask);
8336 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8337 ret = -EINVAL;
8338 goto error_open;
8339 }
8340 switch (config->format) {
8341 case AUDIO_FORMAT_DEFAULT:
8342 case AUDIO_FORMAT_PCM_16_BIT:
8343 out->format = AUDIO_FORMAT_PCM_16_BIT;
8344 break;
8345 default:
8346 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8347 config->format);
8348 config->format = AUDIO_FORMAT_PCM_16_BIT;
8349 ret = -EINVAL;
8350 goto error_open;
8351 }
8352
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308353 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008354 if (ret != 0) {
8355 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008356 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008357 goto error_open;
8358 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008359 } else if (is_single_device_type_equal(&out->device_list,
8360 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008361 switch (config->sample_rate) {
8362 case 0:
8363 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8364 break;
8365 case 8000:
8366 case 16000:
8367 case 48000:
8368 out->sample_rate = config->sample_rate;
8369 break;
8370 default:
8371 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8372 config->sample_rate);
8373 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8374 ret = -EINVAL;
8375 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008376 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008377 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8378 switch (config->channel_mask) {
8379 case AUDIO_CHANNEL_NONE:
8380 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8381 break;
8382 case AUDIO_CHANNEL_OUT_STEREO:
8383 out->channel_mask = config->channel_mask;
8384 break;
8385 default:
8386 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8387 config->channel_mask);
8388 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8389 ret = -EINVAL;
8390 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008391 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008392 switch (config->format) {
8393 case AUDIO_FORMAT_DEFAULT:
8394 out->format = AUDIO_FORMAT_PCM_16_BIT;
8395 break;
8396 case AUDIO_FORMAT_PCM_16_BIT:
8397 out->format = config->format;
8398 break;
8399 default:
8400 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8401 config->format);
8402 config->format = AUDIO_FORMAT_PCM_16_BIT;
8403 ret = -EINVAL;
8404 break;
8405 }
8406 if (ret != 0)
8407 goto error_open;
8408
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008409 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8410 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008411 out->config.rate = out->sample_rate;
8412 out->config.channels =
8413 audio_channel_count_from_out_mask(out->channel_mask);
8414 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008415 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008416 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308417 unsigned int channels = 0;
8418 /*Update config params to default if not set by the caller*/
8419 if (config->sample_rate == 0)
8420 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8421 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8422 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8423 if (config->format == AUDIO_FORMAT_DEFAULT)
8424 config->format = AUDIO_FORMAT_PCM_16_BIT;
8425
8426 channels = audio_channel_count_from_out_mask(out->channel_mask);
8427
Varun Balaraje49253e2017-07-06 19:48:56 +05308428 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8429 out->usecase = get_interactive_usecase(adev);
8430 out->config = pcm_config_low_latency;
8431 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308432 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008433 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8434 out->flags);
8435 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008436 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8437 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8438 out->config = pcm_config_mmap_playback;
8439 out->stream.start = out_start;
8440 out->stream.stop = out_stop;
8441 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8442 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308443 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8444 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008445 out->hal_output_suspend_supported =
8446 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8447 out->dynamic_pm_qos_config_supported =
8448 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8449 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008450 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8451 } else {
8452 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8453 //the mixer path will be a string similar to "low-latency-playback resume"
8454 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8455 strlcat(out->pm_qos_mixer_path,
8456 " resume", MAX_MIXER_PATH_LEN);
8457 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8458 out->pm_qos_mixer_path);
8459 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308460 out->config = pcm_config_low_latency;
8461 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8462 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8463 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308464 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8465 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8466 if (out->config.period_size <= 0) {
8467 ALOGE("Invalid configuration period size is not valid");
8468 ret = -EINVAL;
8469 goto error_open;
8470 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008471 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8472 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8473 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008474 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8475 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8476 out->config = pcm_config_haptics_audio;
8477 if (force_haptic_path)
8478 adev->haptics_config = pcm_config_haptics_audio;
8479 else
8480 adev->haptics_config = pcm_config_haptics;
8481
Meng Wangd08ce322020-04-02 08:59:20 +08008482 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008483 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8484
8485 if (force_haptic_path) {
8486 out->config.channels = 1;
8487 adev->haptics_config.channels = 1;
8488 } else
8489 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 -08008490 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008491 ret = audio_extn_auto_hal_open_output_stream(out);
8492 if (ret) {
8493 ALOGE("%s: Failed to open output stream for bus device", __func__);
8494 ret = -EINVAL;
8495 goto error_open;
8496 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308497 } else {
8498 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008499 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8500 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308501 }
8502 out->hal_ip_format = format = out->format;
8503 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8504 out->hal_op_format = pcm_format_to_hal(out->config.format);
8505 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8506 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008507 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308508 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308509 if (out->hal_ip_format != out->hal_op_format) {
8510 uint32_t buffer_size = out->config.period_size *
8511 format_to_bitwidth_table[out->hal_op_format] *
8512 out->config.channels;
8513 out->convert_buffer = calloc(1, buffer_size);
8514 if (out->convert_buffer == NULL){
8515 ALOGE("Allocation failed for convert buffer for size %d",
8516 out->compr_config.fragment_size);
8517 ret = -ENOMEM;
8518 goto error_open;
8519 }
8520 ALOGD("Convert buffer allocated of size %d", buffer_size);
8521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008522 }
8523
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008524 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8525 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308526
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008527 /* TODO remove this hardcoding and check why width is zero*/
8528 if (out->bit_width == 0)
8529 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308530 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008531 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008532 &out->device_list, out->flags,
8533 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308534 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308535 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008536 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008537 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8538 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008539 if(adev->primary_output == NULL)
8540 adev->primary_output = out;
8541 else {
8542 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008543 ret = -EEXIST;
8544 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008545 }
8546 }
8547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008548 /* Check if this usecase is already existing */
8549 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008550 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8551 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008553 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008554 ret = -EEXIST;
8555 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008556 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008558 pthread_mutex_unlock(&adev->lock);
8559
8560 out->stream.common.get_sample_rate = out_get_sample_rate;
8561 out->stream.common.set_sample_rate = out_set_sample_rate;
8562 out->stream.common.get_buffer_size = out_get_buffer_size;
8563 out->stream.common.get_channels = out_get_channels;
8564 out->stream.common.get_format = out_get_format;
8565 out->stream.common.set_format = out_set_format;
8566 out->stream.common.standby = out_standby;
8567 out->stream.common.dump = out_dump;
8568 out->stream.common.set_parameters = out_set_parameters;
8569 out->stream.common.get_parameters = out_get_parameters;
8570 out->stream.common.add_audio_effect = out_add_audio_effect;
8571 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8572 out->stream.get_latency = out_get_latency;
8573 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008574#ifdef NO_AUDIO_OUT
8575 out->stream.write = out_write_for_no_output;
8576#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008577 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008578#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008579 out->stream.get_render_position = out_get_render_position;
8580 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008581 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008582
Haynes Mathew George16081042017-05-31 17:16:49 -07008583 if (out->realtime)
8584 out->af_period_multiplier = af_period_multiplier;
8585 else
8586 out->af_period_multiplier = 1;
8587
Andy Hunga1f48fa2019-07-01 18:14:53 -07008588 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008590 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008591 out->volume_l = PLAYBACK_GAIN_MAX;
8592 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008593 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008594 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008595
8596 config->format = out->stream.common.get_format(&out->stream.common);
8597 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8598 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308599 register_format(out->format, out->supported_formats);
8600 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8601 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008602
Aalique Grahame22e49102018-12-18 14:23:57 -08008603 out->error_log = error_log_create(
8604 ERROR_LOG_ENTRIES,
8605 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8606
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308607 /*
8608 By locking output stream before registering, we allow the callback
8609 to update stream's state only after stream's initial state is set to
8610 adev state.
8611 */
8612 lock_output_stream(out);
8613 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8614 pthread_mutex_lock(&adev->lock);
8615 out->card_status = adev->card_status;
8616 pthread_mutex_unlock(&adev->lock);
8617 pthread_mutex_unlock(&out->lock);
8618
Aalique Grahame22e49102018-12-18 14:23:57 -08008619 stream_app_type_cfg_init(&out->app_type_cfg);
8620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008621 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308622 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008623 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008624
8625 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8626 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8627 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008628 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308629 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008630 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008631 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308632 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8633 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008634 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8635 out->usecase, PCM_PLAYBACK);
8636 hdlr_stream_cfg.flags = out->flags;
8637 hdlr_stream_cfg.type = PCM_PLAYBACK;
8638 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8639 &hdlr_stream_cfg);
8640 if (ret) {
8641 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8642 out->adsp_hdlr_stream_handle = NULL;
8643 }
8644 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308645 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8646 is_direct_passthough, false);
8647 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8648 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008649 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008650 if (ret < 0) {
8651 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8652 out->ip_hdlr_handle = NULL;
8653 }
8654 }
Derek Chenf939fb72018-11-13 13:34:41 -08008655
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008656 ret = io_streams_map_insert(adev, &out->stream.common,
8657 out->handle, AUDIO_PATCH_HANDLE_NONE);
8658 if (ret != 0)
8659 goto error_open;
8660
Derek Chenf939fb72018-11-13 13:34:41 -08008661 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8662 calloc(1, sizeof(streams_output_ctxt_t));
8663 if (out_ctxt == NULL) {
8664 ALOGE("%s fail to allocate output ctxt", __func__);
8665 ret = -ENOMEM;
8666 goto error_open;
8667 }
8668 out_ctxt->output = out;
8669
8670 pthread_mutex_lock(&adev->lock);
8671 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8672 pthread_mutex_unlock(&adev->lock);
8673
Eric Laurent994a6932013-07-17 11:51:42 -07008674 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008675 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008676
8677error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308678 if (out->convert_buffer)
8679 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008680 free(out);
8681 *stream_out = NULL;
8682 ALOGD("%s: exit: ret %d", __func__, ret);
8683 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008684}
8685
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308686void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008687 struct audio_stream_out *stream)
8688{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008689 struct stream_out *out = (struct stream_out *)stream;
8690 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008691 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008692
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008693 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008695 io_streams_map_remove(adev, out->handle);
8696
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308697 // must deregister from sndmonitor first to prevent races
8698 // between the callback and close_stream
8699 audio_extn_snd_mon_unregister_listener(out);
8700
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008701 /* close adsp hdrl session before standby */
8702 if (out->adsp_hdlr_stream_handle) {
8703 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8704 if (ret)
8705 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8706 out->adsp_hdlr_stream_handle = NULL;
8707 }
8708
Manish Dewangan21a850a2017-08-14 12:03:55 +05308709 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008710 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8711 out->ip_hdlr_handle = NULL;
8712 }
8713
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008714 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308715 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008716 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308717 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308718 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008719 if(ret != 0)
8720 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8721 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008722 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008723 out_standby(&stream->common);
8724
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008725 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008726 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008727 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008728 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008729 if (out->compr_config.codec != NULL)
8730 free(out->compr_config.codec);
8731 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008732
Zhou Songbaddf9f2020-11-20 13:57:39 +08008733 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308734
Varun Balaraje49253e2017-07-06 19:48:56 +05308735 if (is_interactive_usecase(out->usecase))
8736 free_interactive_usecase(adev, out->usecase);
8737
Ashish Jain83a6cc22016-06-28 14:34:17 +05308738 if (out->convert_buffer != NULL) {
8739 free(out->convert_buffer);
8740 out->convert_buffer = NULL;
8741 }
8742
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008743 if (adev->voice_tx_output == out)
8744 adev->voice_tx_output = NULL;
8745
Aalique Grahame22e49102018-12-18 14:23:57 -08008746 error_log_destroy(out->error_log);
8747 out->error_log = NULL;
8748
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308749 if (adev->primary_output == out)
8750 adev->primary_output = NULL;
8751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008752 pthread_cond_destroy(&out->cond);
8753 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008754 pthread_mutex_destroy(&out->pre_lock);
8755 pthread_mutex_destroy(&out->latch_lock);
8756 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008757
8758 pthread_mutex_lock(&adev->lock);
8759 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8760 if (out_ctxt != NULL) {
8761 list_remove(&out_ctxt->list);
8762 free(out_ctxt);
8763 } else {
8764 ALOGW("%s, output stream already closed", __func__);
8765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008767 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008768 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008769}
8770
8771static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8772{
8773 struct audio_device *adev = (struct audio_device *)dev;
8774 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008775 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008776 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008777 int ret;
8778 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008779 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008780 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008781 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008783 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008784 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008785
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308786 if (!parms)
8787 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308788
Derek Chen6f293672019-04-01 01:40:24 -07008789 /* notify adev and input/output streams on the snd card status */
8790 adev_snd_mon_cb((void *)adev, parms);
8791
Weiyin Jiang24f55292020-12-22 14:35:46 +08008792 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8793 if (ret >= 0) {
8794 list_for_each(node, &adev->active_outputs_list) {
8795 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8796 streams_output_ctxt_t,
8797 list);
8798 out_snd_mon_cb((void *)out_ctxt->output, parms);
8799 }
Derek Chen6f293672019-04-01 01:40:24 -07008800
Weiyin Jiang24f55292020-12-22 14:35:46 +08008801 list_for_each(node, &adev->active_inputs_list) {
8802 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8803 streams_input_ctxt_t,
8804 list);
8805 in_snd_mon_cb((void *)in_ctxt->input, parms);
8806 }
Derek Chen6f293672019-04-01 01:40:24 -07008807 }
8808
Zhou Songd6d71752019-05-21 18:08:51 +08008809 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308810 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8811 if (ret >= 0) {
8812 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008813 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308814 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008815 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308816 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008817 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008818 }
8819 }
8820
8821 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008822 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008823 if (!strncmp(value, "false", 5) &&
8824 audio_extn_a2dp_source_is_suspended()) {
8825 struct audio_usecase *usecase;
8826 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008827 list_for_each(node, &adev->usecase_list) {
8828 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008829 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008830 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008831 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008832 reassign_device_list(&usecase->stream.in->device_list,
8833 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008834 select_devices(adev, usecase->id);
8835 }
Zhou Songd6d71752019-05-21 18:08:51 +08008836 }
8837 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308838 }
8839
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008840 status = voice_set_parameters(adev, parms);
8841 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008842 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008843
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008844 status = platform_set_parameters(adev->platform, parms);
8845 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008846 goto done;
8847
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008848 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8849 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008850 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008851 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8852 adev->bluetooth_nrec = true;
8853 else
8854 adev->bluetooth_nrec = false;
8855 }
8856
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008857 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8858 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008859 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8860 adev->screen_off = false;
8861 else
8862 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008863 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008864 }
8865
Eric Laurent4b084132018-10-19 17:33:43 -07008866 ret = str_parms_get_int(parms, "rotation", &val);
8867 if (ret >= 0) {
8868 bool reverse_speakers = false;
8869 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8870 switch (val) {
8871 // FIXME: note that the code below assumes that the speakers are in the correct placement
8872 // relative to the user when the device is rotated 90deg from its default rotation. This
8873 // assumption is device-specific, not platform-specific like this code.
8874 case 270:
8875 reverse_speakers = true;
8876 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8877 break;
8878 case 0:
8879 case 180:
8880 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8881 break;
8882 case 90:
8883 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8884 break;
8885 default:
8886 ALOGE("%s: unexpected rotation of %d", __func__, val);
8887 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008888 }
Eric Laurent4b084132018-10-19 17:33:43 -07008889 if (status == 0) {
8890 // check and set swap
8891 // - check if orientation changed and speaker active
8892 // - set rotation and cache the rotation value
8893 adev->camera_orientation =
8894 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8895 if (!audio_extn_is_maxx_audio_enabled())
8896 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8897 }
8898 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008899
Mingming Yin514a8bc2014-07-29 15:22:21 -07008900 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8901 if (ret >= 0) {
8902 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8903 adev->bt_wb_speech_enabled = true;
8904 else
8905 adev->bt_wb_speech_enabled = false;
8906 }
8907
Zhou Song12c29502019-03-16 10:37:18 +08008908 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8909 if (ret >= 0) {
8910 val = atoi(value);
8911 adev->swb_speech_mode = val;
8912 }
8913
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008914 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8915 if (ret >= 0) {
8916 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308917 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008918 if (audio_is_output_device(val) &&
8919 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008920 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008921 platform_get_controller_stream_from_params(parms, &controller, &stream);
8922 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8923 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008924 if (ret < 0) {
8925 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308926 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008927 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008928 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308929 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008930 /*
8931 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8932 * Per AudioPolicyManager, USB device is higher priority than WFD.
8933 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8934 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8935 * starting voice call on USB
8936 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008937 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308938 if (ret >= 0)
8939 audio_extn_usb_add_device(device, atoi(value));
8940
Zhou Song6f862822017-11-06 17:27:57 +08008941 if (!audio_extn_usb_is_tunnel_supported()) {
8942 ALOGV("detected USB connect .. disable proxy");
8943 adev->allow_afe_proxy_usage = false;
8944 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008945 }
8946 }
8947
8948 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8949 if (ret >= 0) {
8950 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308951 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008952 /*
8953 * The HDMI / Displayport disconnect handling has been moved to
8954 * audio extension to ensure that its parameters are not
8955 * invalidated prior to updating sysfs of the disconnect event
8956 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8957 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308958 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008959 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308960 if (ret >= 0)
8961 audio_extn_usb_remove_device(device, atoi(value));
8962
Zhou Song6f862822017-11-06 17:27:57 +08008963 if (!audio_extn_usb_is_tunnel_supported()) {
8964 ALOGV("detected USB disconnect .. enable proxy");
8965 adev->allow_afe_proxy_usage = true;
8966 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008967 }
8968 }
8969
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008970 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008971
8972 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008973 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308974 struct audio_usecase *usecase;
8975 struct listnode *node;
8976 list_for_each(node, &adev->usecase_list) {
8977 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008978 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8979 continue;
8980
8981 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308982 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308983 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308984 ALOGD("Switching to speaker and muting the stream before select_devices");
8985 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308986 //force device switch to re configure encoder
8987 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308988 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08008989 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308990 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308991 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008992 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008993 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08008994 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008995 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8996 reassign_device_list(&usecase->stream.out->device_list,
8997 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8998 check_a2dp_restore_l(adev, usecase->stream.out, true);
8999 break;
9000 }
9001 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309002 }
9003 }
9004 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009005
9006 //handle vr audio setparam
9007 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9008 value, sizeof(value));
9009 if (ret >= 0) {
9010 ALOGI("Setting vr mode to be %s", value);
9011 if (!strncmp(value, "true", 4)) {
9012 adev->vr_audio_mode_enabled = true;
9013 ALOGI("Setting vr mode to true");
9014 } else if (!strncmp(value, "false", 5)) {
9015 adev->vr_audio_mode_enabled = false;
9016 ALOGI("Setting vr mode to false");
9017 } else {
9018 ALOGI("wrong vr mode set");
9019 }
9020 }
9021
Eric Laurent4b084132018-10-19 17:33:43 -07009022 //FIXME: to be replaced by proper video capture properties API
9023 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9024 if (ret >= 0) {
9025 int camera_facing = CAMERA_FACING_BACK;
9026 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9027 camera_facing = CAMERA_FACING_FRONT;
9028 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9029 camera_facing = CAMERA_FACING_BACK;
9030 else {
9031 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9032 goto done;
9033 }
9034 adev->camera_orientation =
9035 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9036 struct audio_usecase *usecase;
9037 struct listnode *node;
9038 list_for_each(node, &adev->usecase_list) {
9039 usecase = node_to_item(node, struct audio_usecase, list);
9040 struct stream_in *in = usecase->stream.in;
9041 if (usecase->type == PCM_CAPTURE && in != NULL &&
9042 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9043 select_devices(adev, in->usecase);
9044 }
9045 }
9046 }
9047
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309048 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009049done:
9050 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009051 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309052error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009053 ALOGV("%s: exit with code(%d)", __func__, status);
9054 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009055}
9056
9057static char* adev_get_parameters(const struct audio_hw_device *dev,
9058 const char *keys)
9059{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309060 ALOGD("%s:%s", __func__, keys);
9061
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009062 struct audio_device *adev = (struct audio_device *)dev;
9063 struct str_parms *reply = str_parms_create();
9064 struct str_parms *query = str_parms_create_str(keys);
9065 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309066 char value[256] = {0};
9067 int ret = 0;
9068
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009069 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009070 if (reply) {
9071 str_parms_destroy(reply);
9072 }
9073 if (query) {
9074 str_parms_destroy(query);
9075 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009076 ALOGE("adev_get_parameters: failed to create query or reply");
9077 return NULL;
9078 }
9079
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009080 //handle vr audio getparam
9081
9082 ret = str_parms_get_str(query,
9083 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9084 value, sizeof(value));
9085
9086 if (ret >= 0) {
9087 bool vr_audio_enabled = false;
9088 pthread_mutex_lock(&adev->lock);
9089 vr_audio_enabled = adev->vr_audio_mode_enabled;
9090 pthread_mutex_unlock(&adev->lock);
9091
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009092 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009093
9094 if (vr_audio_enabled) {
9095 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9096 "true");
9097 goto exit;
9098 } else {
9099 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9100 "false");
9101 goto exit;
9102 }
9103 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009104
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009105 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009106 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009107 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009108 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009109 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009110 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309111 pthread_mutex_unlock(&adev->lock);
9112
Naresh Tannirud7205b62014-06-20 02:54:48 +05309113exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009114 str = str_parms_to_str(reply);
9115 str_parms_destroy(query);
9116 str_parms_destroy(reply);
9117
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009118 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009119 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009120}
9121
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009122static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123{
9124 return 0;
9125}
9126
9127static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9128{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009129 int ret;
9130 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009131
9132 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9133
Haynes Mathew George5191a852013-09-11 14:19:36 -07009134 pthread_mutex_lock(&adev->lock);
9135 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009136 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009137 pthread_mutex_unlock(&adev->lock);
9138 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009139}
9140
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009141static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9142 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009143{
9144 return -ENOSYS;
9145}
9146
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009147static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9148 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149{
9150 return -ENOSYS;
9151}
9152
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009153static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9154 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009155{
9156 return -ENOSYS;
9157}
9158
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009159static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9160 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009161{
9162 return -ENOSYS;
9163}
9164
9165static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9166{
9167 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009168 struct listnode *node;
9169 struct audio_usecase *usecase = NULL;
9170 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172 pthread_mutex_lock(&adev->lock);
9173 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309174 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9175 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009177 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309178 adev->current_call_output = adev->primary_output;
9179 voice_start_call(adev);
9180 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009181 (mode == AUDIO_MODE_NORMAL ||
9182 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009183 list_for_each(node, &adev->usecase_list) {
9184 usecase = node_to_item(node, struct audio_usecase, list);
9185 if (usecase->type == VOICE_CALL)
9186 break;
9187 }
9188 if (usecase &&
9189 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9190 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9191 true);
9192 if (ret != 0) {
9193 /* default service interval was successfully updated,
9194 reopen USB backend with new service interval */
9195 check_usecases_codec_backend(adev,
9196 usecase,
9197 usecase->out_snd_device);
9198 }
9199 }
9200
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009201 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009202 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009203 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009204 // restore device for other active usecases after stop call
9205 list_for_each(node, &adev->usecase_list) {
9206 usecase = node_to_item(node, struct audio_usecase, list);
9207 select_devices(adev, usecase->id);
9208 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009209 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009210 }
9211 pthread_mutex_unlock(&adev->lock);
9212 return 0;
9213}
9214
9215static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9216{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009217 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009218 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009219
9220 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009221 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009222 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009223
Derek Chend2530072014-11-24 12:39:14 -08009224 if (adev->ext_hw_plugin)
9225 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009226
9227 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009228 pthread_mutex_unlock(&adev->lock);
9229
9230 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231}
9232
9233static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9234{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009235 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236 return 0;
9237}
9238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009239static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009240 const struct audio_config *config)
9241{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009242 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009243
Aalique Grahame22e49102018-12-18 14:23:57 -08009244 /* Don't know if USB HIFI in this context so use true to be conservative */
9245 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9246 true /*is_usb_hifi */) != 0)
9247 return 0;
9248
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009249 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9250 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009251}
9252
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009253static bool adev_input_allow_hifi_record(struct audio_device *adev,
9254 audio_devices_t devices,
9255 audio_input_flags_t flags,
9256 audio_source_t source) {
9257 const bool allowed = true;
9258
9259 if (!audio_is_usb_in_device(devices))
9260 return !allowed;
9261
9262 switch (flags) {
9263 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009264 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009265 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9266 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009267 default:
9268 return !allowed;
9269 }
9270
9271 switch (source) {
9272 case AUDIO_SOURCE_DEFAULT:
9273 case AUDIO_SOURCE_MIC:
9274 case AUDIO_SOURCE_UNPROCESSED:
9275 break;
9276 default:
9277 return !allowed;
9278 }
9279
9280 switch (adev->mode) {
9281 case 0:
9282 break;
9283 default:
9284 return !allowed;
9285 }
9286
9287 return allowed;
9288}
9289
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009290static int adev_update_voice_comm_input_stream(struct stream_in *in,
9291 struct audio_config *config)
9292{
9293 bool valid_rate = (config->sample_rate == 8000 ||
9294 config->sample_rate == 16000 ||
9295 config->sample_rate == 32000 ||
9296 config->sample_rate == 48000);
9297 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9298
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009299 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009300 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009301 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9302 in->config = default_pcm_config_voip_copp;
9303 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9304 DEFAULT_VOIP_BUF_DURATION_MS,
9305 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009306 } else {
9307 ALOGW("%s No valid input in voip, use defaults"
9308 "sample rate %u, channel mask 0x%X",
9309 __func__, config->sample_rate, in->channel_mask);
9310 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009311 in->config.rate = config->sample_rate;
9312 in->sample_rate = config->sample_rate;
9313 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009314 //XXX needed for voice_extn_compress_voip_open_input_stream
9315 in->config.rate = config->sample_rate;
9316 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309317 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009318 voice_extn_compress_voip_is_active(in->dev)) &&
9319 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9320 valid_rate && valid_ch) {
9321 voice_extn_compress_voip_open_input_stream(in);
9322 // update rate entries to match config from AF
9323 in->config.rate = config->sample_rate;
9324 in->sample_rate = config->sample_rate;
9325 } else {
9326 ALOGW("%s compress voip not active, use defaults", __func__);
9327 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009328 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009329 return 0;
9330}
9331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009332static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009333 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009334 audio_devices_t devices,
9335 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009336 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309337 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009338 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009339 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009340{
9341 struct audio_device *adev = (struct audio_device *)dev;
9342 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009343 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009344 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009345 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309346 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009347 bool is_usb_dev = audio_is_usb_in_device(devices);
9348 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9349 devices,
9350 flags,
9351 source);
Andy Hung94320602018-10-29 18:31:12 -07009352 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9353 " sample_rate %u, channel_mask %#x, format %#x",
9354 __func__, flags, is_usb_dev, may_use_hifi_record,
9355 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309356
kunleizdff872d2018-08-20 14:40:33 +08009357 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009358 is_usb_dev = false;
9359 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9360 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9361 __func__, devices);
9362 }
9363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009364 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009365
9366 if (!(is_usb_dev && may_use_hifi_record)) {
9367 if (config->sample_rate == 0)
9368 config->sample_rate = 48000;
9369 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9370 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9371 if (config->format == AUDIO_FORMAT_DEFAULT)
9372 config->format = AUDIO_FORMAT_PCM_16_BIT;
9373
9374 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9375
Aalique Grahame22e49102018-12-18 14:23:57 -08009376 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9377 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009378 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309379 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009380
Rahul Sharma99770982019-03-06 17:05:26 +05309381 pthread_mutex_lock(&adev->lock);
9382 if (in_get_stream(adev, handle) != NULL) {
9383 ALOGW("%s, input stream already opened", __func__);
9384 ret = -EEXIST;
9385 }
9386 pthread_mutex_unlock(&adev->lock);
9387 if (ret)
9388 return ret;
9389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009390 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009391
9392 if (!in) {
9393 ALOGE("failed to allocate input stream");
9394 return -ENOMEM;
9395 }
9396
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309397 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309398 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9399 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009400 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009401 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009403 in->stream.common.get_sample_rate = in_get_sample_rate;
9404 in->stream.common.set_sample_rate = in_set_sample_rate;
9405 in->stream.common.get_buffer_size = in_get_buffer_size;
9406 in->stream.common.get_channels = in_get_channels;
9407 in->stream.common.get_format = in_get_format;
9408 in->stream.common.set_format = in_set_format;
9409 in->stream.common.standby = in_standby;
9410 in->stream.common.dump = in_dump;
9411 in->stream.common.set_parameters = in_set_parameters;
9412 in->stream.common.get_parameters = in_get_parameters;
9413 in->stream.common.add_audio_effect = in_add_audio_effect;
9414 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9415 in->stream.set_gain = in_set_gain;
9416 in->stream.read = in_read;
9417 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009418 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309419 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009420 in->stream.set_microphone_direction = in_set_microphone_direction;
9421 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009422 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009423
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009424 list_init(&in->device_list);
9425 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009426 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009427 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009428 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009429 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009430 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009431 in->bit_width = 16;
9432 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009433 in->direction = MIC_DIRECTION_UNSPECIFIED;
9434 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009435 list_init(&in->aec_list);
9436 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009437 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009438
Andy Hung94320602018-10-29 18:31:12 -07009439 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009440 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9441 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9442 /* Force channel config requested to mono if incall
9443 record is being requested for only uplink/downlink */
9444 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9445 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9446 ret = -EINVAL;
9447 goto err_open;
9448 }
9449 }
9450
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009451 if (is_usb_dev && may_use_hifi_record) {
9452 /* HiFi record selects an appropriate format, channel, rate combo
9453 depending on sink capabilities*/
9454 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9455 &config->format,
9456 &in->supported_formats[0],
9457 MAX_SUPPORTED_FORMATS,
9458 &config->channel_mask,
9459 &in->supported_channel_masks[0],
9460 MAX_SUPPORTED_CHANNEL_MASKS,
9461 &config->sample_rate,
9462 &in->supported_sample_rates[0],
9463 MAX_SUPPORTED_SAMPLE_RATES);
9464 if (ret != 0) {
9465 ret = -EINVAL;
9466 goto err_open;
9467 }
9468 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009469 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309470 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309471 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9472 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9473 in->config.format = PCM_FORMAT_S32_LE;
9474 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309475 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9476 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9477 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9478 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9479 bool ret_error = false;
9480 in->bit_width = 24;
9481 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9482 from HAL is 24_packed and 8_24
9483 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9484 24_packed return error indicating supported format is 24_packed
9485 *> In case of any other source requesting 24 bit or float return error
9486 indicating format supported is 16 bit only.
9487
9488 on error flinger will retry with supported format passed
9489 */
9490 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9491 (source != AUDIO_SOURCE_CAMCORDER)) {
9492 config->format = AUDIO_FORMAT_PCM_16_BIT;
9493 if (config->sample_rate > 48000)
9494 config->sample_rate = 48000;
9495 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009496 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9497 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309498 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9499 ret_error = true;
9500 }
9501
9502 if (ret_error) {
9503 ret = -EINVAL;
9504 goto err_open;
9505 }
9506 }
9507
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009508 in->channel_mask = config->channel_mask;
9509 in->format = config->format;
9510
9511 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309512
Huicheng Liu1404ba12020-09-11 01:03:25 -04009513 /* validate bus device address */
9514 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9515 /* extract car audio stream index */
9516 in->car_audio_stream =
9517 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9518 if (in->car_audio_stream < 0) {
9519 ALOGE("%s: invalid car audio stream %x",
9520 __func__, in->car_audio_stream);
9521 ret = -EINVAL;
9522 goto err_open;
9523 }
9524 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
9525 }
9526
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309527 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9528 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9529 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9530 else {
9531 ret = -EINVAL;
9532 goto err_open;
9533 }
9534 }
9535
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009536 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309537 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9538 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009539 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9540 is_low_latency = true;
9541#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309542 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9543 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9544 else
9545 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009546#endif
9547 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009548 if (!in->realtime) {
9549 in->config = pcm_config_audio_capture;
9550 frame_size = audio_stream_in_frame_size(&in->stream);
9551 buffer_size = get_input_buffer_size(config->sample_rate,
9552 config->format,
9553 channel_count,
9554 is_low_latency);
9555 in->config.period_size = buffer_size / frame_size;
9556 in->config.rate = config->sample_rate;
9557 in->af_period_multiplier = 1;
9558 } else {
9559 // period size is left untouched for rt mode playback
9560 in->config = pcm_config_audio_capture_rt;
9561 in->af_period_multiplier = af_period_multiplier;
9562 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009563 }
9564
9565 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9566 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9567 in->realtime = 0;
9568 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9569 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009570 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009571 in->stream.start = in_start;
9572 in->stream.stop = in_stop;
9573 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9574 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009575 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009576 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009577 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9578 in->config = pcm_config_audio_capture;
9579 frame_size = audio_stream_in_frame_size(&in->stream);
9580 buffer_size = get_input_buffer_size(config->sample_rate,
9581 config->format,
9582 channel_count,
9583 false /*is_low_latency*/);
9584 in->config.period_size = buffer_size / frame_size;
9585 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009586 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009587 switch (config->format) {
9588 case AUDIO_FORMAT_PCM_32_BIT:
9589 in->bit_width = 32;
9590 break;
9591 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9592 case AUDIO_FORMAT_PCM_8_24_BIT:
9593 in->bit_width = 24;
9594 break;
9595 default:
9596 in->bit_width = 16;
9597 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009598 } else if (is_single_device_type_equal(&in->device_list,
9599 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9600 is_single_device_type_equal(&in->device_list,
9601 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009602 if (config->sample_rate == 0)
9603 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9604 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9605 config->sample_rate != 8000) {
9606 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9607 ret = -EINVAL;
9608 goto err_open;
9609 }
9610 if (config->format == AUDIO_FORMAT_DEFAULT)
9611 config->format = AUDIO_FORMAT_PCM_16_BIT;
9612 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9613 config->format = AUDIO_FORMAT_PCM_16_BIT;
9614 ret = -EINVAL;
9615 goto err_open;
9616 }
9617
9618 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009619 if (adev->ha_proxy_enable &&
9620 is_single_device_type_equal(&in->device_list,
9621 AUDIO_DEVICE_IN_TELEPHONY_RX))
9622 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009623 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009624 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009625 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309626 } else if (in->realtime) {
9627 in->config = pcm_config_audio_capture_rt;
9628 in->config.format = pcm_format_from_audio_format(config->format);
9629 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009630 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9631 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9632 (config->sample_rate == 8000 ||
9633 config->sample_rate == 16000 ||
9634 config->sample_rate == 32000 ||
9635 config->sample_rate == 48000) &&
9636 channel_count == 1) {
9637 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9638 in->config = pcm_config_audio_capture;
9639 frame_size = audio_stream_in_frame_size(&in->stream);
9640 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9641 config->sample_rate,
9642 config->format,
9643 channel_count, false /*is_low_latency*/);
9644 in->config.period_size = buffer_size / frame_size;
9645 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9646 in->config.rate = config->sample_rate;
9647 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009648 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309649 int ret_val;
9650 pthread_mutex_lock(&adev->lock);
9651 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9652 in, config, &channel_mask_updated);
9653 pthread_mutex_unlock(&adev->lock);
9654
9655 if (!ret_val) {
9656 if (channel_mask_updated == true) {
9657 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9658 __func__, config->channel_mask);
9659 ret = -EINVAL;
9660 goto err_open;
9661 }
9662 ALOGD("%s: created multi-channel session succesfully",__func__);
9663 } else if (audio_extn_compr_cap_enabled() &&
9664 audio_extn_compr_cap_format_supported(config->format) &&
9665 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9666 audio_extn_compr_cap_init(in);
9667 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309668 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309669 if (ret)
9670 goto err_open;
9671 } else {
9672 in->config = pcm_config_audio_capture;
9673 in->config.rate = config->sample_rate;
9674 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309675 in->format = config->format;
9676 frame_size = audio_stream_in_frame_size(&in->stream);
9677 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009678 config->format,
9679 channel_count,
9680 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009681 /* prevent division-by-zero */
9682 if (frame_size == 0) {
9683 ALOGE("%s: Error frame_size==0", __func__);
9684 ret = -EINVAL;
9685 goto err_open;
9686 }
9687
Revathi Uddarajud2634032017-12-07 14:42:34 +05309688 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009689 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009690
Revathi Uddarajud2634032017-12-07 14:42:34 +05309691 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9692 /* optionally use VOIP usecase depending on config(s) */
9693 ret = adev_update_voice_comm_input_stream(in, config);
9694 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009695
Revathi Uddarajud2634032017-12-07 14:42:34 +05309696 if (ret) {
9697 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9698 goto err_open;
9699 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009700 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309701
9702 /* assign concurrent capture usecase if record has to caried out from
9703 * actual hardware input source */
9704 if (audio_extn_is_concurrent_capture_enabled() &&
9705 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309706 /* Acquire lock to avoid two concurrent use cases initialized to
9707 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009708
Samyak Jainc37062f2019-04-25 18:41:06 +05309709 if (in->usecase == USECASE_AUDIO_RECORD) {
9710 pthread_mutex_lock(&adev->lock);
9711 if (!(adev->pcm_record_uc_state)) {
9712 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9713 adev->pcm_record_uc_state = 1;
9714 pthread_mutex_unlock(&adev->lock);
9715 } else {
9716 pthread_mutex_unlock(&adev->lock);
9717 /* Assign compress record use case for second record */
9718 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9719 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9720 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9721 if (audio_extn_cin_applicable_stream(in)) {
9722 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309723 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309724 if (ret)
9725 goto err_open;
9726 }
9727 }
9728 }
kunleiz28c73e72019-03-27 17:24:04 +08009729 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009730 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9731 ret = audio_extn_auto_hal_open_input_stream(in);
9732 if (ret) {
9733 ALOGE("%s: Failed to open input stream for bus device", __func__);
9734 ret = -EINVAL;
9735 goto err_open;
9736 }
9737 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009738 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309739 if (audio_extn_ssr_get_stream() != in)
9740 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009741
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009742 in->sample_rate = in->config.rate;
9743
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309744 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9745 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009746 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009747 in->sample_rate, in->bit_width,
9748 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309749 register_format(in->format, in->supported_formats);
9750 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9751 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309752
Aalique Grahame22e49102018-12-18 14:23:57 -08009753 in->error_log = error_log_create(
9754 ERROR_LOG_ENTRIES,
9755 1000000000 /* aggregate consecutive identical errors within one second */);
9756
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009757 /* This stream could be for sound trigger lab,
9758 get sound trigger pcm if present */
9759 audio_extn_sound_trigger_check_and_get_session(in);
9760
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309761 lock_input_stream(in);
9762 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9763 pthread_mutex_lock(&adev->lock);
9764 in->card_status = adev->card_status;
9765 pthread_mutex_unlock(&adev->lock);
9766 pthread_mutex_unlock(&in->lock);
9767
Aalique Grahame22e49102018-12-18 14:23:57 -08009768 stream_app_type_cfg_init(&in->app_type_cfg);
9769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009770 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009771
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009772 ret = io_streams_map_insert(adev, &in->stream.common,
9773 handle, AUDIO_PATCH_HANDLE_NONE);
9774 if (ret != 0)
9775 goto err_open;
9776
Derek Chenf939fb72018-11-13 13:34:41 -08009777 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9778 calloc(1, sizeof(streams_input_ctxt_t));
9779 if (in_ctxt == NULL) {
9780 ALOGE("%s fail to allocate input ctxt", __func__);
9781 ret = -ENOMEM;
9782 goto err_open;
9783 }
9784 in_ctxt->input = in;
9785
9786 pthread_mutex_lock(&adev->lock);
9787 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9788 pthread_mutex_unlock(&adev->lock);
9789
Eric Laurent994a6932013-07-17 11:51:42 -07009790 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009792
9793err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309794 if (in->usecase == USECASE_AUDIO_RECORD) {
9795 pthread_mutex_lock(&adev->lock);
9796 adev->pcm_record_uc_state = 0;
9797 pthread_mutex_unlock(&adev->lock);
9798 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009799 free(in);
9800 *stream_in = NULL;
9801 return ret;
9802}
9803
9804static void adev_close_input_stream(struct audio_hw_device *dev,
9805 struct audio_stream_in *stream)
9806{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009807 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009808 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009809 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309810
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309811 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009812
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009813 if (in == NULL) {
9814 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9815 return;
9816 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009817 io_streams_map_remove(adev, in->capture_handle);
9818
kunleiz70e57612018-12-28 17:50:23 +08009819 /* must deregister from sndmonitor first to prevent races
9820 * between the callback and close_stream
9821 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309822 audio_extn_snd_mon_unregister_listener(stream);
9823
kunleiz70e57612018-12-28 17:50:23 +08009824 /* Disable echo reference if there are no active input, hfp call
9825 * and sound trigger while closing input stream
9826 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009827 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009828 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009829 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9830 struct listnode out_devices;
9831 list_init(&out_devices);
9832 platform_set_echo_reference(adev, false, &out_devices);
9833 } else
kunleiz70e57612018-12-28 17:50:23 +08009834 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309835
Weiyin Jiang2995f662019-04-17 14:25:12 +08009836 error_log_destroy(in->error_log);
9837 in->error_log = NULL;
9838
Pallavid7c7a272018-01-16 11:22:55 +05309839
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009840 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309841 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009842 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309843 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009844 if (ret != 0)
9845 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9846 __func__, ret);
9847 } else
9848 in_standby(&stream->common);
9849
Weiyin Jiang280ea742020-09-08 20:28:22 +08009850 pthread_mutex_destroy(&in->lock);
9851 pthread_mutex_destroy(&in->pre_lock);
9852
Revathi Uddarajud2634032017-12-07 14:42:34 +05309853 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309854 if (in->usecase == USECASE_AUDIO_RECORD) {
9855 adev->pcm_record_uc_state = 0;
9856 }
9857
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009858 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9859 adev->enable_voicerx = false;
9860 }
9861
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009862 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009863 audio_extn_ssr_deinit();
9864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009865
Garmond Leunge2433c32017-09-28 21:51:22 -07009866 if (audio_extn_ffv_get_stream() == in) {
9867 audio_extn_ffv_stream_deinit();
9868 }
9869
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309870 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009871 audio_extn_compr_cap_format_supported(in->config.format))
9872 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309873
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309874 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309875 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009876
Mingming Yinfd7607b2016-01-22 12:48:44 -08009877 if (in->is_st_session) {
9878 ALOGV("%s: sound trigger pcm stop lab", __func__);
9879 audio_extn_sound_trigger_stop_lab(in);
9880 }
Derek Chenf939fb72018-11-13 13:34:41 -08009881 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9882 if (in_ctxt != NULL) {
9883 list_remove(&in_ctxt->list);
9884 free(in_ctxt);
9885 } else {
9886 ALOGW("%s, input stream already closed", __func__);
9887 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009888 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309889 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009890 return;
9891}
9892
Aalique Grahame22e49102018-12-18 14:23:57 -08009893/* verifies input and output devices and their capabilities.
9894 *
9895 * This verification is required when enabling extended bit-depth or
9896 * sampling rates, as not all qcom products support it.
9897 *
9898 * Suitable for calling only on initialization such as adev_open().
9899 * It fills the audio_device use_case_table[] array.
9900 *
9901 * Has a side-effect that it needs to configure audio routing / devices
9902 * in order to power up the devices and read the device parameters.
9903 * It does not acquire any hw device lock. Should restore the devices
9904 * back to "normal state" upon completion.
9905 */
9906static int adev_verify_devices(struct audio_device *adev)
9907{
9908 /* enumeration is a bit difficult because one really wants to pull
9909 * the use_case, device id, etc from the hidden pcm_device_table[].
9910 * In this case there are the following use cases and device ids.
9911 *
9912 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9913 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9914 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9915 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9916 * [USECASE_AUDIO_RECORD] = {0, 0},
9917 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9918 * [USECASE_VOICE_CALL] = {2, 2},
9919 *
9920 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9921 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9922 */
9923
9924 /* should be the usecases enabled in adev_open_input_stream() */
9925 static const int test_in_usecases[] = {
9926 USECASE_AUDIO_RECORD,
9927 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9928 };
9929 /* should be the usecases enabled in adev_open_output_stream()*/
9930 static const int test_out_usecases[] = {
9931 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9932 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9933 };
9934 static const usecase_type_t usecase_type_by_dir[] = {
9935 PCM_PLAYBACK,
9936 PCM_CAPTURE,
9937 };
9938 static const unsigned flags_by_dir[] = {
9939 PCM_OUT,
9940 PCM_IN,
9941 };
9942
9943 size_t i;
9944 unsigned dir;
9945 const unsigned card_id = adev->snd_card;
9946
9947 for (dir = 0; dir < 2; ++dir) {
9948 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9949 const unsigned flags_dir = flags_by_dir[dir];
9950 const size_t testsize =
9951 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9952 const int *testcases =
9953 dir ? test_in_usecases : test_out_usecases;
9954 const audio_devices_t audio_device =
9955 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9956
9957 for (i = 0; i < testsize; ++i) {
9958 const audio_usecase_t audio_usecase = testcases[i];
9959 int device_id;
9960 struct pcm_params **pparams;
9961 struct stream_out out;
9962 struct stream_in in;
9963 struct audio_usecase uc_info;
9964 int retval;
9965
9966 pparams = &adev->use_case_table[audio_usecase];
9967 pcm_params_free(*pparams); /* can accept null input */
9968 *pparams = NULL;
9969
9970 /* find the device ID for the use case (signed, for error) */
9971 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9972 if (device_id < 0)
9973 continue;
9974
9975 /* prepare structures for device probing */
9976 memset(&uc_info, 0, sizeof(uc_info));
9977 uc_info.id = audio_usecase;
9978 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009979 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009980 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009981 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009982 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009983 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009984 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9985 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009986 }
9987 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009988 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009989 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009990 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009991 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009992 uc_info.in_snd_device = SND_DEVICE_NONE;
9993 uc_info.out_snd_device = SND_DEVICE_NONE;
9994 list_add_tail(&adev->usecase_list, &uc_info.list);
9995
9996 /* select device - similar to start_(in/out)put_stream() */
9997 retval = select_devices(adev, audio_usecase);
9998 if (retval >= 0) {
9999 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10000#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010001 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010002 if (*pparams) {
10003 ALOGV("%s: (%s) card %d device %d", __func__,
10004 dir ? "input" : "output", card_id, device_id);
10005 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10006 } else {
10007 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10008 }
10009#endif
10010 }
10011
10012 /* deselect device - similar to stop_(in/out)put_stream() */
10013 /* 1. Get and set stream specific mixer controls */
10014 retval = disable_audio_route(adev, &uc_info);
10015 /* 2. Disable the rx device */
10016 retval = disable_snd_device(adev,
10017 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10018 list_remove(&uc_info.list);
10019 }
10020 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010021 return 0;
10022}
10023
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024int update_patch(unsigned int num_sources,
10025 const struct audio_port_config *sources,
10026 unsigned int num_sinks,
10027 const struct audio_port_config *sinks,
10028 audio_patch_handle_t handle,
10029 struct audio_patch_info *p_info,
10030 patch_type_t patch_type, bool new_patch)
10031{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010032 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010033
10034 if (p_info == NULL) {
10035 ALOGE("%s: Invalid patch pointer", __func__);
10036 return -EINVAL;
10037 }
10038
10039 if (new_patch) {
10040 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10041 if (p_info->patch == NULL) {
10042 ALOGE("%s: Could not allocate patch", __func__);
10043 return -ENOMEM;
10044 }
10045 }
10046
10047 p_info->patch->id = handle;
10048 p_info->patch->num_sources = num_sources;
10049 p_info->patch->num_sinks = num_sinks;
10050
10051 for (int i = 0; i < num_sources; i++)
10052 p_info->patch->sources[i] = sources[i];
10053 for (int i = 0; i < num_sinks; i++)
10054 p_info->patch->sinks[i] = sinks[i];
10055
10056 p_info->patch_type = patch_type;
10057 return 0;
10058}
10059
10060audio_patch_handle_t generate_patch_handle()
10061{
10062 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10063 if (++patch_handle < 0)
10064 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10065 return patch_handle;
10066}
10067
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010068int adev_create_audio_patch(struct audio_hw_device *dev,
10069 unsigned int num_sources,
10070 const struct audio_port_config *sources,
10071 unsigned int num_sinks,
10072 const struct audio_port_config *sinks,
10073 audio_patch_handle_t *handle)
10074{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 int ret = 0;
10076 struct audio_device *adev = (struct audio_device *)dev;
10077 struct audio_patch_info *p_info = NULL;
10078 patch_type_t patch_type = PATCH_NONE;
10079 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10080 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10081 struct audio_stream_info *s_info = NULL;
10082 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010083 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010084 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10085 bool new_patch = false;
10086 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010087
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010088 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10089 num_sources, num_sinks, *handle);
10090
10091 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10092 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10093 ALOGE("%s: Invalid patch arguments", __func__);
10094 ret = -EINVAL;
10095 goto done;
10096 }
10097
10098 if (num_sources > 1) {
10099 ALOGE("%s: Multiple sources are not supported", __func__);
10100 ret = -EINVAL;
10101 goto done;
10102 }
10103
10104 if (sources == NULL || sinks == NULL) {
10105 ALOGE("%s: Invalid sources or sinks port config", __func__);
10106 ret = -EINVAL;
10107 goto done;
10108 }
10109
10110 ALOGV("%s: source role %d, source type %d", __func__,
10111 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010112 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010113
10114 // Populate source/sink information and fetch stream info
10115 switch (sources[0].type) {
10116 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10117 device_type = sources[0].ext.device.type;
10118 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010119 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010120 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10121 patch_type = PATCH_CAPTURE;
10122 io_handle = sinks[0].ext.mix.handle;
10123 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010124 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010125 __func__, device_type, io_handle);
10126 } else {
10127 // Device to device patch is not implemented.
10128 // This space will need changes if audio HAL
10129 // handles device to device patches in the future.
10130 patch_type = PATCH_DEVICE_LOOPBACK;
10131 }
10132 break;
10133 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10134 io_handle = sources[0].ext.mix.handle;
10135 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010136 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010138 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010139 }
10140 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010141 ALOGD("%s: Playback patch from mix handle %d to device %x",
10142 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010143 break;
10144 case AUDIO_PORT_TYPE_SESSION:
10145 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010146 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10147 ret = -EINVAL;
10148 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149 }
10150
10151 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 // Generate patch info and update patch
10154 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010155 *handle = generate_patch_handle();
10156 p_info = (struct audio_patch_info *)
10157 calloc(1, sizeof(struct audio_patch_info));
10158 if (p_info == NULL) {
10159 ALOGE("%s: Failed to allocate memory", __func__);
10160 pthread_mutex_unlock(&adev->lock);
10161 ret = -ENOMEM;
10162 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010163 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010164 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010166 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010167 if (p_info == NULL) {
10168 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10169 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010170 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010171 ret = -EINVAL;
10172 goto done;
10173 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010174 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010176 *handle, p_info, patch_type, new_patch);
10177
10178 // Fetch stream info of associated mix for playback or capture patches
10179 if (p_info->patch_type == PATCH_PLAYBACK ||
10180 p_info->patch_type == PATCH_CAPTURE) {
10181 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10182 if (s_info == NULL) {
10183 ALOGE("%s: Failed to obtain stream info", __func__);
10184 if (new_patch)
10185 free(p_info);
10186 pthread_mutex_unlock(&adev->lock);
10187 ret = -EINVAL;
10188 goto done;
10189 }
10190 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10191 s_info->patch_handle = *handle;
10192 stream = s_info->stream;
10193 }
10194 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195
10196 // Update routing for stream
10197 if (stream != NULL) {
10198 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010199 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010200 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010201 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010202 if (ret < 0) {
10203 pthread_mutex_lock(&adev->lock);
10204 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10205 if (new_patch)
10206 free(p_info);
10207 pthread_mutex_unlock(&adev->lock);
10208 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10209 goto done;
10210 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211 }
10212
10213 // Add new patch to patch map
10214 if (!ret && new_patch) {
10215 pthread_mutex_lock(&adev->lock);
10216 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010217 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010218 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 }
10220
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010221done:
10222 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010223 num_sources,
10224 sources,
10225 num_sinks,
10226 sinks,
10227 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010228 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010229 num_sources,
10230 sources,
10231 num_sinks,
10232 sinks,
10233 handle);
10234 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010235}
10236
10237int adev_release_audio_patch(struct audio_hw_device *dev,
10238 audio_patch_handle_t handle)
10239{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010240 struct audio_device *adev = (struct audio_device *) dev;
10241 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010242 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010243 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010244
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010245 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10246 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10247 ret = -EINVAL;
10248 goto done;
10249 }
10250
10251 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010252 pthread_mutex_lock(&adev->lock);
10253 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010254 if (p_info == NULL) {
10255 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010256 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010257 ret = -EINVAL;
10258 goto done;
10259 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010260 struct audio_patch *patch = p_info->patch;
10261 if (patch == NULL) {
10262 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010263 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010264 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010265 goto done;
10266 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010267 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10268 switch (patch->sources[0].type) {
10269 case AUDIO_PORT_TYPE_MIX:
10270 io_handle = patch->sources[0].ext.mix.handle;
10271 break;
10272 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010273 if (p_info->patch_type == PATCH_CAPTURE)
10274 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010275 break;
10276 case AUDIO_PORT_TYPE_SESSION:
10277 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010278 pthread_mutex_unlock(&adev->lock);
10279 ret = -EINVAL;
10280 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010281 }
10282
10283 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010284 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010285 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010286 if (patch_type == PATCH_PLAYBACK ||
10287 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010288 struct audio_stream_info *s_info =
10289 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10290 if (s_info == NULL) {
10291 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10292 pthread_mutex_unlock(&adev->lock);
10293 goto done;
10294 }
10295 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10296 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010297 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010298 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010299
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010300 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010301 struct listnode devices;
10302 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010303 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010304 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010305 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010306 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010307 }
10308
10309 if (ret < 0)
10310 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10311
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010312done:
10313 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10314 audio_extn_auto_hal_release_audio_patch(dev, handle);
10315
10316 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010317 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010318}
10319
10320int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10321{
Derek Chenf13dd492018-11-13 14:53:51 -080010322 int ret = 0;
10323
10324 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10325 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10326 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010327}
10328
10329int adev_set_audio_port_config(struct audio_hw_device *dev,
10330 const struct audio_port_config *config)
10331{
Derek Chenf13dd492018-11-13 14:53:51 -080010332 int ret = 0;
10333
10334 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10335 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10336 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010337}
10338
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010339static int adev_dump(const audio_hw_device_t *device __unused,
10340 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010341{
10342 return 0;
10343}
10344
10345static int adev_close(hw_device_t *device)
10346{
Aalique Grahame22e49102018-12-18 14:23:57 -080010347 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010348 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010349
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010350 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010351 return 0;
10352
10353 pthread_mutex_lock(&adev_init_lock);
10354
10355 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010356 if (audio_extn_spkr_prot_is_enabled())
10357 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010358 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010359 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010360 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010361 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010362 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010363 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010364 audio_extn_utils_release_streams_cfg_lists(
10365 &adev->streams_output_cfg_list,
10366 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010367 if (audio_extn_qap_is_enabled())
10368 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010369 if (audio_extn_qaf_is_enabled())
10370 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010371 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010372 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010373 free(adev->snd_dev_ref_cnt);
10374 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010375 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10376 pcm_params_free(adev->use_case_table[i]);
10377 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010378 if (adev->adm_deinit)
10379 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010380 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010381 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010382 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010383 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010384 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010385 if (adev->device_cfg_params) {
10386 free(adev->device_cfg_params);
10387 adev->device_cfg_params = NULL;
10388 }
Derek Chend2530072014-11-24 12:39:14 -080010389 if(adev->ext_hw_plugin)
10390 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010391 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010392 free_map(adev->patch_map);
10393 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010394 free(device);
10395 adev = NULL;
10396 }
10397 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010398 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010399 return 0;
10400}
10401
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010402/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10403 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10404 * just that it _might_ work.
10405 */
10406static int period_size_is_plausible_for_low_latency(int period_size)
10407{
10408 switch (period_size) {
10409 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010410 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010411 case 240:
10412 case 320:
10413 case 480:
10414 return 1;
10415 default:
10416 return 0;
10417 }
10418}
10419
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010420static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10421{
10422 bool is_snd_card_status = false;
10423 bool is_ext_device_status = false;
10424 char value[32];
10425 int card = -1;
10426 card_status_t status;
10427
10428 if (cookie != adev || !parms)
10429 return;
10430
10431 if (!parse_snd_card_status(parms, &card, &status)) {
10432 is_snd_card_status = true;
10433 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10434 is_ext_device_status = true;
10435 } else {
10436 // not a valid event
10437 return;
10438 }
10439
10440 pthread_mutex_lock(&adev->lock);
10441 if (card == adev->snd_card || is_ext_device_status) {
10442 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010443 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010444 adev->card_status = status;
10445 platform_snd_card_update(adev->platform, status);
10446 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010447 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010448 if (status == CARD_STATUS_OFFLINE)
10449 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010450 } else if (is_ext_device_status) {
10451 platform_set_parameters(adev->platform, parms);
10452 }
10453 }
10454 pthread_mutex_unlock(&adev->lock);
10455 return;
10456}
10457
Weiyin Jiang280ea742020-09-08 20:28:22 +080010458/* adev lock held */
10459int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010460{
10461 struct audio_usecase *uc_info;
10462 float left_p;
10463 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010464 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010465
10466 uc_info = get_usecase_from_list(adev, out->usecase);
10467 if (uc_info == NULL) {
10468 ALOGE("%s: Could not find the usecase (%d) in the list",
10469 __func__, out->usecase);
10470 return -EINVAL;
10471 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010472 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010473
Zhou Songbaddf9f2020-11-20 13:57:39 +080010474 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10475 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010476
10477 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010478 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010479 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010480 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010482 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10483 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010484
10485 if (is_offload_usecase(out->usecase)) {
10486 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010487 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010488 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10489 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10490 } else {
10491 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010492 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010493 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010494 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010495 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010496 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010497 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010498 // mute stream and switch to speaker if suspended
10499 if (!out->a2dp_muted && !out->standby) {
10500 ALOGD("%s: selecting speaker and muting stream", __func__);
10501 assign_devices(&devices, &out->device_list);
10502 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
10503 left_p = out->volume_l;
10504 right_p = out->volume_r;
10505 out->a2dp_muted = true;
10506 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010507 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10508 compress_pause(out->compr);
10509 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010510 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10511 out_set_voip_volume(&out->stream, (float)0, (float)0);
10512 } else {
10513 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10514 /* wait for stale pcm drained before switching to speaker */
10515 uint32_t latency =
10516 (out->config.period_count * out->config.period_size * 1000) /
10517 (out->config.rate);
10518 usleep(latency * 1000);
10519 }
10520 select_devices(adev, out->usecase);
10521 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010522 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10523 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010524 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010525 assign_devices(&out->device_list, &devices);
10526 out->volume_l = left_p;
10527 out->volume_r = right_p;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010528 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010529 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010530 }
10531 ALOGV("%s: exit", __func__);
10532 return 0;
10533}
10534
Haynes Mathew George01156f92018-04-13 15:29:54 -070010535void adev_on_battery_status_changed(bool charging)
10536{
10537 pthread_mutex_lock(&adev->lock);
10538 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10539 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010540 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010541 pthread_mutex_unlock(&adev->lock);
10542}
10543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010544static int adev_open(const hw_module_t *module, const char *name,
10545 hw_device_t **device)
10546{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010547 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010548 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010549 char mixer_ctl_name[128] = {0};
10550 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010551
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010552 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010553 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10554
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010555 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010556 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010557 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010558 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010559 ALOGD("%s: returning existing instance of adev", __func__);
10560 ALOGD("%s: exit", __func__);
10561 pthread_mutex_unlock(&adev_init_lock);
10562 return 0;
10563 }
10564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010565 adev = calloc(1, sizeof(struct audio_device));
10566
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010567 if (!adev) {
10568 pthread_mutex_unlock(&adev_init_lock);
10569 return -ENOMEM;
10570 }
10571
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010572 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10573
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010574 // register audio ext hidl at the earliest
10575 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010576#ifdef DYNAMIC_LOG_ENABLED
10577 register_for_dynamic_logging("hal");
10578#endif
10579
Derek Chenf939fb72018-11-13 13:34:41 -080010580 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010581 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010582 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10583 maj_version = atoi(value);
10584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010585 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010586 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010587 adev->device.common.module = (struct hw_module_t *)module;
10588 adev->device.common.close = adev_close;
10589
10590 adev->device.init_check = adev_init_check;
10591 adev->device.set_voice_volume = adev_set_voice_volume;
10592 adev->device.set_master_volume = adev_set_master_volume;
10593 adev->device.get_master_volume = adev_get_master_volume;
10594 adev->device.set_master_mute = adev_set_master_mute;
10595 adev->device.get_master_mute = adev_get_master_mute;
10596 adev->device.set_mode = adev_set_mode;
10597 adev->device.set_mic_mute = adev_set_mic_mute;
10598 adev->device.get_mic_mute = adev_get_mic_mute;
10599 adev->device.set_parameters = adev_set_parameters;
10600 adev->device.get_parameters = adev_get_parameters;
10601 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10602 adev->device.open_output_stream = adev_open_output_stream;
10603 adev->device.close_output_stream = adev_close_output_stream;
10604 adev->device.open_input_stream = adev_open_input_stream;
10605 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010606 adev->device.create_audio_patch = adev_create_audio_patch;
10607 adev->device.release_audio_patch = adev_release_audio_patch;
10608 adev->device.get_audio_port = adev_get_audio_port;
10609 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010610 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010611 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010612
10613 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010614 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010615 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010616 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010617 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010618 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010619 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010620 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010621 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010622 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010623 /* Init audio and voice feature */
10624 audio_extn_feature_init();
10625 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010626 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010627 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010628 list_init(&adev->active_inputs_list);
10629 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010630 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010631 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10632 audio_extn_utils_hash_eq);
10633 if (!adev->io_streams_map) {
10634 ALOGE("%s: Could not create io streams map", __func__);
10635 ret = -ENOMEM;
10636 goto adev_open_err;
10637 }
10638 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10639 audio_extn_utils_hash_eq);
10640 if (!adev->patch_map) {
10641 ALOGE("%s: Could not create audio patch map", __func__);
10642 ret = -ENOMEM;
10643 goto adev_open_err;
10644 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010645 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010646 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010647 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010648 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010649 adev->perf_lock_opts[0] = 0x101;
10650 adev->perf_lock_opts[1] = 0x20E;
10651 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010652 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010653 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010654 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010655 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010656 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010657
Zhou Song68ebc352019-12-05 17:11:15 +080010658 audio_extn_perf_lock_init();
10659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010660 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010661 adev->platform = platform_init(adev);
10662 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010663 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010664 ret = -EINVAL;
10665 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010666 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010667
Aalique Grahame22e49102018-12-18 14:23:57 -080010668 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010669 if (audio_extn_qap_is_enabled()) {
10670 ret = audio_extn_qap_init(adev);
10671 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010672 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010673 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010674 }
10675 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10676 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10677 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010678
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010679 if (audio_extn_qaf_is_enabled()) {
10680 ret = audio_extn_qaf_init(adev);
10681 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010682 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010683 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010684 }
10685
10686 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10687 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10688 }
10689
Derek Chenae7b0342019-02-08 15:17:04 -080010690 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010691 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10692
Eric Laurentc4aef752013-09-12 17:45:53 -070010693 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10694 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10695 if (adev->visualizer_lib == NULL) {
10696 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10697 } else {
10698 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10699 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010700 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010701 "visualizer_hal_start_output");
10702 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010703 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010704 "visualizer_hal_stop_output");
10705 }
10706 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010707 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010708 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010709 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010710 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010711 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010712 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010713
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010714 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10715 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10716 if (adev->offload_effects_lib == NULL) {
10717 ALOGE("%s: DLOPEN failed for %s", __func__,
10718 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10719 } else {
10720 ALOGV("%s: DLOPEN successful for %s", __func__,
10721 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10722 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010723 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010724 "offload_effects_bundle_hal_start_output");
10725 adev->offload_effects_stop_output =
10726 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10727 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010728 adev->offload_effects_set_hpx_state =
10729 (int (*)(bool))dlsym(adev->offload_effects_lib,
10730 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010731 adev->offload_effects_get_parameters =
10732 (void (*)(struct str_parms *, struct str_parms *))
10733 dlsym(adev->offload_effects_lib,
10734 "offload_effects_bundle_get_parameters");
10735 adev->offload_effects_set_parameters =
10736 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10737 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010738 }
10739 }
10740
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010741 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10742 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10743 if (adev->adm_lib == NULL) {
10744 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10745 } else {
10746 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10747 adev->adm_init = (adm_init_t)
10748 dlsym(adev->adm_lib, "adm_init");
10749 adev->adm_deinit = (adm_deinit_t)
10750 dlsym(adev->adm_lib, "adm_deinit");
10751 adev->adm_register_input_stream = (adm_register_input_stream_t)
10752 dlsym(adev->adm_lib, "adm_register_input_stream");
10753 adev->adm_register_output_stream = (adm_register_output_stream_t)
10754 dlsym(adev->adm_lib, "adm_register_output_stream");
10755 adev->adm_deregister_stream = (adm_deregister_stream_t)
10756 dlsym(adev->adm_lib, "adm_deregister_stream");
10757 adev->adm_request_focus = (adm_request_focus_t)
10758 dlsym(adev->adm_lib, "adm_request_focus");
10759 adev->adm_abandon_focus = (adm_abandon_focus_t)
10760 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010761 adev->adm_set_config = (adm_set_config_t)
10762 dlsym(adev->adm_lib, "adm_set_config");
10763 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10764 dlsym(adev->adm_lib, "adm_request_focus_v2");
10765 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10766 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10767 adev->adm_on_routing_change = (adm_on_routing_change_t)
10768 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010769 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10770 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010771 }
10772 }
10773
Aalique Grahame22e49102018-12-18 14:23:57 -080010774 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010775 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010776 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010777 //initialize this to false for now,
10778 //this will be set to true through set param
10779 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010780
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010781 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010782 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010783
10784 if (k_enable_extended_precision)
10785 adev_verify_devices(adev);
10786
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010787 adev->dsp_bit_width_enforce_mode =
10788 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010789
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010790 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10791 &adev->streams_output_cfg_list,
10792 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010793
Kiran Kandi910e1862013-10-29 13:29:42 -070010794 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010795
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010796 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010797 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010798 trial = atoi(value);
10799 if (period_size_is_plausible_for_low_latency(trial)) {
10800 pcm_config_low_latency.period_size = trial;
10801 pcm_config_low_latency.start_threshold = trial / 4;
10802 pcm_config_low_latency.avail_min = trial / 4;
10803 configured_low_latency_capture_period_size = trial;
10804 }
10805 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010806 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10807 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010808 trial = atoi(value);
10809 if (period_size_is_plausible_for_low_latency(trial)) {
10810 configured_low_latency_capture_period_size = trial;
10811 }
10812 }
10813
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010814 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10815
Eric Laurent4b084132018-10-19 17:33:43 -070010816 adev->camera_orientation = CAMERA_DEFAULT;
10817
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010818 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010819 af_period_multiplier = atoi(value);
10820 if (af_period_multiplier < 0)
10821 af_period_multiplier = 2;
10822 else if (af_period_multiplier > 4)
10823 af_period_multiplier = 4;
10824
10825 ALOGV("new period_multiplier = %d", af_period_multiplier);
10826 }
10827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010828 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010829
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010830 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010831 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010832 pthread_mutex_unlock(&adev_init_lock);
10833
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010834 if (adev->adm_init)
10835 adev->adm_data = adev->adm_init();
10836
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010837 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010838 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010839
10840 audio_extn_snd_mon_init();
10841 pthread_mutex_lock(&adev->lock);
10842 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10843 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010844 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10845 /*
10846 * if the battery state callback happens before charging can be queried,
10847 * it will be guarded with the adev->lock held in the cb function and so
10848 * the callback value will reflect the latest state
10849 */
10850 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010851 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010852 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010853 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010854 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010855 /* Allocate memory for Device config params */
10856 adev->device_cfg_params = (struct audio_device_config_param*)
10857 calloc(platform_get_max_codec_backend(),
10858 sizeof(struct audio_device_config_param));
10859 if (adev->device_cfg_params == NULL)
10860 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010861
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010862 /*
10863 * Check if new PSPD matrix mixer control is supported. If not
10864 * supported, then set flag so that old mixer ctrl is sent while
10865 * sending pspd coefficients on older kernel version. Query mixer
10866 * control for default pcm id and channel value one.
10867 */
10868 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10869 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10870
10871 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10872 if (!ctl) {
10873 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10874 __func__, mixer_ctl_name);
10875 adev->use_old_pspd_mix_ctrl = true;
10876 }
10877
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010878 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010879 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010880
10881adev_open_err:
10882 free_map(adev->patch_map);
10883 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010884 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010885 pthread_mutex_destroy(&adev->lock);
10886 free(adev);
10887 adev = NULL;
10888 *device = NULL;
10889 pthread_mutex_unlock(&adev_init_lock);
10890 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010891}
10892
10893static struct hw_module_methods_t hal_module_methods = {
10894 .open = adev_open,
10895};
10896
10897struct audio_module HAL_MODULE_INFO_SYM = {
10898 .common = {
10899 .tag = HARDWARE_MODULE_TAG,
10900 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10901 .hal_api_version = HARDWARE_HAL_API_VERSION,
10902 .id = AUDIO_HARDWARE_MODULE_ID,
10903 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010904 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010905 .methods = &hal_module_methods,
10906 },
10907};