blob: ab051ca0bb9504bad03f78a5cc7f5985dd6add23 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070097#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070098
Aalique Grahame22e49102018-12-18 14:23:57 -080099#define RECORD_GAIN_MIN 0.0f
100#define RECORD_GAIN_MAX 1.0f
101#define RECORD_VOLUME_CTL_MAX 0x2000
102
103/* treat as unsigned Q1.13 */
104#define APP_TYPE_GAIN_DEFAULT 0x2000
105
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700106#define PROXY_OPEN_RETRY_COUNT 100
107#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800108
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800109#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
110 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
111 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
112#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
113 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800114
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700115#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700116#define DEFAULT_VOIP_BUF_DURATION_MS 20
117#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
118#define DEFAULT_VOIP_SAMP_RATE 48000
119
120#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
121
122struct pcm_config default_pcm_config_voip_copp = {
123 .channels = 1,
124 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
125 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
126 .period_count = 2,
127 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800128 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
129 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700130};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700131
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700132#define MIN_CHANNEL_COUNT 1
133#define DEFAULT_CHANNEL_COUNT 2
134#define MAX_HIFI_CHANNEL_COUNT 8
135
Aalique Grahame22e49102018-12-18 14:23:57 -0800136#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
137#define MAX_CHANNEL_COUNT 1
138#else
139#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
140#define XSTR(x) STR(x)
141#define STR(x) #x
142#endif
143
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700144static unsigned int configured_low_latency_capture_period_size =
145 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
146
Haynes Mathew George16081042017-05-31 17:16:49 -0700147#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
148#define MMAP_PERIOD_COUNT_MIN 32
149#define MMAP_PERIOD_COUNT_MAX 512
150#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
151
Aalique Grahame22e49102018-12-18 14:23:57 -0800152/* This constant enables extended precision handling.
153 * TODO The flag is off until more testing is done.
154 */
155static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700156extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800157
Eric Laurentb23d5282013-05-14 15:27:20 -0700158struct pcm_config pcm_config_deep_buffer = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
162 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165 .stop_threshold = INT_MAX,
166 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
167};
168
169struct pcm_config pcm_config_low_latency = {
170 .channels = 2,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
173 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176 .stop_threshold = INT_MAX,
177 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
178};
179
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800180struct pcm_config pcm_config_haptics_audio = {
181 .channels = 1,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
184 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187 .stop_threshold = INT_MAX,
188 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
189};
190
191struct pcm_config pcm_config_haptics = {
192 .channels = 1,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
195 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .stop_threshold = INT_MAX,
199 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
200};
201
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700202static int af_period_multiplier = 4;
203struct pcm_config pcm_config_rt = {
204 .channels = 2,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = ULL_PERIOD_SIZE, //1 ms
207 .period_count = 512, //=> buffer size is 512ms
208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = ULL_PERIOD_SIZE, //1 ms
214};
215
Eric Laurentb23d5282013-05-14 15:27:20 -0700216struct pcm_config pcm_config_hdmi_multi = {
217 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
218 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
219 .period_size = HDMI_MULTI_PERIOD_SIZE,
220 .period_count = HDMI_MULTI_PERIOD_COUNT,
221 .format = PCM_FORMAT_S16_LE,
222 .start_threshold = 0,
223 .stop_threshold = INT_MAX,
224 .avail_min = 0,
225};
226
Haynes Mathew George16081042017-05-31 17:16:49 -0700227struct pcm_config pcm_config_mmap_playback = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = MMAP_PERIOD_SIZE,
231 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = MMAP_PERIOD_SIZE*8,
234 .stop_threshold = INT32_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = MMAP_PERIOD_SIZE, //1 ms
238};
239
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700240struct pcm_config pcm_config_hifi = {
241 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
242 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
243 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
244 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
245 .format = PCM_FORMAT_S24_3LE,
246 .start_threshold = 0,
247 .stop_threshold = INT_MAX,
248 .avail_min = 0,
249};
250
Eric Laurentb23d5282013-05-14 15:27:20 -0700251struct pcm_config pcm_config_audio_capture = {
252 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
254 .format = PCM_FORMAT_S16_LE,
255};
256
Haynes Mathew George16081042017-05-31 17:16:49 -0700257struct pcm_config pcm_config_mmap_capture = {
258 .channels = 2,
259 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
260 .period_size = MMAP_PERIOD_SIZE,
261 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
262 .format = PCM_FORMAT_S16_LE,
263 .start_threshold = 0,
264 .stop_threshold = INT_MAX,
265 .silence_threshold = 0,
266 .silence_size = 0,
267 .avail_min = MMAP_PERIOD_SIZE, //1 ms
268};
269
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700270#define AFE_PROXY_CHANNEL_COUNT 2
271#define AFE_PROXY_SAMPLING_RATE 48000
272
273#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
274#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
275
276struct pcm_config pcm_config_afe_proxy_playback = {
277 .channels = AFE_PROXY_CHANNEL_COUNT,
278 .rate = AFE_PROXY_SAMPLING_RATE,
279 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
280 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
281 .format = PCM_FORMAT_S16_LE,
282 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283 .stop_threshold = INT_MAX,
284 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
285};
286
287#define AFE_PROXY_RECORD_PERIOD_SIZE 768
288#define AFE_PROXY_RECORD_PERIOD_COUNT 4
289
Aalique Grahame22e49102018-12-18 14:23:57 -0800290struct pcm_config pcm_config_audio_capture_rt = {
291 .channels = 2,
292 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
293 .period_size = ULL_PERIOD_SIZE,
294 .period_count = 512,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = 0,
297 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
298 .silence_threshold = 0,
299 .silence_size = 0,
300 .avail_min = ULL_PERIOD_SIZE, //1 ms
301};
302
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700303struct pcm_config pcm_config_afe_proxy_record = {
304 .channels = AFE_PROXY_CHANNEL_COUNT,
305 .rate = AFE_PROXY_SAMPLING_RATE,
306 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
307 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
308 .format = PCM_FORMAT_S16_LE,
309 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
310 .stop_threshold = INT_MAX,
311 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
312};
313
Ashish Jainf1eaa582016-05-23 20:54:24 +0530314#define AUDIO_MAX_PCM_FORMATS 7
315
316const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
317 [AUDIO_FORMAT_DEFAULT] = 0,
318 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
319 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
320 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
323 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
324};
325
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800326const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700327 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
328 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800329 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700330 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
331 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700333 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700342 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
343 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700344 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800345 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700346
Eric Laurentb23d5282013-05-14 15:27:20 -0700347 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700348 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530349 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
350 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
351 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530352 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
353 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700355 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700357 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800359 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800360 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400361 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
362 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700363
Derek Chenf7092792017-05-23 12:23:53 -0400364 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700365 [USECASE_VOICE2_CALL] = "voice2-call",
366 [USECASE_VOLTE_CALL] = "volte-call",
367 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800368 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800369 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
370 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800371 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700372 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
373 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800375 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
376 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
377 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
378
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700379 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
380 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700381 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
382 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700383
384 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
385 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530386 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530388 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530389 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
390 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700391
392 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
393 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530394 /* For Interactive Audio Streams */
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700403
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800404 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
405
Derek Chenf6318be2017-06-12 17:16:24 -0400406 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
407
408 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
409 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
410 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
411 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700412 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530413 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700414};
415
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700416static const audio_usecase_t offload_usecases[] = {
417 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700418 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427
Varun Balaraje49253e2017-07-06 19:48:56 +0530428static const audio_usecase_t interactive_usecases[] = {
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
437};
438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439#define STRING_TO_ENUM(string) { #string, string }
440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441struct string_to_enum {
442 const char *name;
443 uint32_t value;
444};
445
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700446static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466};
467
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700468static const struct string_to_enum formats_name_to_enum_table[] = {
469 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700472 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
473 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700475 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
477 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700478 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800479};
480
481//list of all supported sample rates by HDMI specification.
482static const int out_hdmi_sample_rates[] = {
483 32000, 44100, 48000, 88200, 96000, 176400, 192000,
484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800487 STRING_TO_ENUM(32000),
488 STRING_TO_ENUM(44100),
489 STRING_TO_ENUM(48000),
490 STRING_TO_ENUM(88200),
491 STRING_TO_ENUM(96000),
492 STRING_TO_ENUM(176400),
493 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800494 STRING_TO_ENUM(352800),
495 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700496};
497
Carter Hsu2e429db2019-05-14 18:50:52 +0800498struct in_effect_list {
499 struct listnode list;
500 effect_handle_t handle;
501};
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700504static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700505static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700506//cache last MBDRC cal step level
507static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700508
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530509static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
510static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700511static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800512static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530513static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530514
Derek Chen6f293672019-04-01 01:40:24 -0700515static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
516static void in_snd_mon_cb(void * stream, struct str_parms * parms);
517static void out_snd_mon_cb(void * stream, struct str_parms * parms);
518
Zhou Song331c8e52019-08-26 14:16:12 +0800519static int configure_btsco_sample_rate(snd_device_t snd_device);
520
Vatsal Buchac09ae062018-11-14 13:25:08 +0530521#ifdef AUDIO_FEATURE_ENABLED_GCOV
522extern void __gcov_flush();
523static void enable_gcov()
524{
525 __gcov_flush();
526}
527#else
528static void enable_gcov()
529{
530}
531#endif
532
justinweng20fb6d82019-02-21 18:49:00 -0700533static int in_set_microphone_direction(const struct audio_stream_in *stream,
534 audio_microphone_direction_t dir);
535static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
536
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700537static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
538 int flags __unused)
539{
540 int dir = 0;
541 switch (uc_id) {
542 case USECASE_AUDIO_RECORD_LOW_LATENCY:
543 dir = 1;
544 case USECASE_AUDIO_PLAYBACK_ULL:
545 break;
546 default:
547 return false;
548 }
549
550 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
551 PCM_PLAYBACK : PCM_CAPTURE);
552 if (adev->adm_is_noirq_avail)
553 return adev->adm_is_noirq_avail(adev->adm_data,
554 adev->snd_card, dev_id, dir);
555 return false;
556}
557
558static void register_out_stream(struct stream_out *out)
559{
560 struct audio_device *adev = out->dev;
561 if (is_offload_usecase(out->usecase) ||
562 !adev->adm_register_output_stream)
563 return;
564
565 // register stream first for backward compatibility
566 adev->adm_register_output_stream(adev->adm_data,
567 out->handle,
568 out->flags);
569
570 if (!adev->adm_set_config)
571 return;
572
573 if (out->realtime)
574 adev->adm_set_config(adev->adm_data,
575 out->handle,
576 out->pcm, &out->config);
577}
578
579static void register_in_stream(struct stream_in *in)
580{
581 struct audio_device *adev = in->dev;
582 if (!adev->adm_register_input_stream)
583 return;
584
585 adev->adm_register_input_stream(adev->adm_data,
586 in->capture_handle,
587 in->flags);
588
589 if (!adev->adm_set_config)
590 return;
591
592 if (in->realtime)
593 adev->adm_set_config(adev->adm_data,
594 in->capture_handle,
595 in->pcm,
596 &in->config);
597}
598
599static void request_out_focus(struct stream_out *out, long ns)
600{
601 struct audio_device *adev = out->dev;
602
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700603 if (adev->adm_request_focus_v2)
604 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
605 else if (adev->adm_request_focus)
606 adev->adm_request_focus(adev->adm_data, out->handle);
607}
608
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700609static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700610{
611 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700612 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614 if (adev->adm_request_focus_v2_1)
615 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
616 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
618 else if (adev->adm_request_focus)
619 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620
621 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622}
623
624static void release_out_focus(struct stream_out *out)
625{
626 struct audio_device *adev = out->dev;
627
628 if (adev->adm_abandon_focus)
629 adev->adm_abandon_focus(adev->adm_data, out->handle);
630}
631
632static void release_in_focus(struct stream_in *in)
633{
634 struct audio_device *adev = in->dev;
635 if (adev->adm_abandon_focus)
636 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
637}
638
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530639static int parse_snd_card_status(struct str_parms *parms, int *card,
640 card_status_t *status)
641{
642 char value[32]={0};
643 char state[32]={0};
644
645 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
646 if (ret < 0)
647 return -1;
648
649 // sscanf should be okay as value is of max length 32.
650 // same as sizeof state.
651 if (sscanf(value, "%d,%s", card, state) < 2)
652 return -1;
653
654 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
655 CARD_STATUS_OFFLINE;
656 return 0;
657}
658
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700659static inline void adjust_frames_for_device_delay(struct stream_out *out,
660 uint32_t *dsp_frames) {
661 // Adjustment accounts for A2dp encoder latency with offload usecases
662 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800663 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700664 unsigned long offset =
665 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
666 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
667 }
668}
669
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700670static inline bool free_entry(void *key __unused,
671 void *value, void *context __unused)
672{
673 free(value);
674 return true;
675}
676
677static inline void free_map(Hashmap *map)
678{
679 if (map) {
680 hashmapForEach(map, free_entry, (void *) NULL);
681 hashmapFree(map);
682 }
683}
684
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800685static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700686 audio_patch_handle_t patch_handle)
687{
688 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
689 return;
690
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700691 struct audio_patch_info *p_info =
692 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
693 if (p_info) {
694 ALOGV("%s: Remove patch %d", __func__, patch_handle);
695 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
696 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 free(p_info);
698 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699}
700
701static inline int io_streams_map_insert(struct audio_device *adev,
702 struct audio_stream *stream,
703 audio_io_handle_t handle,
704 audio_patch_handle_t patch_handle)
705{
706 struct audio_stream_info *s_info =
707 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
708
709 if (s_info == NULL) {
710 ALOGE("%s: Could not allocate stream info", __func__);
711 return -ENOMEM;
712 }
713 s_info->stream = stream;
714 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715
716 pthread_mutex_lock(&adev->lock);
717 struct audio_stream_info *stream_info =
718 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719 if (stream_info != NULL)
720 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800721 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700722 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
723 return 0;
724}
725
726static inline void io_streams_map_remove(struct audio_device *adev,
727 audio_io_handle_t handle)
728{
729 pthread_mutex_lock(&adev->lock);
730 struct audio_stream_info *s_info =
731 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700732 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800733 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800735 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737done:
738 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700739 return;
740}
741
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 audio_patch_handle_t handle)
744{
745 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 p_info = (struct audio_patch_info *)
747 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return p_info;
749}
750
vivek mehtaa76401a2015-04-24 14:12:15 -0700751__attribute__ ((visibility ("default")))
752bool audio_hw_send_gain_dep_calibration(int level) {
753 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700754 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700755
756 pthread_mutex_lock(&adev_init_lock);
757
758 if (adev != NULL && adev->platform != NULL) {
759 pthread_mutex_lock(&adev->lock);
760 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700761
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530762 // cache level info for any of the use case which
763 // was not started.
764 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
vivek mehtaa76401a2015-04-24 14:12:15 -0700766 pthread_mutex_unlock(&adev->lock);
767 } else {
768 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
769 }
770
771 pthread_mutex_unlock(&adev_init_lock);
772
773 return ret_val;
774}
775
Ashish Jain5106d362016-05-11 19:23:33 +0530776static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
777{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800778 bool gapless_enabled = false;
779 const char *mixer_ctl_name = "Compress Gapless Playback";
780 struct mixer_ctl *ctl;
781
782 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700783 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530784
785 /*Disable gapless if its AV playback*/
786 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787
788 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
789 if (!ctl) {
790 ALOGE("%s: Could not get ctl for mixer cmd - %s",
791 __func__, mixer_ctl_name);
792 return -EINVAL;
793 }
794
795 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
796 ALOGE("%s: Could not set gapless mode %d",
797 __func__, gapless_enabled);
798 return -EINVAL;
799 }
800 return 0;
801}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700802
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700803__attribute__ ((visibility ("default")))
804int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
805 int table_size) {
806 int ret_val = 0;
807 ALOGV("%s: enter ... ", __func__);
808
809 pthread_mutex_lock(&adev_init_lock);
810 if (adev == NULL) {
811 ALOGW("%s: adev is NULL .... ", __func__);
812 goto done;
813 }
814
815 pthread_mutex_lock(&adev->lock);
816 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
817 pthread_mutex_unlock(&adev->lock);
818done:
819 pthread_mutex_unlock(&adev_init_lock);
820 ALOGV("%s: exit ... ", __func__);
821 return ret_val;
822}
823
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800824bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800825{
826 bool ret = false;
827 ALOGV("%s: enter ...", __func__);
828
829 pthread_mutex_lock(&adev_init_lock);
830
831 if (adev != NULL && adev->platform != NULL) {
832 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800834 pthread_mutex_unlock(&adev->lock);
835 }
836
837 pthread_mutex_unlock(&adev_init_lock);
838
839 ALOGV("%s: exit with ret %d", __func__, ret);
840 return ret;
841}
Aalique Grahame22e49102018-12-18 14:23:57 -0800842
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700843static bool is_supported_format(audio_format_t format)
844{
Eric Laurent86e17132013-09-12 17:49:30 -0700845 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530846 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530847 format == AUDIO_FORMAT_AAC_LC ||
848 format == AUDIO_FORMAT_AAC_HE_V1 ||
849 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530850 format == AUDIO_FORMAT_AAC_ADTS_LC ||
851 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
852 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530853 format == AUDIO_FORMAT_AAC_LATM_LC ||
854 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
855 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530856 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
857 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530858 format == AUDIO_FORMAT_PCM_FLOAT ||
859 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700860 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530861 format == AUDIO_FORMAT_AC3 ||
862 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700863 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530864 format == AUDIO_FORMAT_DTS ||
865 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800866 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530867 format == AUDIO_FORMAT_ALAC ||
868 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530869 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530870 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800871 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530872 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700873 format == AUDIO_FORMAT_APTX ||
874 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800875 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700876
877 return false;
878}
879
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700880static inline bool is_mmap_usecase(audio_usecase_t uc_id)
881{
882 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
883 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
884}
885
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700886static inline bool is_valid_volume(float left, float right)
887{
888 return ((left >= 0.0f && right >= 0.0f) ? true : false);
889}
890
Avinash Vaish71a8b972014-07-24 15:36:33 +0530891static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
892 struct audio_usecase *uc_info)
893{
894 struct listnode *node;
895 struct audio_usecase *usecase;
896
897 if (uc_info == NULL)
898 return -EINVAL;
899
900 /* Re-route all voice usecases on the shared backend other than the
901 specified usecase to new snd devices */
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800904 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530905 enable_audio_route(adev, usecase);
906 }
907 return 0;
908}
909
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530910static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530911{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530912 ALOGV("%s", __func__);
913 audio_route_apply_and_update_path(adev->audio_route,
914 "asrc-mode");
915 adev->asrc_mode_enabled = true;
916}
917
918static void disable_asrc_mode(struct audio_device *adev)
919{
920 ALOGV("%s", __func__);
921 audio_route_reset_and_update_path(adev->audio_route,
922 "asrc-mode");
923 adev->asrc_mode_enabled = false;
924}
925
926/*
927 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
928 * 44.1 or Native DSD backends are enabled for any of current use case.
929 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
930 * - Disable current mix path use case(Headphone backend) and re-enable it with
931 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
932 * e.g. Naitve DSD or Headphone 44.1 -> + 48
933 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530934static void check_and_set_asrc_mode(struct audio_device *adev,
935 struct audio_usecase *uc_info,
936 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530937{
938 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939 int i, num_new_devices = 0;
940 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
941 /*
942 *Split snd device for new combo use case
943 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
944 */
945 if (platform_split_snd_device(adev->platform,
946 snd_device,
947 &num_new_devices,
948 split_new_snd_devices) == 0) {
949 for (i = 0; i < num_new_devices; i++)
950 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
951 } else {
952 int new_backend_idx = platform_get_backend_index(snd_device);
953 if (((new_backend_idx == HEADPHONE_BACKEND) ||
954 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
955 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
956 !adev->asrc_mode_enabled) {
957 struct listnode *node = NULL;
958 struct audio_usecase *uc = NULL;
959 struct stream_out *curr_out = NULL;
960 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
961 int i, num_devices, ret = 0;
962 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530963
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530964 list_for_each(node, &adev->usecase_list) {
965 uc = node_to_item(node, struct audio_usecase, list);
966 curr_out = (struct stream_out*) uc->stream.out;
967 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
968 /*
969 *Split snd device for existing combo use case
970 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
971 */
972 ret = platform_split_snd_device(adev->platform,
973 uc->out_snd_device,
974 &num_devices,
975 split_snd_devices);
976 if (ret < 0 || num_devices == 0) {
977 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
978 split_snd_devices[0] = uc->out_snd_device;
979 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800980 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530981 for (i = 0; i < num_devices; i++) {
982 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
983 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
984 if((new_backend_idx == HEADPHONE_BACKEND) &&
985 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
986 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
987 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
988 __func__);
989 enable_asrc_mode(adev);
990 break;
991 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
992 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
993 (usecase_backend_idx == HEADPHONE_BACKEND)) {
994 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
995 __func__);
996 disable_audio_route(adev, uc);
997 disable_snd_device(adev, uc->out_snd_device);
998 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
999 if (new_backend_idx == DSD_NATIVE_BACKEND)
1000 audio_route_apply_and_update_path(adev->audio_route,
1001 "hph-true-highquality-mode");
1002 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1003 (curr_out->bit_width >= 24))
1004 audio_route_apply_and_update_path(adev->audio_route,
1005 "hph-highquality-mode");
1006 enable_asrc_mode(adev);
1007 enable_snd_device(adev, uc->out_snd_device);
1008 enable_audio_route(adev, uc);
1009 break;
1010 }
1011 }
1012 // reset split devices count
1013 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001014 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301015 if (adev->asrc_mode_enabled)
1016 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301017 }
1018 }
1019 }
1020}
1021
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001022static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1023 struct audio_effect_config effect_config,
1024 unsigned int param_value)
1025{
1026 char mixer_ctl_name[] = "Audio Effect";
1027 struct mixer_ctl *ctl;
1028 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001029 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001030
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001031 if (in == NULL) {
1032 ALOGE("%s: active input stream is NULL", __func__);
1033 return -EINVAL;
1034 }
1035
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001036 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1037 if (!ctl) {
1038 ALOGE("%s: Could not get mixer ctl - %s",
1039 __func__, mixer_ctl_name);
1040 return -EINVAL;
1041 }
1042
1043 set_values[0] = 1; //0:Rx 1:Tx
1044 set_values[1] = in->app_type_cfg.app_type;
1045 set_values[2] = (long)effect_config.module_id;
1046 set_values[3] = (long)effect_config.instance_id;
1047 set_values[4] = (long)effect_config.param_id;
1048 set_values[5] = param_value;
1049
1050 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1051
1052 return 0;
1053
1054}
1055
1056static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1057 int effect_type, unsigned int *param_value)
1058{
1059 int ret = 0;
1060 struct audio_effect_config other_effect_config;
1061 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001062 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001063
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001064 if (in == NULL) {
1065 ALOGE("%s: active input stream is NULL", __func__);
1066 return -EINVAL;
1067 }
1068
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069 usecase = get_usecase_from_list(adev, in->usecase);
1070 if (!usecase)
1071 return -EINVAL;
1072
1073 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1074 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1075 if (ret < 0) {
1076 ALOGE("%s Failed to get effect params %d", __func__, ret);
1077 return ret;
1078 }
1079
1080 if (module_id == other_effect_config.module_id) {
1081 //Same module id for AEC/NS. Values need to be combined
1082 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1083 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1084 *param_value |= other_effect_config.param_value;
1085 }
1086 }
1087
1088 return ret;
1089}
1090
1091static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301092{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 struct audio_effect_config effect_config;
1094 struct audio_usecase *usecase = NULL;
1095 int ret = 0;
1096 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001097 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001099 if(!voice_extn_is_dynamic_ecns_enabled())
1100 return ENOSYS;
1101
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 if (!in) {
1103 ALOGE("%s: Invalid input stream", __func__);
1104 return -EINVAL;
1105 }
1106
1107 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1108
1109 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001110 if (usecase == NULL) {
1111 ALOGE("%s: Could not find the usecase (%d) in the list",
1112 __func__, in->usecase);
1113 return -EINVAL;
1114 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001115
1116 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1117 if (ret < 0) {
1118 ALOGE("%s Failed to get module id %d", __func__, ret);
1119 return ret;
1120 }
1121 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1122 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1123
1124 if(enable)
1125 param_value = effect_config.param_value;
1126
1127 /*Special handling for AEC & NS effects Param values need to be
1128 updated if module ids are same*/
1129
1130 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1131 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1132 if (ret < 0)
1133 return ret;
1134 }
1135
1136 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1137
1138 return ret;
1139}
1140
1141static void check_and_enable_effect(struct audio_device *adev)
1142{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001143 if(!voice_extn_is_dynamic_ecns_enabled())
1144 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001145
Eric Laurent637e2d42018-11-15 12:24:31 -08001146 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Eric Laurent637e2d42018-11-15 12:24:31 -08001148 if (in != NULL && !in->standby) {
1149 if (in->enable_aec)
1150 enable_disable_effect(adev, EFFECT_AEC, true);
1151
1152 if (in->enable_ns &&
1153 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1154 enable_disable_effect(adev, EFFECT_NS, true);
1155 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156 }
1157}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001159int pcm_ioctl(struct pcm *pcm, int request, ...)
1160{
1161 va_list ap;
1162 void * arg;
1163 int pcm_fd = *(int*)pcm;
1164
1165 va_start(ap, request);
1166 arg = va_arg(ap, void *);
1167 va_end(ap);
1168
1169 return ioctl(pcm_fd, request, arg);
1170}
1171
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001172int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001173 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001176 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301177 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301178 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001179 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301180 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001181
1182 if (usecase == NULL)
1183 return -EINVAL;
1184
1185 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1186
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 if (usecase->type == PCM_CAPTURE) {
1188 struct stream_in *in = usecase->stream.in;
1189 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001191
1192 if (in) {
1193 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001194 list_init(&out_devices);
1195 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 struct listnode *node;
1197 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1198 USECASE_AUDIO_PLAYBACK_VOIP);
1199 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001200 assign_devices(&out_devices,
1201 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001202 } else if (adev->primary_output &&
1203 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001204 assign_devices(&out_devices,
1205 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001206 } else {
1207 list_for_each(node, &adev->usecase_list) {
1208 uinfo = node_to_item(node, struct audio_usecase, list);
1209 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001210 assign_devices(&out_devices,
1211 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 break;
1213 }
1214 }
1215 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216
1217 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 in->ec_opened = true;
1219 }
1220 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001221 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1222 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1223 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 snd_device = usecase->in_snd_device;
1225 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001228
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001229#ifdef DS1_DOLBY_DAP_ENABLED
1230 audio_extn_dolby_set_dmid(adev);
1231 audio_extn_dolby_set_endpoint(adev);
1232#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001233 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001234 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301235 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001236 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001237 if (audio_extn_is_maxx_audio_enabled())
1238 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301239 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301240 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1241 out = usecase->stream.out;
1242 if (out && out->compr)
1243 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1244 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301245
1246 if (usecase->type == PCM_CAPTURE) {
1247 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001248 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301249 ALOGD("%s: set custom mtmx params v1", __func__);
1250 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1251 }
1252 } else {
1253 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1254 }
Manish Dewangan58229382017-02-02 15:48:41 +05301255
Andy Hung756ecc12018-10-19 17:47:12 -07001256 // we shouldn't truncate mixer_path
1257 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1258 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1259 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001260 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001261 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301262 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1263 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1264 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1265 if (parms) {
1266 audio_extn_fm_set_parameters(adev, parms);
1267 str_parms_destroy(parms);
1268 }
1269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 ALOGV("%s: exit", __func__);
1271 return 0;
1272}
1273
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001274int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001275 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001278 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301279 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001280
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301281 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001282 return -EINVAL;
1283
1284 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301285 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 snd_device = usecase->in_snd_device;
1287 else
1288 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001289 // we shouldn't truncate mixer_path
1290 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1291 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1292 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001293 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001294 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001295 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001296 if (usecase->type == PCM_CAPTURE) {
1297 struct stream_in *in = usecase->stream.in;
1298 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001299 struct listnode out_devices;
1300 list_init(&out_devices);
1301 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001302 in->ec_opened = false;
1303 }
1304 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001305 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301306 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301307
1308 if (usecase->type == PCM_CAPTURE) {
1309 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001310 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301311 ALOGD("%s: reset custom mtmx params v1", __func__);
1312 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1313 }
1314 } else {
1315 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1316 }
1317
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001318 if ((usecase->type == PCM_PLAYBACK) &&
1319 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301320 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322 ALOGV("%s: exit", __func__);
1323 return 0;
1324}
1325
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001326int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001327 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001328{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301329 int i, num_devices = 0;
1330 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001331 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1332
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001333 if (snd_device < SND_DEVICE_MIN ||
1334 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001335 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001336 return -EINVAL;
1337 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001339 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001340 ALOGE("%s: Invalid sound device returned", __func__);
1341 return -EINVAL;
1342 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001343
1344 adev->snd_dev_ref_cnt[snd_device]++;
1345
1346 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1347 (platform_split_snd_device(adev->platform,
1348 snd_device,
1349 &num_devices,
1350 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001351 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001352 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353 return 0;
1354 }
1355
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001356 if (audio_extn_spkr_prot_is_enabled())
1357 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001358
Aalique Grahame22e49102018-12-18 14:23:57 -08001359 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1360
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001361 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1362 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001363 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1364 goto err;
1365 }
1366 audio_extn_dev_arbi_acquire(snd_device);
1367 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001368 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001369 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001370 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001371 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001372 } else if (platform_split_snd_device(adev->platform,
1373 snd_device,
1374 &num_devices,
1375 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301376 for (i = 0; i < num_devices; i++) {
1377 enable_snd_device(adev, new_snd_devices[i]);
1378 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001379 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001380 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001381 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301382
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301383
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1385 (audio_extn_a2dp_start_playback() < 0)) {
1386 ALOGE(" fail to configure A2dp Source control path ");
1387 goto err;
1388 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001389
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001390 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1391 (audio_extn_a2dp_start_capture() < 0)) {
1392 ALOGE(" fail to configure A2dp Sink control path ");
1393 goto err;
1394 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301395
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001396 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1397 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1398 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1399 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1400 ALOGE(" fail to configure sco control path ");
1401 goto err;
1402 }
Zhou Song12c29502019-03-16 10:37:18 +08001403 }
1404
Zhou Song331c8e52019-08-26 14:16:12 +08001405 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001406 /* due to the possibility of calibration overwrite between listen
1407 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001408 audio_extn_sound_trigger_update_device_status(snd_device,
1409 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301410 audio_extn_listen_update_device_status(snd_device,
1411 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001412 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001417 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001418 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001419 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001420 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421
1422 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1423 !adev->native_playback_enabled &&
1424 audio_is_true_native_stream_active(adev)) {
1425 ALOGD("%s: %d: napb: enabling native mode in hardware",
1426 __func__, __LINE__);
1427 audio_route_apply_and_update_path(adev->audio_route,
1428 "true-native-mode");
1429 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301430 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301431 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1432 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001433 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001434 ALOGD("%s: init ec ref loopback", __func__);
1435 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001439err:
1440 adev->snd_dev_ref_cnt[snd_device]--;
1441 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442}
1443
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001444int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001445 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301447 int i, num_devices = 0;
1448 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001449 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1450
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001451 if (snd_device < SND_DEVICE_MIN ||
1452 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001453 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 return -EINVAL;
1455 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001456
1457 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1458 ALOGE("%s: Invalid sound device returned", __func__);
1459 return -EINVAL;
1460 }
1461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1463 ALOGE("%s: device ref cnt is already 0", __func__);
1464 return -EINVAL;
1465 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001468
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001469
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001471 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301472
Aalique Grahame22e49102018-12-18 14:23:57 -08001473 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1474
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001475 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1476 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001477 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001478
1479 // when speaker device is disabled, reset swap.
1480 // will be renabled on usecase start
1481 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001482 } else if (platform_split_snd_device(adev->platform,
1483 snd_device,
1484 &num_devices,
1485 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 for (i = 0; i < num_devices; i++) {
1487 disable_snd_device(adev, new_snd_devices[i]);
1488 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001489 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001490 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001491 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001492 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001493
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301495 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001496 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001497 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001498 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301500 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301502 adev->native_playback_enabled) {
1503 ALOGD("%s: %d: napb: disabling native mode in hardware",
1504 __func__, __LINE__);
1505 audio_route_reset_and_update_path(adev->audio_route,
1506 "true-native-mode");
1507 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001508 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301509 adev->asrc_mode_enabled) {
1510 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301511 disable_asrc_mode(adev);
1512 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301514 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001515 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001516 ALOGD("%s: deinit ec ref loopback", __func__);
1517 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1518 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001519
1520 audio_extn_utils_release_snd_device(snd_device);
1521 } else {
1522 if (platform_split_snd_device(adev->platform,
1523 snd_device,
1524 &num_devices,
1525 new_snd_devices) == 0) {
1526 for (i = 0; i < num_devices; i++) {
1527 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1528 }
1529 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 return 0;
1533}
1534
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001535/*
1536 legend:
1537 uc - existing usecase
1538 new_uc - new usecase
1539 d1, d11, d2 - SND_DEVICE enums
1540 a1, a2 - corresponding ANDROID device enums
1541 B1, B2 - backend strings
1542
1543case 1
1544 uc->dev d1 (a1) B1
1545 new_uc->dev d1 (a1), d2 (a2) B1, B2
1546
1547 resolution: disable and enable uc->dev on d1
1548
1549case 2
1550 uc->dev d1 (a1) B1
1551 new_uc->dev d11 (a1) B1
1552
1553 resolution: need to switch uc since d1 and d11 are related
1554 (e.g. speaker and voice-speaker)
1555 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1556
1557case 3
1558 uc->dev d1 (a1) B1
1559 new_uc->dev d2 (a2) B2
1560
1561 resolution: no need to switch uc
1562
1563case 4
1564 uc->dev d1 (a1) B1
1565 new_uc->dev d2 (a2) B1
1566
1567 resolution: disable enable uc-dev on d2 since backends match
1568 we cannot enable two streams on two different devices if they
1569 share the same backend. e.g. if offload is on speaker device using
1570 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1571 using the same backend, offload must also be switched to voice-handset.
1572
1573case 5
1574 uc->dev d1 (a1) B1
1575 new_uc->dev d1 (a1), d2 (a2) B1
1576
1577 resolution: disable enable uc-dev on d2 since backends match
1578 we cannot enable two streams on two different devices if they
1579 share the same backend.
1580
1581case 6
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d2 (a1) B2
1584
1585 resolution: no need to switch
1586
1587case 7
1588 uc->dev d1 (a1), d2 (a2) B1, B2
1589 new_uc->dev d1 (a1) B1
1590
1591 resolution: no need to switch
1592
Zhou Song4ba65882018-07-09 14:48:07 +08001593case 8
1594 uc->dev d1 (a1) B1
1595 new_uc->dev d11 (a1), d2 (a2) B1, B2
1596 resolution: compared to case 1, for this case, d1 and d11 are related
1597 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001598*/
1599static snd_device_t derive_playback_snd_device(void * platform,
1600 struct audio_usecase *uc,
1601 struct audio_usecase *new_uc,
1602 snd_device_t new_snd_device)
1603{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001604 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001605
1606 snd_device_t d1 = uc->out_snd_device;
1607 snd_device_t d2 = new_snd_device;
1608
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 list_init(&a1);
1610 list_init(&a2);
1611
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301612 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301613 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1615 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301616 break;
1617 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001618 assign_devices(&a1, &uc->stream.out->device_list);
1619 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301620 break;
1621 }
1622
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001623 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001624 if (!compare_devices(&a1, &a2) &&
1625 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001626 snd_device_t d3[2];
1627 int num_devices = 0;
1628 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001630 &num_devices,
1631 d3);
1632 if (ret < 0) {
1633 if (ret != -ENOSYS) {
1634 ALOGW("%s failed to split snd_device %d",
1635 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001636 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001637 }
1638 goto end;
1639 }
1640
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001641 if (platform_check_backends_match(d3[0], d3[1])) {
1642 return d2; // case 5
1643 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001644 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301645 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001646 // check if d1 is related to any of d3's
1647 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001648 return d1; // case 1
1649 else
1650 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001651 }
1652 } else {
1653 if (platform_check_backends_match(d1, d2)) {
1654 return d2; // case 2, 4
1655 } else {
1656 return d1; // case 6, 3
1657 }
1658 }
1659
1660end:
1661 return d2; // return whatever was calculated before.
1662}
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301665 struct audio_usecase *uc_info,
1666 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667{
1668 struct listnode *node;
1669 struct audio_usecase *usecase;
1670 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301671 snd_device_t uc_derive_snd_device;
1672 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001673 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1674 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001675 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301676 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 /*
1678 * This function is to make sure that all the usecases that are active on
1679 * the hardware codec backend are always routed to any one device that is
1680 * handled by the hardware codec.
1681 * For example, if low-latency and deep-buffer usecases are currently active
1682 * on speaker and out_set_parameters(headset) is received on low-latency
1683 * output, then we have to make sure deep-buffer is also switched to headset,
1684 * because of the limitation that both the devices cannot be enabled
1685 * at the same time as they share the same backend.
1686 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001687 /*
1688 * This call is to check if we need to force routing for a particular stream
1689 * If there is a backend configuration change for the device when a
1690 * new stream starts, then ADM needs to be closed and re-opened with the new
1691 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001692 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001693 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001694 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1695 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301696 /* For a2dp device reconfigure all active sessions
1697 * with new AFE encoder format based on a2dp state
1698 */
1699 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1700 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1701 audio_extn_a2dp_is_force_device_switch()) {
1702 force_routing = true;
1703 force_restart_session = true;
1704 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301705 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1706
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001708 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001709 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1711 switch_device[i] = false;
1712
1713 list_for_each(node, &adev->usecase_list) {
1714 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001715
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301716 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1717 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301718 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301719 platform_get_snd_device_name(usecase->out_snd_device),
1720 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301721 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1722 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301723 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1724 usecase, uc_info, snd_device);
1725 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001726 (is_codec_backend_out_device_type(&usecase->device_list) ||
1727 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1728 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1730 is_a2dp_out_device_type(&usecase->device_list) ||
1731 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301732 ((force_restart_session) ||
1733 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301734 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1735 __func__, use_case_table[usecase->id],
1736 platform_get_snd_device_name(usecase->out_snd_device));
1737 disable_audio_route(adev, usecase);
1738 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301739 /* Enable existing usecase on derived playback device */
1740 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301741 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001743 }
1744 }
1745
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301746 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1747 num_uc_to_switch);
1748
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001750 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301752 /* Make sure the previous devices to be disabled first and then enable the
1753 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 list_for_each(node, &adev->usecase_list) {
1755 usecase = node_to_item(node, struct audio_usecase, list);
1756 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001757 /* Check if output sound device to be switched can be split and if any
1758 of the split devices match with derived sound device */
1759 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1760 &num_devices, split_snd_devices) == 0) {
1761 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1762 for (i = 0; i < num_devices; i++) {
1763 /* Disable devices that do not match with derived sound device */
1764 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1765 disable_snd_device(adev, split_snd_devices[i]);
1766 }
1767 } else {
1768 disable_snd_device(adev, usecase->out_snd_device);
1769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 }
1771 }
1772
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
1775 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001776 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1777 &num_devices, split_snd_devices) == 0) {
1778 /* Enable derived sound device only if it does not match with
1779 one of the split sound devices. This is because the matching
1780 sound device was not disabled */
1781 bool should_enable = true;
1782 for (i = 0; i < num_devices; i++) {
1783 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1784 should_enable = false;
1785 break;
1786 }
1787 }
1788 if (should_enable)
1789 enable_snd_device(adev, derive_snd_device[usecase->id]);
1790 } else {
1791 enable_snd_device(adev, derive_snd_device[usecase->id]);
1792 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001793 }
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796 /* Re-route all the usecases on the shared backend other than the
1797 specified usecase to new snd devices */
1798 list_for_each(node, &adev->usecase_list) {
1799 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301800 /* Update the out_snd_device only before enabling the audio route */
1801 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301802 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301803 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301804 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 use_case_table[usecase->id],
1806 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001807 /* Update voc calibration before enabling VoIP route */
1808 if (usecase->type == VOIP_CALL)
1809 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001810 usecase->out_snd_device,
1811 platform_get_input_snd_device(
1812 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301813 &uc_info->device_list,
1814 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301815 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301816 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001817 out_set_voip_volume(&usecase->stream.out->stream,
1818 usecase->stream.out->volume_l,
1819 usecase->stream.out->volume_r);
1820 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 }
1823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 }
1825}
1826
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301827static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001828 struct audio_usecase *uc_info,
1829 snd_device_t snd_device)
1830{
1831 struct listnode *node;
1832 struct audio_usecase *usecase;
1833 bool switch_device[AUDIO_USECASE_MAX];
1834 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001835 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001836 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001837
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301838 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1839 snd_device);
1840 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301841
1842 /*
1843 * Make sure out devices is checked against out codec backend device and
1844 * also in devices against in codec backend. Checking out device against in
1845 * codec backend or vice versa causes issues.
1846 */
1847 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001848 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001849 /*
1850 * This function is to make sure that all the active capture usecases
1851 * are always routed to the same input sound device.
1852 * For example, if audio-record and voice-call usecases are currently
1853 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1854 * is received for voice call then we have to make sure that audio-record
1855 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1856 * because of the limitation that two devices cannot be enabled
1857 * at the same time if they share the same backend.
1858 */
1859 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1860 switch_device[i] = false;
1861
1862 list_for_each(node, &adev->usecase_list) {
1863 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301864 /*
1865 * TODO: Enhance below condition to handle BT sco/USB multi recording
1866 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301867
1868 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1869 (usecase->in_snd_device != snd_device || force_routing));
1870 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1871 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1872 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001873 ((backend_check_cond &&
1874 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001875 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001876 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001877 is_single_device_type_equal(&usecase->device_list,
1878 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001879 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001880 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001881 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301882 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001883 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001884 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001885 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001886 switch_device[usecase->id] = true;
1887 num_uc_to_switch++;
1888 }
1889 }
1890
1891 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001892 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001893
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301894 /* Make sure the previous devices to be disabled first and then enable the
1895 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001896 list_for_each(node, &adev->usecase_list) {
1897 usecase = node_to_item(node, struct audio_usecase, list);
1898 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001899 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001900 }
1901 }
1902
1903 list_for_each(node, &adev->usecase_list) {
1904 usecase = node_to_item(node, struct audio_usecase, list);
1905 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001906 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001907 }
1908 }
1909
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001910 /* Re-route all the usecases on the shared backend other than the
1911 specified usecase to new snd devices */
1912 list_for_each(node, &adev->usecase_list) {
1913 usecase = node_to_item(node, struct audio_usecase, list);
1914 /* Update the in_snd_device only before enabling the audio route */
1915 if (switch_device[usecase->id] ) {
1916 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001917 if (usecase->type != VOICE_CALL) {
1918 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301919 if (usecase->type == VOIP_CALL) {
1920 snd_device_t voip_snd_device;
1921 voip_snd_device = platform_get_output_snd_device(adev->platform,
1922 uc_info->stream.out,
1923 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001924 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301925 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001926 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301927 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301928 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001929 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001930 }
1931 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001932 }
1933}
1934
Mingming Yin3a941d42016-02-17 18:08:05 -08001935static void reset_hdmi_sink_caps(struct stream_out *out) {
1936 int i = 0;
1937
1938 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1939 out->supported_channel_masks[i] = 0;
1940 }
1941 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1942 out->supported_formats[i] = 0;
1943 }
1944 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1945 out->supported_sample_rates[i] = 0;
1946 }
1947}
1948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001950static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951{
Mingming Yin3a941d42016-02-17 18:08:05 -08001952 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001953 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1954 out->extconn.cs.controller,
1955 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956
Mingming Yin3a941d42016-02-17 18:08:05 -08001957 reset_hdmi_sink_caps(out);
1958
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001959 /* Cache ext disp type */
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001960 if (platform_get_ext_disp_type_v2(adev->platform,
1961 out->extconn.cs.controller,
1962 out->extconn.cs.stream <= 0)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001963 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001964 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001965 }
1966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001969 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001970 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001971 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1972 case 6:
1973 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1974 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1975 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1976 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1978 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 break;
1980 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001981 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001982 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 break;
1984 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001985
1986 // check channel format caps
1987 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001988 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1989 out->extconn.cs.controller,
1990 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001991 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1992 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1993 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1994 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1995 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1996 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1997 }
1998
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001999 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2000 out->extconn.cs.controller,
2001 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002002 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2003 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2004 }
2005
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002006 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2007 out->extconn.cs.controller,
2008 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002009 ALOGV(":%s HDMI supports DTS format", __func__);
2010 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2011 }
2012
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002013 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2014 out->extconn.cs.controller,
2015 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002016 ALOGV(":%s HDMI supports DTS HD format", __func__);
2017 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2018 }
2019
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002020 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2021 out->extconn.cs.controller,
2022 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002023 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2024 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2025 }
2026
Mingming Yin3a941d42016-02-17 18:08:05 -08002027
2028 // check sample rate caps
2029 i = 0;
2030 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002031 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2032 out->extconn.cs.controller,
2033 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002034 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2035 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2036 }
2037 }
2038
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002039 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040}
2041
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002042static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2043 uint32_t *supported_sample_rates __unused,
2044 uint32_t max_rates __unused)
2045{
2046 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2047 supported_sample_rates,
2048 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302049 ssize_t i = 0;
2050
2051 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002052 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2053 supported_sample_rates[i]);
2054 }
2055 return count;
2056}
2057
2058static inline int read_usb_sup_channel_masks(bool is_playback,
2059 audio_channel_mask_t *supported_channel_masks,
2060 uint32_t max_masks)
2061{
2062 int channels = audio_extn_usb_get_max_channels(is_playback);
2063 int channel_count;
2064 uint32_t num_masks = 0;
2065 if (channels > MAX_HIFI_CHANNEL_COUNT)
2066 channels = MAX_HIFI_CHANNEL_COUNT;
2067
2068 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002069 // start from 2 channels as framework currently doesn't support mono.
2070 if (channels >= FCC_2) {
2071 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2072 }
2073 for (channel_count = FCC_2;
2074 channel_count <= channels && num_masks < max_masks;
2075 ++channel_count) {
2076 supported_channel_masks[num_masks++] =
2077 audio_channel_mask_for_index_assignment_from_count(channel_count);
2078 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002079 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002080 // For capture we report all supported channel masks from 1 channel up.
2081 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002082 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2083 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002084 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2085 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2086 if (channel_count <= FCC_2) {
2087 mask = audio_channel_in_mask_from_count(channel_count);
2088 supported_channel_masks[num_masks++] = mask;
2089 }
2090 const audio_channel_mask_t index_mask =
2091 audio_channel_mask_for_index_assignment_from_count(channel_count);
2092 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2093 supported_channel_masks[num_masks++] = index_mask;
2094 }
2095 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002096 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302097
vincenttewf51c94e2019-05-07 10:28:53 +08002098 for (size_t i = 0; i < num_masks; ++i) {
2099 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2100 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302101 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002102 return num_masks;
2103}
2104
2105static inline int read_usb_sup_formats(bool is_playback __unused,
2106 audio_format_t *supported_formats,
2107 uint32_t max_formats __unused)
2108{
2109 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2110 switch (bitwidth) {
2111 case 24:
2112 // XXX : usb.c returns 24 for s24 and s24_le?
2113 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2114 break;
2115 case 32:
2116 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2117 break;
2118 case 16:
2119 default :
2120 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2121 break;
2122 }
2123 ALOGV("%s: %s supported format %d", __func__,
2124 is_playback ? "P" : "C", bitwidth);
2125 return 1;
2126}
2127
2128static inline int read_usb_sup_params_and_compare(bool is_playback,
2129 audio_format_t *format,
2130 audio_format_t *supported_formats,
2131 uint32_t max_formats,
2132 audio_channel_mask_t *mask,
2133 audio_channel_mask_t *supported_channel_masks,
2134 uint32_t max_masks,
2135 uint32_t *rate,
2136 uint32_t *supported_sample_rates,
2137 uint32_t max_rates) {
2138 int ret = 0;
2139 int num_formats;
2140 int num_masks;
2141 int num_rates;
2142 int i;
2143
2144 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2145 max_formats);
2146 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2147 max_masks);
2148
2149 num_rates = read_usb_sup_sample_rates(is_playback,
2150 supported_sample_rates, max_rates);
2151
2152#define LUT(table, len, what, dflt) \
2153 for (i=0; i<len && (table[i] != what); i++); \
2154 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2155
2156 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2157 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2158 LUT(supported_sample_rates, num_rates, *rate, 0);
2159
2160#undef LUT
2161 return ret < 0 ? -EINVAL : 0; // HACK TBD
2162}
2163
Alexy Josephb1379942016-01-29 15:49:38 -08002164audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002165 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002166{
2167 struct audio_usecase *usecase;
2168 struct listnode *node;
2169
2170 list_for_each(node, &adev->usecase_list) {
2171 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002172 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002173 ALOGV("%s: usecase id %d", __func__, usecase->id);
2174 return usecase->id;
2175 }
2176 }
2177 return USECASE_INVALID;
2178}
2179
Alexy Josephb1379942016-01-29 15:49:38 -08002180struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002181 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002182{
2183 struct audio_usecase *usecase;
2184 struct listnode *node;
2185
2186 list_for_each(node, &adev->usecase_list) {
2187 usecase = node_to_item(node, struct audio_usecase, list);
2188 if (usecase->id == uc_id)
2189 return usecase;
2190 }
2191 return NULL;
2192}
2193
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302194/*
2195 * is a true native playback active
2196 */
2197bool audio_is_true_native_stream_active(struct audio_device *adev)
2198{
2199 bool active = false;
2200 int i = 0;
2201 struct listnode *node;
2202
2203 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2204 ALOGV("%s:napb: not in true mode or non hdphones device",
2205 __func__);
2206 active = false;
2207 goto exit;
2208 }
2209
2210 list_for_each(node, &adev->usecase_list) {
2211 struct audio_usecase *uc;
2212 uc = node_to_item(node, struct audio_usecase, list);
2213 struct stream_out *curr_out =
2214 (struct stream_out*) uc->stream.out;
2215
2216 if (curr_out && PCM_PLAYBACK == uc->type) {
2217 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2218 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2219 uc->id, curr_out->sample_rate,
2220 curr_out->bit_width,
2221 platform_get_snd_device_name(uc->out_snd_device));
2222
2223 if (is_offload_usecase(uc->id) &&
2224 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2225 active = true;
2226 ALOGD("%s:napb:native stream detected", __func__);
2227 }
2228 }
2229 }
2230exit:
2231 return active;
2232}
2233
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002234uint32_t adev_get_dsp_bit_width_enforce_mode()
2235{
2236 if (adev == NULL) {
2237 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2238 return 0;
2239 }
2240 return adev->dsp_bit_width_enforce_mode;
2241}
2242
2243static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2244{
2245 char value[PROPERTY_VALUE_MAX];
2246 int trial;
2247 uint32_t dsp_bit_width_enforce_mode = 0;
2248
2249 if (!mixer) {
2250 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2251 __func__);
2252 return 0;
2253 }
2254
2255 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2256 value, NULL) > 0) {
2257 trial = atoi(value);
2258 switch (trial) {
2259 case 16:
2260 dsp_bit_width_enforce_mode = 16;
2261 break;
2262 case 24:
2263 dsp_bit_width_enforce_mode = 24;
2264 break;
2265 case 32:
2266 dsp_bit_width_enforce_mode = 32;
2267 break;
2268 default:
2269 dsp_bit_width_enforce_mode = 0;
2270 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2271 break;
2272 }
2273 }
2274
2275 return dsp_bit_width_enforce_mode;
2276}
2277
2278static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2279 uint32_t enforce_mode,
2280 bool enable)
2281{
2282 struct mixer_ctl *ctl = NULL;
2283 const char *mixer_ctl_name = "ASM Bit Width";
2284 uint32_t asm_bit_width_mode = 0;
2285
2286 if (enforce_mode == 0) {
2287 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2288 return;
2289 }
2290
2291 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2292 if (!ctl) {
2293 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2294 __func__, mixer_ctl_name);
2295 return;
2296 }
2297
2298 if (enable)
2299 asm_bit_width_mode = enforce_mode;
2300 else
2301 asm_bit_width_mode = 0;
2302
2303 ALOGV("%s DSP bit width feature status is %d width=%d",
2304 __func__, enable, asm_bit_width_mode);
2305 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2306 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2307 asm_bit_width_mode);
2308
2309 return;
2310}
2311
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302312/*
2313 * if native DSD playback active
2314 */
2315bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2316{
2317 bool active = false;
2318 struct listnode *node = NULL;
2319 struct audio_usecase *uc = NULL;
2320 struct stream_out *curr_out = NULL;
2321
2322 list_for_each(node, &adev->usecase_list) {
2323 uc = node_to_item(node, struct audio_usecase, list);
2324 curr_out = (struct stream_out*) uc->stream.out;
2325
2326 if (curr_out && PCM_PLAYBACK == uc->type &&
2327 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2328 active = true;
2329 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302330 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302331 }
2332 }
2333 return active;
2334}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302335
2336static bool force_device_switch(struct audio_usecase *usecase)
2337{
2338 bool ret = false;
2339 bool is_it_true_mode = false;
2340
Zhou Song30f2c3e2018-02-08 14:02:15 +08002341 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302342 usecase->type == TRANSCODE_LOOPBACK_RX ||
2343 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002344 return false;
2345 }
2346
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002347 if(usecase->stream.out == NULL) {
2348 ALOGE("%s: stream.out is NULL", __func__);
2349 return false;
2350 }
2351
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302352 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002353 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002354 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2355 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302356 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2357 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2358 (!is_it_true_mode && adev->native_playback_enabled)){
2359 ret = true;
2360 ALOGD("napb: time to toggle native mode");
2361 }
2362 }
2363
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302364 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302365 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2366 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002367 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302368 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302369 ALOGD("Force a2dp device switch to update new encoder config");
2370 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002371 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302372
Florian Pfister1a84f312018-07-19 14:38:18 +02002373 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302374 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2375 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002376 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302377 return ret;
2378}
2379
Aalique Grahame22e49102018-12-18 14:23:57 -08002380static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2381{
2382 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2383}
2384
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302385bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2386{
2387 bool ret=false;
2388 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002389 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2390 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302391 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2392 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002393 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302394 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2395 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2396 ret = true;
2397
2398 return ret;
2399}
2400
2401bool is_a2dp_device(snd_device_t out_snd_device)
2402{
2403 bool ret=false;
2404 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2405 ret = true;
2406
2407 return ret;
2408}
2409
2410bool is_bt_soc_on(struct audio_device *adev)
2411{
2412 struct mixer_ctl *ctl;
2413 char *mixer_ctl_name = "BT SOC status";
2414 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2415 bool bt_soc_status = true;
2416 if (!ctl) {
2417 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2418 __func__, mixer_ctl_name);
2419 /*This is to ensure we dont break targets which dont have the kernel change*/
2420 return true;
2421 }
2422 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2423 ALOGD("BT SOC status: %d",bt_soc_status);
2424 return bt_soc_status;
2425}
2426
Zhou Song331c8e52019-08-26 14:16:12 +08002427static int configure_btsco_sample_rate(snd_device_t snd_device)
2428{
2429 struct mixer_ctl *ctl = NULL;
2430 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2431 char *rate_str = NULL;
2432 bool is_rx_dev = true;
2433
2434 if (is_btsco_device(snd_device, snd_device)) {
2435 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2436 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2437 if (!ctl_sr_tx || !ctl_sr_rx) {
2438 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2439 if (!ctl_sr)
2440 return -ENOSYS;
2441 }
2442
2443 switch (snd_device) {
2444 case SND_DEVICE_OUT_BT_SCO:
2445 rate_str = "KHZ_8";
2446 break;
2447 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2448 case SND_DEVICE_IN_BT_SCO_MIC:
2449 rate_str = "KHZ_8";
2450 is_rx_dev = false;
2451 break;
2452 case SND_DEVICE_OUT_BT_SCO_WB:
2453 rate_str = "KHZ_16";
2454 break;
2455 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2456 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2457 rate_str = "KHZ_16";
2458 is_rx_dev = false;
2459 break;
2460 default:
2461 return 0;
2462 }
2463
2464 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2465 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2466 return -ENOSYS;
2467 }
2468 return 0;
2469}
2470
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302471int out_standby_l(struct audio_stream *stream);
2472
Eric Laurent637e2d42018-11-15 12:24:31 -08002473struct stream_in *adev_get_active_input(const struct audio_device *adev)
2474{
2475 struct listnode *node;
2476 struct stream_in *last_active_in = NULL;
2477
2478 /* Get last added active input.
2479 * TODO: We may use a priority mechanism to pick highest priority active source */
2480 list_for_each(node, &adev->usecase_list)
2481 {
2482 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2483 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2484 last_active_in = usecase->stream.in;
2485 }
2486
2487 return last_active_in;
2488}
2489
2490struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2491{
2492 struct listnode *node;
2493
2494 /* First check active inputs with voice communication source and then
2495 * any input if audio mode is in communication */
2496 list_for_each(node, &adev->usecase_list)
2497 {
2498 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2499 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2500 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2501 return usecase->stream.in;
2502 }
2503 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2504 return adev_get_active_input(adev);
2505
2506 return NULL;
2507}
2508
Carter Hsu2e429db2019-05-14 18:50:52 +08002509/*
2510 * Aligned with policy.h
2511 */
2512static inline int source_priority(int inputSource)
2513{
2514 switch (inputSource) {
2515 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2516 return 9;
2517 case AUDIO_SOURCE_CAMCORDER:
2518 return 8;
2519 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2520 return 7;
2521 case AUDIO_SOURCE_UNPROCESSED:
2522 return 6;
2523 case AUDIO_SOURCE_MIC:
2524 return 5;
2525 case AUDIO_SOURCE_ECHO_REFERENCE:
2526 return 4;
2527 case AUDIO_SOURCE_FM_TUNER:
2528 return 3;
2529 case AUDIO_SOURCE_VOICE_RECOGNITION:
2530 return 2;
2531 case AUDIO_SOURCE_HOTWORD:
2532 return 1;
2533 default:
2534 break;
2535 }
2536 return 0;
2537}
2538
2539static struct stream_in *get_priority_input(struct audio_device *adev)
2540{
2541 struct listnode *node;
2542 struct audio_usecase *usecase;
2543 int last_priority = 0, priority;
2544 struct stream_in *priority_in = NULL;
2545 struct stream_in *in;
2546
2547 list_for_each(node, &adev->usecase_list) {
2548 usecase = node_to_item(node, struct audio_usecase, list);
2549 if (usecase->type == PCM_CAPTURE) {
2550 in = usecase->stream.in;
2551 if (!in)
2552 continue;
2553 priority = source_priority(in->source);
2554
2555 if (priority > last_priority) {
2556 last_priority = priority;
2557 priority_in = in;
2558 }
2559 }
2560 }
2561 return priority_in;
2562}
2563
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002564int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002566 snd_device_t out_snd_device = SND_DEVICE_NONE;
2567 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002568 struct audio_usecase *usecase = NULL;
2569 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002570 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002571 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302572 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002573 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302576 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002578 usecase = get_usecase_from_list(adev, uc_id);
2579 if (usecase == NULL) {
2580 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2581 return -EINVAL;
2582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002584 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002585 (usecase->type == VOIP_CALL) ||
2586 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302587 if(usecase->stream.out == NULL) {
2588 ALOGE("%s: stream.out is NULL", __func__);
2589 return -EINVAL;
2590 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002591 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002592 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2593 uc_id);
2594 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2595 uc_id);
2596 } else {
2597 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302598 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002599 in_snd_device = platform_get_input_snd_device(adev->platform,
2600 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302601 &usecase->stream.out->device_list,
2602 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002603 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002604 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302605 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302606 if (usecase->stream.inout == NULL) {
2607 ALOGE("%s: stream.inout is NULL", __func__);
2608 return -EINVAL;
2609 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002610 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302611 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2612 stream_out.format = usecase->stream.inout->out_config.format;
2613 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302614 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002615 assign_devices(&usecase->device_list,
2616 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302617 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2618 if (usecase->stream.inout == NULL) {
2619 ALOGE("%s: stream.inout is NULL", __func__);
2620 return -EINVAL;
2621 }
Jaideep Sharma477917f2020-03-13 18:13:33 +05302622 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002623 assign_devices(&usecase->device_list,
2624 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002625 } else {
2626 /*
2627 * If the voice call is active, use the sound devices of voice call usecase
2628 * so that it would not result any device switch. All the usecases will
2629 * be switched to new device when select_devices() is called for voice call
2630 * usecase. This is to avoid switching devices for voice call when
2631 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002632 * choose voice call device only if the use case device is
2633 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002634 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002635 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002636 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002637 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002638 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2639 is_codec_backend_out_device_type(&usecase->device_list)) ||
2640 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2641 is_codec_backend_in_device_type(&usecase->device_list)) ||
2642 is_single_device_type_equal(&vc_usecase->device_list,
2643 AUDIO_DEVICE_OUT_HEARING_AID) ||
2644 is_single_device_type_equal(&usecase->device_list,
2645 AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002646 in_snd_device = vc_usecase->in_snd_device;
2647 out_snd_device = vc_usecase->out_snd_device;
2648 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002649 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002650 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002651 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002652 if ((voip_usecase != NULL) &&
2653 (usecase->type == PCM_PLAYBACK) &&
2654 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002655 out_snd_device_backend_match = platform_check_backends_match(
2656 voip_usecase->out_snd_device,
2657 platform_get_output_snd_device(
2658 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302659 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002660 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002661 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2662 (is_codec_backend_out_device_type(&usecase->device_list) ||
2663 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002664 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002665 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002666 in_snd_device = voip_usecase->in_snd_device;
2667 out_snd_device = voip_usecase->out_snd_device;
2668 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002669 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002670 hfp_ucid = audio_extn_hfp_get_usecase();
2671 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002672 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002673 in_snd_device = hfp_usecase->in_snd_device;
2674 out_snd_device = hfp_usecase->out_snd_device;
2675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 }
2677 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302678 if (usecase->stream.out == NULL) {
2679 ALOGE("%s: stream.out is NULL", __func__);
2680 return -EINVAL;
2681 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002682 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002684 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002685 struct stream_out *voip_out = adev->primary_output;
2686 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002687 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002688 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2689 else
2690 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302691 usecase->stream.out,
2692 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002693 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002694
Eric Laurent637e2d42018-11-15 12:24:31 -08002695 if (voip_usecase)
2696 voip_out = voip_usecase->stream.out;
2697
2698 if (usecase->stream.out == voip_out && voip_in != NULL)
2699 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002700 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002701 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302702 if (usecase->stream.in == NULL) {
2703 ALOGE("%s: stream.in is NULL", __func__);
2704 return -EINVAL;
2705 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002706 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002707 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002708 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002709 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002710 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002711 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002712
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002713 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002714 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002715 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2716 USECASE_AUDIO_PLAYBACK_VOIP);
2717
Carter Hsu2e429db2019-05-14 18:50:52 +08002718 usecase->stream.in->enable_ec_port = false;
2719
Eric Laurent637e2d42018-11-15 12:24:31 -08002720 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002721 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002722 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002723 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002724 } else if (adev->primary_output &&
2725 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002726 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002727 } else {
2728 /* forcing speaker o/p device to get matching i/p pair
2729 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002730 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002731 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002732 priority_in = voip_in;
2733 } else {
2734 /* get the input with the highest priority source*/
2735 priority_in = get_priority_input(adev);
2736
2737 if (!priority_in)
2738 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002739 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002740
Eric Laurent637e2d42018-11-15 12:24:31 -08002741 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002742 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302743 &out_devices,
2744 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002745 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002746 }
2747 }
2748
2749 if (out_snd_device == usecase->out_snd_device &&
2750 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302751
2752 if (!force_device_switch(usecase))
2753 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 }
2755
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002756 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002757 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002758 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002759 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2760 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302761 }
2762
Aalique Grahame22e49102018-12-18 14:23:57 -08002763 if (out_snd_device != SND_DEVICE_NONE &&
2764 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2765 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2766 __func__,
2767 use_case_table[uc_id],
2768 adev->last_logged_snd_device[uc_id][0],
2769 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2770 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2771 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2772 -1,
2773 out_snd_device,
2774 platform_get_snd_device_name(out_snd_device),
2775 platform_get_snd_device_acdb_id(out_snd_device));
2776 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2777 }
2778 if (in_snd_device != SND_DEVICE_NONE &&
2779 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2780 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2781 __func__,
2782 use_case_table[uc_id],
2783 adev->last_logged_snd_device[uc_id][1],
2784 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2785 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2786 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2787 -1,
2788 in_snd_device,
2789 platform_get_snd_device_name(in_snd_device),
2790 platform_get_snd_device_acdb_id(in_snd_device));
2791 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2792 }
2793
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 /*
2796 * Limitation: While in call, to do a device switch we need to disable
2797 * and enable both RX and TX devices though one of them is same as current
2798 * device.
2799 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002800 if ((usecase->type == VOICE_CALL) &&
2801 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2802 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002803 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002804 }
2805
2806 if (((usecase->type == VOICE_CALL) ||
2807 (usecase->type == VOIP_CALL)) &&
2808 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2809 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302810 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002811 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002812 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002813
2814 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302815 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002816 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002817 }
2818
Aalique Grahame22e49102018-12-18 14:23:57 -08002819 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2820 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002821 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302822 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002823 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2824 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2825 else
2826 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302827 }
2828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 /* Disable current sound devices */
2830 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002831 disable_audio_route(adev, usecase);
2832 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 }
2834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002835 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002836 disable_audio_route(adev, usecase);
2837 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
2839
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002840 /* Applicable only on the targets that has external modem.
2841 * New device information should be sent to modem before enabling
2842 * the devices to reduce in-call device switch time.
2843 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002844 if ((usecase->type == VOICE_CALL) &&
2845 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2846 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002847 status = platform_switch_voice_call_enable_device_config(adev->platform,
2848 out_snd_device,
2849 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002850 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 /* Enable new sound devices */
2853 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002854 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302855 if (platform_check_codec_asrc_support(adev->platform))
2856 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002857 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 }
2859
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002860 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302861 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002862 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002864
Avinash Vaish71a8b972014-07-24 15:36:33 +05302865 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002866 status = platform_switch_voice_call_device_post(adev->platform,
2867 out_snd_device,
2868 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302869 enable_audio_route_for_voice_usecases(adev, usecase);
2870 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002871
sangwoo170731f2013-06-08 15:36:36 +09002872 usecase->in_snd_device = in_snd_device;
2873 usecase->out_snd_device = out_snd_device;
2874
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302875 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2876 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302877 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002878 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002879 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002880 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2881 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2882 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2883 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2884 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2885 /*
2886 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2887 * configured device sample rate, if not update the COPP rate to be equal to the
2888 * device sample rate, else open COPP at stream sample rate
2889 */
2890 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2891 usecase->stream.out->sample_rate,
2892 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302893 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302894 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2895 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302896 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002897 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2898 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2899 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2900 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002901 }
2902 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002903
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002904 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002905
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002906 /* If input stream is already running then effect needs to be
2907 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002908 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002909 check_and_enable_effect(adev);
2910
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002911 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002912 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302913 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002914 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2915
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002916 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302917 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002918 voice_extn_compress_voip_is_started(adev))
2919 voice_set_sidetone(adev, out_snd_device, true);
2920 }
2921
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002922 /* Applicable only on the targets that has external modem.
2923 * Enable device command should be sent to modem only after
2924 * enabling voice call mixer controls
2925 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002926 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002927 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2928 out_snd_device,
2929 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302930
2931 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002932 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302933 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002934 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302935 if (is_bt_soc_on(adev) == false){
2936 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002937 if (in->pcm != NULL)
2938 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302939 }
2940 }
2941 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2942 && usecase->stream.out->started) {
2943 if (is_bt_soc_on(adev) == false) {
2944 ALOGD("BT SCO/A2DP disconnected while in connection");
2945 out_standby_l(&usecase->stream.out->stream.common);
2946 }
2947 }
2948 } else if ((usecase->stream.out != NULL) &&
2949 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302950 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2951 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002952 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302953 usecase->stream.out->started) {
2954 if (is_bt_soc_on(adev) == false) {
2955 ALOGD("BT SCO/A2dp disconnected while in connection");
2956 out_standby_l(&usecase->stream.out->stream.common);
2957 }
2958 }
2959 }
2960
Yung Ti Su70cb8242018-06-22 17:38:47 +08002961 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002962 struct stream_out *voip_out = voip_usecase->stream.out;
2963 audio_extn_utils_send_app_type_gain(adev,
2964 voip_out->app_type_cfg.app_type,
2965 &voip_out->app_type_cfg.gain[0]);
2966 }
2967
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302968 ALOGD("%s: done",__func__);
2969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 return status;
2971}
2972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973static int stop_input_stream(struct stream_in *in)
2974{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302975 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302977
2978 if (in == NULL) {
2979 ALOGE("%s: stream_in ptr is NULL", __func__);
2980 return -EINVAL;
2981 }
2982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002984 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985
Eric Laurent994a6932013-07-17 11:51:42 -07002986 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002987 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 uc_info = get_usecase_from_list(adev, in->usecase);
2989 if (uc_info == NULL) {
2990 ALOGE("%s: Could not find the usecase (%d) in the list",
2991 __func__, in->usecase);
2992 return -EINVAL;
2993 }
2994
Carter Hsu2e429db2019-05-14 18:50:52 +08002995 priority_in = get_priority_input(adev);
2996
Derek Chenea197282019-01-07 17:35:01 -08002997 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2998 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002999
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003000 /* Close in-call recording streams */
3001 voice_check_and_stop_incall_rec_usecase(adev, in);
3002
Eric Laurent150dbfe2013-02-27 14:31:02 -08003003 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003004 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003005
3006 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003007 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003009 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303010 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3011
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003012 list_remove(&uc_info->list);
3013 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014
Carter Hsu2e429db2019-05-14 18:50:52 +08003015 if (priority_in == in) {
3016 priority_in = get_priority_input(adev);
3017 if (priority_in)
3018 select_devices(adev, priority_in->usecase);
3019 }
3020
Vatsal Buchac09ae062018-11-14 13:25:08 +05303021 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003022 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 return ret;
3024}
3025
3026int start_input_stream(struct stream_in *in)
3027{
3028 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003029 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303031
3032 if (in == NULL) {
3033 ALOGE("%s: stream_in ptr is NULL", __func__);
3034 return -EINVAL;
3035 }
3036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003038 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003039 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040
Mingming Yin2664a5b2015-09-03 10:53:11 -07003041 if (get_usecase_from_list(adev, usecase) == NULL)
3042 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303043 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3044 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003045
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303046 if (CARD_STATUS_OFFLINE == in->card_status||
3047 CARD_STATUS_OFFLINE == adev->card_status) {
3048 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303049 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303050 goto error_config;
3051 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303052
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003053 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303054 if (!adev->bt_sco_on) {
3055 ALOGE("%s: SCO profile is not ready, return error", __func__);
3056 ret = -EIO;
3057 goto error_config;
3058 }
3059 }
3060
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003061 /* Check if source matches incall recording usecase criteria */
3062 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3063 if (ret)
3064 goto error_config;
3065 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003066 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3067
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303068 if (audio_extn_cin_attached_usecase(in))
3069 audio_extn_cin_acquire_usecase(in);
3070
Mingming Yin2664a5b2015-09-03 10:53:11 -07003071 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3072 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3073 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003074 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003075 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003076
Eric Laurentb23d5282013-05-14 15:27:20 -07003077 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 if (in->pcm_device_id < 0) {
3079 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3080 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003081 ret = -EINVAL;
3082 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003086
3087 if (!uc_info) {
3088 ret = -ENOMEM;
3089 goto error_config;
3090 }
3091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 uc_info->id = in->usecase;
3093 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003094 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003095 list_init(&uc_info->device_list);
3096 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003097 uc_info->in_snd_device = SND_DEVICE_NONE;
3098 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003100 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003101 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303102 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3103 adev->perf_lock_opts,
3104 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003105 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106
Derek Chenea197282019-01-07 17:35:01 -08003107 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3108 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003109
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303110 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3111
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303112 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303113 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303114 if (ret)
3115 goto error_open;
3116 else
3117 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003118 }
3119
Haynes Mathew George16081042017-05-31 17:16:49 -07003120 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003121 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003122 ALOGE("%s: pcm stream not ready", __func__);
3123 goto error_open;
3124 }
3125 ret = pcm_start(in->pcm);
3126 if (ret < 0) {
3127 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3128 goto error_open;
3129 }
3130 } else {
3131 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3132 unsigned int pcm_open_retry_count = 0;
3133
3134 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3135 flags |= PCM_MMAP | PCM_NOIRQ;
3136 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3137 } else if (in->realtime) {
3138 flags |= PCM_MMAP | PCM_NOIRQ;
3139 }
3140
Garmond Leunge2433c32017-09-28 21:51:22 -07003141 if (audio_extn_ffv_get_stream() == in) {
3142 ALOGD("%s: ffv stream, update pcm config", __func__);
3143 audio_extn_ffv_update_pcm_config(&config);
3144 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003145 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3146 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3147
3148 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003149 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003150 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003151 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003152 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303153 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303154 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3155 adev->card_status = CARD_STATUS_OFFLINE;
3156 in->card_status = CARD_STATUS_OFFLINE;
3157 ret = -EIO;
3158 goto error_open;
3159 }
3160
Haynes Mathew George16081042017-05-31 17:16:49 -07003161 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3162 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3163 if (in->pcm != NULL) {
3164 pcm_close(in->pcm);
3165 in->pcm = NULL;
3166 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003167 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003168 ret = -EIO;
3169 goto error_open;
3170 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003171 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003172 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3173 continue;
3174 }
3175 break;
3176 }
3177
3178 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003179 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003180 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003181 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003182 if (ret < 0) {
3183 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3184 pcm_close(in->pcm);
3185 in->pcm = NULL;
3186 goto error_open;
3187 }
3188 register_in_stream(in);
3189 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003190 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003191 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003192 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003193 if (ret < 0) {
3194 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003195 pcm_close(in->pcm);
3196 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003197 goto error_open;
3198 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003199 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003200 }
3201
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003202 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003203 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3204 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003205
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003206 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303207 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3208
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303209done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003210 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303211 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003212 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303213 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003214 return ret;
3215
3216error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003217 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303218 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003220
Eric Laurentc8400632013-02-14 19:04:54 -08003221error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303222 /*
3223 * sleep 50ms to allow sufficient time for kernel
3224 * drivers to recover incases like SSR.
3225 */
3226 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003227 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303228 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003229 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230}
3231
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003232void lock_input_stream(struct stream_in *in)
3233{
3234 pthread_mutex_lock(&in->pre_lock);
3235 pthread_mutex_lock(&in->lock);
3236 pthread_mutex_unlock(&in->pre_lock);
3237}
3238
3239void lock_output_stream(struct stream_out *out)
3240{
3241 pthread_mutex_lock(&out->pre_lock);
3242 pthread_mutex_lock(&out->lock);
3243 pthread_mutex_unlock(&out->pre_lock);
3244}
3245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246/* must be called with out->lock locked */
3247static int send_offload_cmd_l(struct stream_out* out, int command)
3248{
3249 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3250
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003251 if (!cmd) {
3252 ALOGE("failed to allocate mem for command 0x%x", command);
3253 return -ENOMEM;
3254 }
3255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 ALOGVV("%s %d", __func__, command);
3257
3258 cmd->cmd = command;
3259 list_add_tail(&out->offload_cmd_list, &cmd->node);
3260 pthread_cond_signal(&out->offload_cond);
3261 return 0;
3262}
3263
3264/* must be called iwth out->lock locked */
3265static void stop_compressed_output_l(struct stream_out *out)
3266{
3267 out->offload_state = OFFLOAD_STATE_IDLE;
3268 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003269 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 if (out->compr != NULL) {
3271 compress_stop(out->compr);
3272 while (out->offload_thread_blocked) {
3273 pthread_cond_wait(&out->cond, &out->lock);
3274 }
3275 }
3276}
3277
Varun Balaraje49253e2017-07-06 19:48:56 +05303278bool is_interactive_usecase(audio_usecase_t uc_id)
3279{
3280 unsigned int i;
3281 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3282 if (uc_id == interactive_usecases[i])
3283 return true;
3284 }
3285 return false;
3286}
3287
3288static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3289{
3290 audio_usecase_t ret_uc = USECASE_INVALID;
3291 unsigned int intract_uc_index;
3292 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3293
3294 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3295 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3296 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3297 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3298 ret_uc = interactive_usecases[intract_uc_index];
3299 break;
3300 }
3301 }
3302
3303 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3304 return ret_uc;
3305}
3306
3307static void free_interactive_usecase(struct audio_device *adev,
3308 audio_usecase_t uc_id)
3309{
3310 unsigned int interact_uc_index;
3311 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3312
3313 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3314 if (interactive_usecases[interact_uc_index] == uc_id) {
3315 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3316 break;
3317 }
3318 }
3319 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3320}
3321
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003322bool is_offload_usecase(audio_usecase_t uc_id)
3323{
3324 unsigned int i;
3325 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3326 if (uc_id == offload_usecases[i])
3327 return true;
3328 }
3329 return false;
3330}
3331
Dhananjay Kumarac341582017-02-23 23:42:25 +05303332static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003333{
vivek mehta446c3962015-09-14 10:57:35 -07003334 audio_usecase_t ret_uc = USECASE_INVALID;
3335 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003336 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003337 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303338 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003339 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3340 else
3341 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003342
vivek mehta446c3962015-09-14 10:57:35 -07003343 pthread_mutex_lock(&adev->lock);
3344 if (get_usecase_from_list(adev, ret_uc) != NULL)
3345 ret_uc = USECASE_INVALID;
3346 pthread_mutex_unlock(&adev->lock);
3347
3348 return ret_uc;
3349 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003350
3351 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003352 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3353 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3354 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3355 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003356 break;
3357 }
3358 }
vivek mehta446c3962015-09-14 10:57:35 -07003359
3360 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3361 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003362}
3363
3364static void free_offload_usecase(struct audio_device *adev,
3365 audio_usecase_t uc_id)
3366{
vivek mehta446c3962015-09-14 10:57:35 -07003367 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003368 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003369
3370 if (!adev->multi_offload_enable)
3371 return;
3372
3373 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3374 if (offload_usecases[offload_uc_index] == uc_id) {
3375 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003376 break;
3377 }
3378 }
3379 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3380}
3381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382static void *offload_thread_loop(void *context)
3383{
3384 struct stream_out *out = (struct stream_out *) context;
3385 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003386 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003389 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003390 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3391
3392 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003393 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003394 out->offload_state = OFFLOAD_STATE_IDLE;
3395 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003396 for (;;) {
3397 struct offload_cmd *cmd = NULL;
3398 stream_callback_event_t event;
3399 bool send_callback = false;
3400
3401 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3402 __func__, list_empty(&out->offload_cmd_list),
3403 out->offload_state);
3404 if (list_empty(&out->offload_cmd_list)) {
3405 ALOGV("%s SLEEPING", __func__);
3406 pthread_cond_wait(&out->offload_cond, &out->lock);
3407 ALOGV("%s RUNNING", __func__);
3408 continue;
3409 }
3410
3411 item = list_head(&out->offload_cmd_list);
3412 cmd = node_to_item(item, struct offload_cmd, node);
3413 list_remove(item);
3414
3415 ALOGVV("%s STATE %d CMD %d out->compr %p",
3416 __func__, out->offload_state, cmd->cmd, out->compr);
3417
3418 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3419 free(cmd);
3420 break;
3421 }
3422
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003423 // allow OFFLOAD_CMD_ERROR reporting during standby
3424 // this is needed to handle failures during compress_open
3425 // Note however that on a pause timeout, the stream is closed
3426 // and no offload usecase will be active. Therefore this
3427 // special case is needed for compress_open failures alone
3428 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3429 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003431 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 pthread_cond_signal(&out->cond);
3433 continue;
3434 }
3435 out->offload_thread_blocked = true;
3436 pthread_mutex_unlock(&out->lock);
3437 send_callback = false;
3438 switch(cmd->cmd) {
3439 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003440 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003442 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 send_callback = true;
3444 event = STREAM_CBK_EVENT_WRITE_READY;
3445 break;
3446 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003447 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303448 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003449 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303450 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003451 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303452 if (ret < 0)
3453 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303454 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303455 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003456 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003457 else
3458 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003459 if (-ENETRESET != ret && !(-EINTR == ret &&
3460 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303461 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303462 pthread_mutex_lock(&out->lock);
3463 out->send_new_metadata = 1;
3464 out->send_next_track_params = true;
3465 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303466 event = STREAM_CBK_EVENT_DRAIN_READY;
3467 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3468 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303469 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 break;
3471 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003472 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003473 ret = compress_drain(out->compr);
3474 ALOGD("copl(%p):out of compress_drain", out);
3475 // EINTR check avoids drain interruption due to SSR
3476 if (-ENETRESET != ret && !(-EINTR == ret &&
3477 CARD_STATUS_OFFLINE == out->card_status)) {
3478 send_callback = true;
3479 event = STREAM_CBK_EVENT_DRAIN_READY;
3480 } else
3481 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303483 case OFFLOAD_CMD_ERROR:
3484 ALOGD("copl(%p): sending error callback to AF", out);
3485 send_callback = true;
3486 event = STREAM_CBK_EVENT_ERROR;
3487 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 default:
3489 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3490 break;
3491 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003492 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003493 out->offload_thread_blocked = false;
3494 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003495 if (send_callback && out->client_callback) {
3496 ALOGVV("%s: sending client_callback event %d", __func__, event);
3497 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003498 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499 free(cmd);
3500 }
3501
3502 pthread_cond_signal(&out->cond);
3503 while (!list_empty(&out->offload_cmd_list)) {
3504 item = list_head(&out->offload_cmd_list);
3505 list_remove(item);
3506 free(node_to_item(item, struct offload_cmd, node));
3507 }
3508 pthread_mutex_unlock(&out->lock);
3509
3510 return NULL;
3511}
3512
3513static int create_offload_callback_thread(struct stream_out *out)
3514{
3515 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3516 list_init(&out->offload_cmd_list);
3517 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3518 offload_thread_loop, out);
3519 return 0;
3520}
3521
3522static int destroy_offload_callback_thread(struct stream_out *out)
3523{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003524 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 stop_compressed_output_l(out);
3526 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3527
3528 pthread_mutex_unlock(&out->lock);
3529 pthread_join(out->offload_thread, (void **) NULL);
3530 pthread_cond_destroy(&out->offload_cond);
3531
3532 return 0;
3533}
3534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535static int stop_output_stream(struct stream_out *out)
3536{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303537 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 struct audio_usecase *uc_info;
3539 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003540 bool has_voip_usecase =
3541 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542
Eric Laurent994a6932013-07-17 11:51:42 -07003543 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003544 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 uc_info = get_usecase_from_list(adev, out->usecase);
3546 if (uc_info == NULL) {
3547 ALOGE("%s: Could not find the usecase (%d) in the list",
3548 __func__, out->usecase);
3549 return -EINVAL;
3550 }
3551
Derek Chenea197282019-01-07 17:35:01 -08003552 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3553 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003554
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003555 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303556 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003557 if (adev->visualizer_stop_output != NULL)
3558 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003559
3560 audio_extn_dts_remove_state_notifier_node(out->usecase);
3561
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003562 if (adev->offload_effects_stop_output != NULL)
3563 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003564 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3565 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3566 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003567 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003568
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003569 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3570 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003571 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003572 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003573
Eric Laurent150dbfe2013-02-27 14:31:02 -08003574 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003575 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003576
3577 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003578 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Aalique Grahame22e49102018-12-18 14:23:57 -08003580 audio_extn_extspk_update(adev->extspk);
3581
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003582 if (is_offload_usecase(out->usecase)) {
3583 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3584 adev->dsp_bit_width_enforce_mode,
3585 false);
3586 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003587 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003588 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3589 false);
3590
3591 if (ret != 0)
3592 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3593 /* default service interval was successfully updated,
3594 reopen USB backend with new service interval */
3595 ret = 0;
3596 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003597
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003598 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303599 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003600 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303601 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003602 ALOGV("Disable passthrough , reset mixer to pcm");
3603 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003604#ifdef AUDIO_GKI_ENABLED
3605 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3606 out->compr_config.codec->reserved[0] = 0;
3607#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003608 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003609#endif
Mingming Yin21854652016-04-13 11:54:02 -07003610 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003611 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3612 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003613
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303614 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003615 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303616 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303617
Manish Dewangan21a850a2017-08-14 12:03:55 +05303618 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003619 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3620 if (ret < 0)
3621 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3622 }
3623
juyuchen2d415992018-11-16 14:15:16 +08003624 /* 1) media + voip output routing to handset must route media back to
3625 speaker when voip stops.
3626 2) trigger voip input to reroute when voip output changes to
3627 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003628 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003629 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003630 struct listnode *node;
3631 struct audio_usecase *usecase;
3632 list_for_each(node, &adev->usecase_list) {
3633 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003634 if ((usecase->type == PCM_CAPTURE &&
3635 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3636 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003637 continue;
3638
3639 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3640 __func__, usecase->id, use_case_table[usecase->id],
3641 out->usecase, use_case_table[out->usecase]);
3642 select_devices(adev, usecase->id);
3643 }
3644 }
3645
Garmond Leung5fd0b552018-04-17 11:56:12 -07003646 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003647 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 return ret;
3649}
3650
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003651struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3652 unsigned int flags, unsigned int pcm_open_retry_count,
3653 struct pcm_config *config)
3654{
3655 struct pcm* pcm = NULL;
3656
3657 while (1) {
3658 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3659 if (pcm == NULL || !pcm_is_ready(pcm)) {
3660 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3661 if (pcm != NULL) {
3662 pcm_close(pcm);
3663 pcm = NULL;
3664 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003665 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003666 return NULL;
3667
Weiyin Jiang72197252019-10-09 11:49:32 +08003668 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003669 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3670 continue;
3671 }
3672 break;
3673 }
3674
3675 if (pcm_is_ready(pcm)) {
3676 int ret = pcm_prepare(pcm);
3677 if (ret < 0) {
3678 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3679 pcm_close(pcm);
3680 pcm = NULL;
3681 }
3682 }
3683
3684 return pcm;
3685}
3686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687int start_output_stream(struct stream_out *out)
3688{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 struct audio_usecase *uc_info;
3691 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003692 char mixer_ctl_name[128];
3693 struct mixer_ctl *ctl = NULL;
3694 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303695 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003696 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697
Haynes Mathew George380745d2017-10-04 15:27:45 -07003698 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003699 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3700 ret = -EINVAL;
3701 goto error_config;
3702 }
3703
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003704 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303705 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003706 get_device_types(&out->device_list), is_haptic_usecase);
3707
3708 bool is_speaker_active = compare_device_type(&out->device_list,
3709 AUDIO_DEVICE_OUT_SPEAKER);
3710 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3711 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303712
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303713 if (CARD_STATUS_OFFLINE == out->card_status ||
3714 CARD_STATUS_OFFLINE == adev->card_status) {
3715 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303716 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003717 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303718 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303719
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003720 //Update incall music usecase to reflect correct voice session
3721 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3722 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3723 if (ret != 0) {
3724 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3725 __func__, ret);
3726 goto error_config;
3727 }
3728 }
3729
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003730 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003731 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003732 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303733 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303734 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303735 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3736 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3737 ret = -EAGAIN;
3738 goto error_config;
3739 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303740 }
3741 }
3742 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003743 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303744 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003745 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303746 //combo usecase just by pass a2dp
3747 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003748 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303749 } else {
3750 ALOGE("%s: SCO profile is not ready, return error", __func__);
3751 ret = -EAGAIN;
3752 goto error_config;
3753 }
3754 }
3755 }
3756
Eric Laurentb23d5282013-05-14 15:27:20 -07003757 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 if (out->pcm_device_id < 0) {
3759 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3760 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003761 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003762 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 }
3764
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003765 if (is_haptic_usecase) {
3766 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3767 if (adev->haptic_pcm_device_id < 0) {
3768 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3769 __func__, adev->haptic_pcm_device_id, out->usecase);
3770 ret = -EINVAL;
3771 goto error_config;
3772 }
3773 }
3774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003776
3777 if (!uc_info) {
3778 ret = -ENOMEM;
3779 goto error_config;
3780 }
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 uc_info->id = out->usecase;
3783 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003784 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003785 list_init(&uc_info->device_list);
3786 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003787 uc_info->in_snd_device = SND_DEVICE_NONE;
3788 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003789
3790 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003791 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003792 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3793 /* USB backend is not reopened immediately.
3794 This is eventually done as part of select_devices */
3795 }
3796
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003797 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798
Wei Wangf7ca6c92017-11-21 14:51:20 -08003799 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303800 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3801 adev->perf_lock_opts,
3802 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303803
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003804 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303805 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303806 if (audio_extn_passthru_is_enabled() &&
3807 audio_extn_passthru_is_passthrough_stream(out)) {
3808 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303809 }
3810 }
3811
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003812 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003813 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303814 if (!a2dp_combo) {
3815 check_a2dp_restore_l(adev, out, false);
3816 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003817 struct listnode dev;
3818 list_init(&dev);
3819 assign_devices(&dev, &out->device_list);
3820 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3821 reassign_device_list(&out->device_list,
3822 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003823 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 reassign_device_list(&out->device_list,
3825 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303826 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003827 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303828 }
3829 } else {
3830 select_devices(adev, out->usecase);
3831 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003832
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003833 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3834 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003835 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003836 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003837
Derek Chenea197282019-01-07 17:35:01 -08003838 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3839 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003840
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003841 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3842 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003843
3844 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003845 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003846 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3847 ALOGE("%s: pcm stream not ready", __func__);
3848 goto error_open;
3849 }
3850 ret = pcm_start(out->pcm);
3851 if (ret < 0) {
3852 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3853 goto error_open;
3854 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003855 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003856 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003857 unsigned int flags = PCM_OUT;
3858 unsigned int pcm_open_retry_count = 0;
3859 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3860 flags |= PCM_MMAP | PCM_NOIRQ;
3861 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003862 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003863 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003864 } else
3865 flags |= PCM_MONOTONIC;
3866
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003867 if ((adev->vr_audio_mode_enabled) &&
3868 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3869 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3870 "PCM_Dev %d Topology", out->pcm_device_id);
3871 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3872 if (!ctl) {
3873 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3874 __func__, mixer_ctl_name);
3875 } else {
3876 //if success use ULLPP
3877 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3878 __func__, mixer_ctl_name, out->pcm_device_id);
3879 //There is a still a possibility that some sessions
3880 // that request for FAST|RAW when 3D audio is active
3881 //can go through ULLPP. Ideally we expects apps to
3882 //listen to audio focus and stop concurrent playback
3883 //Also, we will look for mode flag (voice_in_communication)
3884 //before enabling the realtime flag.
3885 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3886 }
3887 }
3888
Surendar Karka91fa3682018-07-02 18:12:12 +05303889 if (out->realtime)
3890 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3891 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3892
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003893 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3894 flags, pcm_open_retry_count,
3895 &(out->config));
3896 if (out->pcm == NULL) {
3897 ret = -EIO;
3898 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003899 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003900
3901 if (is_haptic_usecase) {
3902 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3903 adev->haptic_pcm_device_id,
3904 flags, pcm_open_retry_count,
3905 &(adev->haptics_config));
3906 // failure to open haptics pcm shouldnt stop audio,
3907 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003908
3909 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3910 ALOGD("%s: enable haptic audio synchronization", __func__);
3911 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3912 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003913 }
3914
Surendar Karka91fa3682018-07-02 18:12:12 +05303915 if (!out->realtime)
3916 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303917 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003918
Zhou Song2b8f28f2017-09-11 10:51:38 +08003919 // apply volume for voip playback after path is set up
3920 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3921 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303922 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3923 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303924 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3925 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003926 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3927 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303928 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003929 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003930 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303931 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003932 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3933 adev->dsp_bit_width_enforce_mode,
3934 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003936 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003937 out->compr = compress_open(adev->snd_card,
3938 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003940 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303941 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303942 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3943 adev->card_status = CARD_STATUS_OFFLINE;
3944 out->card_status = CARD_STATUS_OFFLINE;
3945 ret = -EIO;
3946 goto error_open;
3947 }
3948
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003949 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003950 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951 compress_close(out->compr);
3952 out->compr = NULL;
3953 ret = -EIO;
3954 goto error_open;
3955 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303956 /* compress_open sends params of the track, so reset the flag here */
3957 out->is_compr_metadata_avail = false;
3958
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003959 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003961
Fred Oh3f43e742015-03-04 18:42:34 -08003962 /* Since small bufs uses blocking writes, a write will be blocked
3963 for the default max poll time (20s) in the event of an SSR.
3964 Reduce the poll time to observe and deal with SSR faster.
3965 */
Ashish Jain5106d362016-05-11 19:23:33 +05303966 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003967 compress_set_max_poll_wait(out->compr, 1000);
3968 }
3969
Manish Dewangan69426c82017-01-30 17:35:36 +05303970 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303971 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303972
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003973 audio_extn_dts_create_state_notifier_node(out->usecase);
3974 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3975 popcount(out->channel_mask),
3976 out->playback_started);
3977
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003978#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303979 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003980 audio_extn_dolby_send_ddp_endp_params(adev);
3981#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303982 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3983 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003984 if (adev->visualizer_start_output != NULL)
3985 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3986 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303987 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003988 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003989 }
Derek Chenf13dd492018-11-13 14:53:51 -08003990
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003991 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003992 /* Update cached volume from media to offload/direct stream */
3993 struct listnode *node = NULL;
3994 list_for_each(node, &adev->active_outputs_list) {
3995 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3996 streams_output_ctxt_t,
3997 list);
3998 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3999 out->volume_l = out_ctxt->output->volume_l;
4000 out->volume_r = out_ctxt->output->volume_r;
4001 }
4002 }
4003 out_set_compr_volume(&out->stream,
4004 out->volume_l, out->volume_r);
4005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004007
4008 if (ret == 0) {
4009 register_out_stream(out);
4010 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004011 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4012 ALOGE("%s: pcm stream not ready", __func__);
4013 goto error_open;
4014 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004015 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004016 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004017 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004018 if (ret < 0)
4019 goto error_open;
4020 }
4021 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004022 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304023 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004024 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004025
vivek mehtad15d2bf2019-05-17 13:35:10 -07004026 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4027 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4028 audio_low_latency_hint_start();
4029 }
4030
Manish Dewangan21a850a2017-08-14 12:03:55 +05304031 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004032 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004033 if (ret < 0)
4034 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4035 }
4036
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004037 // consider a scenario where on pause lower layers are tear down.
4038 // so on resume, swap mixer control need to be sent only when
4039 // backend is active, hence rather than sending from enable device
4040 // sending it from start of streamtream
4041
4042 platform_set_swap_channels(adev, true);
4043
Haynes Mathew George380745d2017-10-04 15:27:45 -07004044 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304045 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004046 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004048 if (adev->haptic_pcm) {
4049 pcm_close(adev->haptic_pcm);
4050 adev->haptic_pcm = NULL;
4051 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004052 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304053 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004055error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304056 /*
4057 * sleep 50ms to allow sufficient time for kernel
4058 * drivers to recover incases like SSR.
4059 */
4060 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004061error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004062 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304063 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004064 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065}
4066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067static int check_input_parameters(uint32_t sample_rate,
4068 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004069 int channel_count,
4070 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004072 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304074 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4075 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4076 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004077 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004078 !audio_extn_compr_cap_format_supported(format) &&
4079 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004080 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004081
Aalique Grahame22e49102018-12-18 14:23:57 -08004082 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4083 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4084 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4085 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4086 return -EINVAL;
4087 }
4088
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004089 switch (channel_count) {
4090 case 1:
4091 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304092 case 3:
4093 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004094 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004095 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304096 case 10:
4097 case 12:
4098 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004099 break;
4100 default:
4101 ret = -EINVAL;
4102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103
4104 switch (sample_rate) {
4105 case 8000:
4106 case 11025:
4107 case 12000:
4108 case 16000:
4109 case 22050:
4110 case 24000:
4111 case 32000:
4112 case 44100:
4113 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004114 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304115 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004116 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304117 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 break;
4119 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004120 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 }
4122
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004123 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124}
4125
Naresh Tanniru04f71882018-06-26 17:46:22 +05304126
4127/** Add a value in a list if not already present.
4128 * @return true if value was successfully inserted or already present,
4129 * false if the list is full and does not contain the value.
4130 */
4131static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4132 for (size_t i = 0; i < list_length; i++) {
4133 if (list[i] == value) return true; // value is already present
4134 if (list[i] == 0) { // no values in this slot
4135 list[i] = value;
4136 return true; // value inserted
4137 }
4138 }
4139 return false; // could not insert value
4140}
4141
4142/** Add channel_mask in supported_channel_masks if not already present.
4143 * @return true if channel_mask was successfully inserted or already present,
4144 * false if supported_channel_masks is full and does not contain channel_mask.
4145 */
4146static void register_channel_mask(audio_channel_mask_t channel_mask,
4147 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4148 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4149 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4150}
4151
4152/** Add format in supported_formats if not already present.
4153 * @return true if format was successfully inserted or already present,
4154 * false if supported_formats is full and does not contain format.
4155 */
4156static void register_format(audio_format_t format,
4157 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4158 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4159 "%s: stream can not declare supporting its format %x", __func__, format);
4160}
4161/** Add sample_rate in supported_sample_rates if not already present.
4162 * @return true if sample_rate was successfully inserted or already present,
4163 * false if supported_sample_rates is full and does not contain sample_rate.
4164 */
4165static void register_sample_rate(uint32_t sample_rate,
4166 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4167 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4168 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4169}
4170
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004171static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4172{
4173 uint32_t high = num1, low = num2, temp = 0;
4174
4175 if (!num1 || !num2)
4176 return 0;
4177
4178 if (num1 < num2) {
4179 high = num2;
4180 low = num1;
4181 }
4182
4183 while (low != 0) {
4184 temp = low;
4185 low = high % low;
4186 high = temp;
4187 }
4188 return (num1 * num2)/high;
4189}
4190
4191static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4192{
4193 uint32_t remainder = 0;
4194
4195 if (!multiplier)
4196 return num;
4197
4198 remainder = num % multiplier;
4199 if (remainder)
4200 num += (multiplier - remainder);
4201
4202 return num;
4203}
4204
Aalique Grahame22e49102018-12-18 14:23:57 -08004205static size_t get_stream_buffer_size(size_t duration_ms,
4206 uint32_t sample_rate,
4207 audio_format_t format,
4208 int channel_count,
4209 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210{
4211 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004212 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213
Aalique Grahame22e49102018-12-18 14:23:57 -08004214 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004215 if (is_low_latency)
4216 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304217
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004218 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004219 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220
Ralf Herzbd08d632018-09-28 15:50:49 +02004221 /* make sure the size is multiple of 32 bytes and additionally multiple of
4222 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004223 * At 48 kHz mono 16-bit PCM:
4224 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4225 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004226 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004227 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004228 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004229
4230 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231}
4232
Aalique Grahame22e49102018-12-18 14:23:57 -08004233static size_t get_input_buffer_size(uint32_t sample_rate,
4234 audio_format_t format,
4235 int channel_count,
4236 bool is_low_latency)
4237{
4238 /* Don't know if USB HIFI in this context so use true to be conservative */
4239 if (check_input_parameters(sample_rate, format, channel_count,
4240 true /*is_usb_hifi */) != 0)
4241 return 0;
4242
4243 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4244 sample_rate,
4245 format,
4246 channel_count,
4247 is_low_latency);
4248}
4249
Derek Chenf6318be2017-06-12 17:16:24 -04004250size_t get_output_period_size(uint32_t sample_rate,
4251 audio_format_t format,
4252 int channel_count,
4253 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304254{
4255 size_t size = 0;
4256 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4257
4258 if ((duration == 0) || (sample_rate == 0) ||
4259 (bytes_per_sample == 0) || (channel_count == 0)) {
4260 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4261 bytes_per_sample, channel_count);
4262 return -EINVAL;
4263 }
4264
4265 size = (sample_rate *
4266 duration *
4267 bytes_per_sample *
4268 channel_count) / 1000;
4269 /*
4270 * To have same PCM samples for all channels, the buffer size requires to
4271 * be multiple of (number of channels * bytes per sample)
4272 * For writes to succeed, the buffer must be written at address which is multiple of 32
4273 */
4274 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4275
4276 return (size/(channel_count * bytes_per_sample));
4277}
4278
Zhou Song48453a02018-01-10 17:50:59 +08004279static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304280{
4281 uint64_t actual_frames_rendered = 0;
4282 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4283
4284 /* This adjustment accounts for buffering after app processor.
4285 * It is based on estimated DSP latency per use case, rather than exact.
4286 */
4287 int64_t platform_latency = platform_render_latency(out->usecase) *
4288 out->sample_rate / 1000000LL;
4289
Zhou Song48453a02018-01-10 17:50:59 +08004290 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304291 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4292 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4293 * hence only estimate.
4294 */
George Gao62ebc722019-07-29 16:29:44 -07004295 uint64_t signed_frames = 0;
4296 if (out->written >= kernel_buffer_size)
4297 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304298
George Gao62ebc722019-07-29 16:29:44 -07004299 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4300 if (signed_frames >= platform_latency)
4301 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304302
Zhou Song48453a02018-01-10 17:50:59 +08004303 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304304 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004305 if (timestamp != NULL )
4306 *timestamp = out->writeAt;
4307 } else if (timestamp != NULL) {
4308 clock_gettime(CLOCK_MONOTONIC, timestamp);
4309 }
4310 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304311
4312 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004313 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304314 (long long int)out->written, (int)kernel_buffer_size,
4315 audio_bytes_per_sample(out->compr_config.codec->format),
4316 popcount(out->channel_mask));
4317
4318 return actual_frames_rendered;
4319}
4320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4322{
4323 struct stream_out *out = (struct stream_out *)stream;
4324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326}
4327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004328static int out_set_sample_rate(struct audio_stream *stream __unused,
4329 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330{
4331 return -ENOSYS;
4332}
4333
4334static size_t out_get_buffer_size(const struct audio_stream *stream)
4335{
4336 struct stream_out *out = (struct stream_out *)stream;
4337
Varun Balaraje49253e2017-07-06 19:48:56 +05304338 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304339 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304340 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304341 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4342 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4343 else
4344 return out->compr_config.fragment_size;
4345 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004346 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304347 else if (is_offload_usecase(out->usecase) &&
4348 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304349 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004350
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004351 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004352 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353}
4354
4355static uint32_t out_get_channels(const struct audio_stream *stream)
4356{
4357 struct stream_out *out = (struct stream_out *)stream;
4358
4359 return out->channel_mask;
4360}
4361
4362static audio_format_t out_get_format(const struct audio_stream *stream)
4363{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364 struct stream_out *out = (struct stream_out *)stream;
4365
4366 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367}
4368
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004369static int out_set_format(struct audio_stream *stream __unused,
4370 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371{
4372 return -ENOSYS;
4373}
4374
4375static int out_standby(struct audio_stream *stream)
4376{
4377 struct stream_out *out = (struct stream_out *)stream;
4378 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004379 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004380
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304381 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4382 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004384 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004386 if (adev->adm_deregister_stream)
4387 adev->adm_deregister_stream(adev->adm_data, out->handle);
4388
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004389 if (is_offload_usecase(out->usecase))
4390 stop_compressed_output_l(out);
4391
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004392 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004394 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4395 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304396 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004397 pthread_mutex_unlock(&adev->lock);
4398 pthread_mutex_unlock(&out->lock);
4399 ALOGD("VOIP output entered standby");
4400 return 0;
4401 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004402 if (out->pcm) {
4403 pcm_close(out->pcm);
4404 out->pcm = NULL;
4405 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004406 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4407 do_stop = out->playback_started;
4408 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004409
4410 if (out->mmap_shared_memory_fd >= 0) {
4411 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4412 __func__, out->mmap_shared_memory_fd);
4413 close(out->mmap_shared_memory_fd);
4414 out->mmap_shared_memory_fd = -1;
4415 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004416 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004417 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004418 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304419 out->send_next_track_params = false;
4420 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004421 out->gapless_mdata.encoder_delay = 0;
4422 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004423 if (out->compr != NULL) {
4424 compress_close(out->compr);
4425 out->compr = NULL;
4426 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004427 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004428 if (do_stop) {
4429 stop_output_stream(out);
4430 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304431 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004432 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004433 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434 }
4435 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304436 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 return 0;
4438}
4439
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304440static int out_on_error(struct audio_stream *stream)
4441{
4442 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004443 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304444
4445 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004446 // always send CMD_ERROR for offload streams, this
4447 // is needed e.g. when SSR happens within compress_open
4448 // since the stream is active, offload_callback_thread is also active.
4449 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4450 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004451 }
4452 pthread_mutex_unlock(&out->lock);
4453
4454 status = out_standby(&out->stream.common);
4455
4456 lock_output_stream(out);
4457 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004458 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304459 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304460
4461 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4462 ALOGD("Setting previous card status if offline");
4463 out->prev_card_status_offline = true;
4464 }
4465
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304466 pthread_mutex_unlock(&out->lock);
4467
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004468 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304469}
4470
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304471/*
4472 *standby implementation without locks, assumes that the callee already
4473 *has taken adev and out lock.
4474 */
4475int out_standby_l(struct audio_stream *stream)
4476{
4477 struct stream_out *out = (struct stream_out *)stream;
4478 struct audio_device *adev = out->dev;
4479
4480 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4481 stream, out->usecase, use_case_table[out->usecase]);
4482
4483 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004484 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304485 if (adev->adm_deregister_stream)
4486 adev->adm_deregister_stream(adev->adm_data, out->handle);
4487
4488 if (is_offload_usecase(out->usecase))
4489 stop_compressed_output_l(out);
4490
4491 out->standby = true;
4492 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4493 voice_extn_compress_voip_close_output_stream(stream);
4494 out->started = 0;
4495 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004496 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304497 return 0;
4498 } else if (!is_offload_usecase(out->usecase)) {
4499 if (out->pcm) {
4500 pcm_close(out->pcm);
4501 out->pcm = NULL;
4502 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004503 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4504 if (adev->haptic_pcm) {
4505 pcm_close(adev->haptic_pcm);
4506 adev->haptic_pcm = NULL;
4507 }
4508
4509 if (adev->haptic_buffer != NULL) {
4510 free(adev->haptic_buffer);
4511 adev->haptic_buffer = NULL;
4512 adev->haptic_buffer_size = 0;
4513 }
4514 adev->haptic_pcm_device_id = 0;
4515 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304516 } else {
4517 ALOGD("copl(%p):standby", out);
4518 out->send_next_track_params = false;
4519 out->is_compr_metadata_avail = false;
4520 out->gapless_mdata.encoder_delay = 0;
4521 out->gapless_mdata.encoder_padding = 0;
4522 if (out->compr != NULL) {
4523 compress_close(out->compr);
4524 out->compr = NULL;
4525 }
4526 }
4527 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004528 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304529 }
4530 ALOGD("%s: exit", __func__);
4531 return 0;
4532}
4533
Aalique Grahame22e49102018-12-18 14:23:57 -08004534static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535{
Aalique Grahame22e49102018-12-18 14:23:57 -08004536 struct stream_out *out = (struct stream_out *)stream;
4537
4538 // We try to get the lock for consistency,
4539 // but it isn't necessary for these variables.
4540 // If we're not in standby, we may be blocked on a write.
4541 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4542 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4543 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4544
4545 if (locked) {
4546 pthread_mutex_unlock(&out->lock);
4547 }
4548
4549 // dump error info
4550 (void)error_log_dump(
4551 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553 return 0;
4554}
4555
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004556static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4557{
4558 int ret = 0;
4559 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004560
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004561 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004562 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004563 return -EINVAL;
4564 }
4565
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304566 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004567
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004568 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4569 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304570 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004571 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004572 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4573 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304574 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004575 }
4576
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004577 ALOGV("%s new encoder delay %u and padding %u", __func__,
4578 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4579
4580 return 0;
4581}
4582
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004583static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4584{
4585 return out == adev->primary_output || out == adev->voice_tx_output;
4586}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004587
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304588// note: this call is safe only if the stream_cb is
4589// removed first in close_output_stream (as is done now).
4590static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4591{
4592 if (!stream || !parms)
4593 return;
4594
4595 struct stream_out *out = (struct stream_out *)stream;
4596 struct audio_device *adev = out->dev;
4597
4598 card_status_t status;
4599 int card;
4600 if (parse_snd_card_status(parms, &card, &status) < 0)
4601 return;
4602
4603 pthread_mutex_lock(&adev->lock);
4604 bool valid_cb = (card == adev->snd_card);
4605 pthread_mutex_unlock(&adev->lock);
4606
4607 if (!valid_cb)
4608 return;
4609
4610 lock_output_stream(out);
4611 if (out->card_status != status)
4612 out->card_status = status;
4613 pthread_mutex_unlock(&out->lock);
4614
4615 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4616 use_case_table[out->usecase],
4617 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4618
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304619 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304620 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304621 if (voice_is_call_state_active(adev) &&
4622 out == adev->primary_output) {
4623 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4624 pthread_mutex_lock(&adev->lock);
4625 voice_stop_call(adev);
4626 adev->mode = AUDIO_MODE_NORMAL;
4627 pthread_mutex_unlock(&adev->lock);
4628 }
4629 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304630 return;
4631}
4632
Kevin Rocardfce19002017-08-07 19:21:36 -07004633static int get_alive_usb_card(struct str_parms* parms) {
4634 int card;
4635 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4636 !audio_extn_usb_alive(card)) {
4637 return card;
4638 }
4639 return -ENODEV;
4640}
4641
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004642int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004643 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004644{
4645 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004646 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004647 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004648 bool bypass_a2dp = false;
4649 bool reconfig = false;
4650 unsigned long service_interval = 0;
4651
4652 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004653 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4654
4655 list_init(&new_devices);
4656 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004657
4658 lock_output_stream(out);
4659 pthread_mutex_lock(&adev->lock);
4660
4661 /*
4662 * When HDMI cable is unplugged the music playback is paused and
4663 * the policy manager sends routing=0. But the audioflinger continues
4664 * to write data until standby time (3sec). As the HDMI core is
4665 * turned off, the write gets blocked.
4666 * Avoid this by routing audio to speaker until standby.
4667 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004668 if (is_single_device_type_equal(&out->device_list,
4669 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004670 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004671 !audio_extn_passthru_is_passthrough_stream(out) &&
4672 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004673 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004674 }
4675 /*
4676 * When A2DP is disconnected the
4677 * music playback is paused and the policy manager sends routing=0
4678 * But the audioflinger continues to write data until standby time
4679 * (3sec). As BT is turned off, the write gets blocked.
4680 * Avoid this by routing audio to speaker until standby.
4681 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004682 if (is_a2dp_out_device_type(&out->device_list) &&
4683 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004684 !audio_extn_a2dp_source_is_ready() &&
4685 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004686 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004687 }
4688 /*
4689 * When USB headset is disconnected the music platback paused
4690 * and the policy manager send routing=0. But if the USB is connected
4691 * back before the standby time, AFE is not closed and opened
4692 * when USB is connected back. So routing to speker will guarantee
4693 * AFE reconfiguration and AFE will be opend once USB is connected again
4694 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004695 if (is_usb_out_device_type(&out->device_list) &&
4696 list_empty(&new_devices) &&
4697 !audio_extn_usb_connected(NULL)) {
4698 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4699 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004700 /* To avoid a2dp to sco overlapping / BT device improper state
4701 * check with BT lib about a2dp streaming support before routing
4702 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004703 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004704 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004705 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4706 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004707 //combo usecase just by pass a2dp
4708 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4709 bypass_a2dp = true;
4710 } else {
4711 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4712 /* update device to a2dp and don't route as BT returned error
4713 * However it is still possible a2dp routing called because
4714 * of current active device disconnection (like wired headset)
4715 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004716 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004717 pthread_mutex_unlock(&adev->lock);
4718 pthread_mutex_unlock(&out->lock);
4719 goto error;
4720 }
4721 }
4722 }
4723
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004724 // Workaround: If routing to an non existing usb device, fail gracefully
4725 // The routing request will otherwise block during 10 second
4726 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004727 if (is_usb_out_device_type(&new_devices)) {
4728 struct str_parms *parms =
4729 str_parms_create_str(get_usb_device_address(&new_devices));
4730 if (!parms)
4731 goto error;
4732 if ((card = get_alive_usb_card(parms)) >= 0) {
4733 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4734 pthread_mutex_unlock(&adev->lock);
4735 pthread_mutex_unlock(&out->lock);
4736 str_parms_destroy(parms);
4737 ret = -ENOSYS;
4738 goto error;
4739 }
4740 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004741 }
4742
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004743 // Workaround: If routing to an non existing hdmi device, fail gracefully
4744 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4745 (platform_get_edid_info_v2(adev->platform,
4746 out->extconn.cs.controller,
4747 out->extconn.cs.stream) != 0)) {
4748 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4749 pthread_mutex_unlock(&adev->lock);
4750 pthread_mutex_unlock(&out->lock);
4751 ret = -ENOSYS;
4752 goto error;
4753 }
4754
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004755 /*
4756 * select_devices() call below switches all the usecases on the same
4757 * backend to the new device. Refer to check_usecases_codec_backend() in
4758 * the select_devices(). But how do we undo this?
4759 *
4760 * For example, music playback is active on headset (deep-buffer usecase)
4761 * and if we go to ringtones and select a ringtone, low-latency usecase
4762 * will be started on headset+speaker. As we can't enable headset+speaker
4763 * and headset devices at the same time, select_devices() switches the music
4764 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4765 * So when the ringtone playback is completed, how do we undo the same?
4766 *
4767 * We are relying on the out_set_parameters() call on deep-buffer output,
4768 * once the ringtone playback is ended.
4769 * NOTE: We should not check if the current devices are same as new devices.
4770 * Because select_devices() must be called to switch back the music
4771 * playback to headset.
4772 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004773 if (!list_empty(&new_devices)) {
4774 bool same_dev = compare_devices(&out->device_list, &new_devices);
4775 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004776
4777 if (output_drives_call(adev, out)) {
4778 if (!voice_is_call_state_active(adev)) {
4779 if (adev->mode == AUDIO_MODE_IN_CALL) {
4780 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004781 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004782 service_interval =
4783 audio_extn_usb_find_service_interval(true, true /*playback*/);
4784 audio_extn_usb_set_service_interval(true /*playback*/,
4785 service_interval,
4786 &reconfig);
4787 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4788 }
4789 ret = voice_start_call(adev);
4790 }
4791 } else {
4792 adev->current_call_output = out;
4793 voice_update_devices_for_all_voice_usecases(adev);
4794 }
4795 }
4796
4797 if (!out->standby) {
4798 if (!same_dev) {
4799 ALOGV("update routing change");
4800 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4801 adev->perf_lock_opts,
4802 adev->perf_lock_opts_size);
4803 if (adev->adm_on_routing_change)
4804 adev->adm_on_routing_change(adev->adm_data,
4805 out->handle);
4806 }
4807 if (!bypass_a2dp) {
4808 select_devices(adev, out->usecase);
4809 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004810 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4811 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004812 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004813 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004814 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004815 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 }
4817
4818 if (!same_dev) {
4819 // on device switch force swap, lower functions will make sure
4820 // to check if swap is allowed or not.
4821 platform_set_swap_channels(adev, true);
4822 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4823 }
4824 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4825 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004826 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004827 pthread_mutex_lock(&out->compr_mute_lock);
4828 out->a2dp_compress_mute = false;
4829 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4830 pthread_mutex_unlock(&out->compr_mute_lock);
4831 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4832 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4833 }
4834 }
4835 }
4836
4837 pthread_mutex_unlock(&adev->lock);
4838 pthread_mutex_unlock(&out->lock);
4839
4840 /*handles device and call state changes*/
4841 audio_extn_extspk_update(adev->extspk);
4842
4843error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004844 ALOGV("%s: exit: code(%d)", __func__, ret);
4845 return ret;
4846}
4847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4849{
4850 struct stream_out *out = (struct stream_out *)stream;
4851 struct audio_device *adev = out->dev;
4852 struct str_parms *parms;
4853 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004855 int ext_controller = -1;
4856 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857
sangwoobc677242013-08-08 16:53:43 +09004858 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004859 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304861 if (!parms)
4862 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004863
4864 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4865 &ext_stream);
4866 if (err >= 0) {
4867 out->extconn.cs.controller = ext_controller;
4868 out->extconn.cs.stream = ext_stream;
4869 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4870 use_case_table[out->usecase], out->extconn.cs.controller,
4871 out->extconn.cs.stream);
4872 }
4873
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004874 if (out == adev->primary_output) {
4875 pthread_mutex_lock(&adev->lock);
4876 audio_extn_set_parameters(adev, parms);
4877 pthread_mutex_unlock(&adev->lock);
4878 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004879 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004880 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004881 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004882
4883 audio_extn_dts_create_state_notifier_node(out->usecase);
4884 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4885 popcount(out->channel_mask),
4886 out->playback_started);
4887
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004888 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004889 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004890
Surendar Karkaf51b5842018-04-26 11:28:38 +05304891 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4892 sizeof(value));
4893 if (err >= 0) {
4894 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4895 audio_extn_send_dual_mono_mixing_coefficients(out);
4896 }
4897
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304898 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4899 if (err >= 0) {
4900 strlcpy(out->profile, value, sizeof(out->profile));
4901 ALOGV("updating stream profile with value '%s'", out->profile);
4902 lock_output_stream(out);
4903 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4904 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 &out->device_list, out->flags,
4906 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304907 out->sample_rate, out->bit_width,
4908 out->channel_mask, out->profile,
4909 &out->app_type_cfg);
4910 pthread_mutex_unlock(&out->lock);
4911 }
4912
Alexy Joseph98988832017-01-13 14:56:59 -08004913 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004914 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4915 // and vendor.audio.hal.output.suspend.supported is set to true
4916 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004917 //check suspend parameter only for low latency and if the property
4918 //is enabled
4919 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4920 ALOGI("%s: got suspend_playback %s", __func__, value);
4921 lock_output_stream(out);
4922 if (!strncmp(value, "false", 5)) {
4923 //suspend_playback=false is supposed to set QOS value back to 75%
4924 //the mixer control sent with value Enable will achieve that
4925 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4926 } else if (!strncmp (value, "true", 4)) {
4927 //suspend_playback=true is supposed to remove QOS value
4928 //resetting the mixer control will set the default value
4929 //for the mixer control which is Disable and this removes the QOS vote
4930 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4931 } else {
4932 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4933 " got %s", __func__, value);
4934 ret = -1;
4935 }
4936
4937 if (ret != 0) {
4938 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4939 __func__, out->pm_qos_mixer_path, ret);
4940 }
4941
4942 pthread_mutex_unlock(&out->lock);
4943 }
4944 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004945
Alexy Joseph98988832017-01-13 14:56:59 -08004946 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304948error:
Eric Laurent994a6932013-07-17 11:51:42 -07004949 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 return ret;
4951}
4952
Paul McLeana50b7332018-12-17 08:24:21 -07004953static int in_set_microphone_direction(const struct audio_stream_in *stream,
4954 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004955 struct stream_in *in = (struct stream_in *)stream;
4956
4957 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4958
4959 in->direction = dir;
4960
4961 if (in->standby)
4962 return 0;
4963
4964 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004965}
4966
4967static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004968 struct stream_in *in = (struct stream_in *)stream;
4969
4970 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4971
4972 if (zoom > 1.0 || zoom < -1.0)
4973 return -EINVAL;
4974
4975 in->zoom = zoom;
4976
4977 if (in->standby)
4978 return 0;
4979
4980 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004981}
4982
4983
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004984static bool stream_get_parameter_channels(struct str_parms *query,
4985 struct str_parms *reply,
4986 audio_channel_mask_t *supported_channel_masks) {
4987 int ret = -1;
4988 char value[512];
4989 bool first = true;
4990 size_t i, j;
4991
4992 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4993 ret = 0;
4994 value[0] = '\0';
4995 i = 0;
4996 while (supported_channel_masks[i] != 0) {
4997 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4998 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4999 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305000 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005001
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305002 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005003 first = false;
5004 break;
5005 }
5006 }
5007 i++;
5008 }
5009 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5010 }
5011 return ret == 0;
5012}
5013
5014static bool stream_get_parameter_formats(struct str_parms *query,
5015 struct str_parms *reply,
5016 audio_format_t *supported_formats) {
5017 int ret = -1;
5018 char value[256];
5019 size_t i, j;
5020 bool first = true;
5021
5022 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5023 ret = 0;
5024 value[0] = '\0';
5025 i = 0;
5026 while (supported_formats[i] != 0) {
5027 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5028 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5029 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305030 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005031 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305032 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005033 first = false;
5034 break;
5035 }
5036 }
5037 i++;
5038 }
5039 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5040 }
5041 return ret == 0;
5042}
5043
5044static bool stream_get_parameter_rates(struct str_parms *query,
5045 struct str_parms *reply,
5046 uint32_t *supported_sample_rates) {
5047
5048 int i;
5049 char value[256];
5050 int ret = -1;
5051 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5052 ret = 0;
5053 value[0] = '\0';
5054 i=0;
5055 int cursor = 0;
5056 while (supported_sample_rates[i]) {
5057 int avail = sizeof(value) - cursor;
5058 ret = snprintf(value + cursor, avail, "%s%d",
5059 cursor > 0 ? "|" : "",
5060 supported_sample_rates[i]);
5061 if (ret < 0 || ret >= avail) {
5062 // if cursor is at the last element of the array
5063 // overwrite with \0 is duplicate work as
5064 // snprintf already put a \0 in place.
5065 // else
5066 // we had space to write the '|' at value[cursor]
5067 // (which will be overwritten) or no space to fill
5068 // the first element (=> cursor == 0)
5069 value[cursor] = '\0';
5070 break;
5071 }
5072 cursor += ret;
5073 ++i;
5074 }
5075 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5076 value);
5077 }
5078 return ret >= 0;
5079}
5080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5082{
5083 struct stream_out *out = (struct stream_out *)stream;
5084 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005085 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086 char value[256];
5087 struct str_parms *reply = str_parms_create();
5088 size_t i, j;
5089 int ret;
5090 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005091
5092 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005093 if (reply) {
5094 str_parms_destroy(reply);
5095 }
5096 if (query) {
5097 str_parms_destroy(query);
5098 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005099 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5100 return NULL;
5101 }
5102
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005103 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005104 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5105 if (ret >= 0) {
5106 value[0] = '\0';
5107 i = 0;
5108 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005109 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5110 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005112 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005114 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 first = false;
5116 break;
5117 }
5118 }
5119 i++;
5120 }
5121 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5122 str = str_parms_to_str(reply);
5123 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005124 voice_extn_out_get_parameters(out, query, reply);
5125 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005127
Alexy Joseph62142aa2015-11-16 15:10:34 -08005128
5129 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5130 if (ret >= 0) {
5131 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305132 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5133 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005134 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305135 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005136 } else {
5137 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305138 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005139 }
5140 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005141 if (str)
5142 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005143 str = str_parms_to_str(reply);
5144 }
5145
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005146 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5147 if (ret >= 0) {
5148 value[0] = '\0';
5149 i = 0;
5150 first = true;
5151 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005152 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5153 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005154 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005155 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005156 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005157 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005158 first = false;
5159 break;
5160 }
5161 }
5162 i++;
5163 }
5164 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005165 if (str)
5166 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005167 str = str_parms_to_str(reply);
5168 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005169
5170 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5171 if (ret >= 0) {
5172 value[0] = '\0';
5173 i = 0;
5174 first = true;
5175 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005176 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5177 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005178 if (!first) {
5179 strlcat(value, "|", sizeof(value));
5180 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005181 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005182 first = false;
5183 break;
5184 }
5185 }
5186 i++;
5187 }
5188 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5189 if (str)
5190 free(str);
5191 str = str_parms_to_str(reply);
5192 }
5193
Alexy Joseph98988832017-01-13 14:56:59 -08005194 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5195 //only low latency track supports suspend_resume
5196 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005197 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005198 if (str)
5199 free(str);
5200 str = str_parms_to_str(reply);
5201 }
5202
5203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005204 str_parms_destroy(query);
5205 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005206 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207 return str;
5208}
5209
5210static uint32_t out_get_latency(const struct audio_stream_out *stream)
5211{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005212 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005214 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215
Alexy Josephaa54c872014-12-03 02:46:47 -08005216 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305217 lock_output_stream(out);
5218 latency = audio_extn_utils_compress_get_dsp_latency(out);
5219 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005220 } else if ((out->realtime) ||
5221 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005222 // since the buffer won't be filled up faster than realtime,
5223 // return a smaller number
5224 if (out->config.rate)
5225 period_ms = (out->af_period_multiplier * out->config.period_size *
5226 1000) / (out->config.rate);
5227 else
5228 period_ms = 0;
5229 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005230 } else {
5231 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005232 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005233 }
5234
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005235 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005236 latency += audio_extn_a2dp_get_encoder_latency();
5237
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305238 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005239 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240}
5241
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305242static float AmpToDb(float amplification)
5243{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305244 float db = DSD_VOLUME_MIN_DB;
5245 if (amplification > 0) {
5246 db = 20 * log10(amplification);
5247 if(db < DSD_VOLUME_MIN_DB)
5248 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305249 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305250 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305251}
5252
Arun Mirpuri5d170872019-03-26 13:21:31 -07005253static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5254 float right)
5255{
5256 struct stream_out *out = (struct stream_out *)stream;
5257 long volume = 0;
5258 char mixer_ctl_name[128] = "";
5259 struct audio_device *adev = out->dev;
5260 struct mixer_ctl *ctl = NULL;
5261 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5262 PCM_PLAYBACK);
5263
5264 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5265 "Playback %d Volume", pcm_device_id);
5266 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5267 if (!ctl) {
5268 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5269 __func__, mixer_ctl_name);
5270 return -EINVAL;
5271 }
5272 if (left != right)
5273 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5274 __func__, left, right);
5275 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5276 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5277 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5278 __func__, mixer_ctl_name, volume);
5279 return -EINVAL;
5280 }
5281 return 0;
5282}
5283
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305284static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5285 float right)
5286{
5287 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305288 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305289 char mixer_ctl_name[128];
5290 struct audio_device *adev = out->dev;
5291 struct mixer_ctl *ctl;
5292 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5293 PCM_PLAYBACK);
5294
5295 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5296 "Compress Playback %d Volume", pcm_device_id);
5297 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5298 if (!ctl) {
5299 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5300 __func__, mixer_ctl_name);
5301 return -EINVAL;
5302 }
5303 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5304 __func__, mixer_ctl_name, left, right);
5305 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5306 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5307 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5308
5309 return 0;
5310}
5311
Zhou Song2b8f28f2017-09-11 10:51:38 +08005312static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5313 float right)
5314{
5315 struct stream_out *out = (struct stream_out *)stream;
5316 char mixer_ctl_name[] = "App Type Gain";
5317 struct audio_device *adev = out->dev;
5318 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305319 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005320
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005321 if (!is_valid_volume(left, right)) {
5322 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5323 __func__, left, right);
5324 return -EINVAL;
5325 }
5326
Zhou Song2b8f28f2017-09-11 10:51:38 +08005327 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5328 if (!ctl) {
5329 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5330 __func__, mixer_ctl_name);
5331 return -EINVAL;
5332 }
5333
5334 set_values[0] = 0; //0: Rx Session 1:Tx Session
5335 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305336 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5337 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005338
5339 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5340 return 0;
5341}
5342
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305343static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5344 float right)
5345{
5346 struct stream_out *out = (struct stream_out *)stream;
5347 /* Volume control for pcm playback */
5348 if (left != right) {
5349 return -EINVAL;
5350 } else {
5351 char mixer_ctl_name[128];
5352 struct audio_device *adev = out->dev;
5353 struct mixer_ctl *ctl;
5354 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5355 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5356 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5357 if (!ctl) {
5358 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5359 return -EINVAL;
5360 }
5361
5362 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5363 int ret = mixer_ctl_set_value(ctl, 0, volume);
5364 if (ret < 0) {
5365 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5366 return -EINVAL;
5367 }
5368
5369 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5370
5371 return 0;
5372 }
5373}
5374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375static int out_set_volume(struct audio_stream_out *stream, float left,
5376 float right)
5377{
Eric Laurenta9024de2013-04-04 09:19:12 -07005378 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005379 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305380 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005381
Arun Mirpuri5d170872019-03-26 13:21:31 -07005382 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005383 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5384 /* only take left channel into account: the API is for stereo anyway */
5385 out->muted = (left == 0.0f);
5386 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005387 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305388 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005389 /*
5390 * Set mute or umute on HDMI passthrough stream.
5391 * Only take left channel into account.
5392 * Mute is 0 and unmute 1
5393 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305394 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305395 } else if (out->format == AUDIO_FORMAT_DSD){
5396 char mixer_ctl_name[128] = "DSD Volume";
5397 struct audio_device *adev = out->dev;
5398 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5399
5400 if (!ctl) {
5401 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5402 __func__, mixer_ctl_name);
5403 return -EINVAL;
5404 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305405 volume[0] = (long)(AmpToDb(left));
5406 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305407 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5408 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005409 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005410 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005411 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5412 struct listnode *node = NULL;
5413 list_for_each(node, &adev->active_outputs_list) {
5414 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5415 streams_output_ctxt_t,
5416 list);
5417 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5418 out->volume_l = out_ctxt->output->volume_l;
5419 out->volume_r = out_ctxt->output->volume_r;
5420 }
5421 }
5422 if (!out->a2dp_compress_mute) {
5423 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5424 }
5425 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005426 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305427 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005428 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305429 if (!out->a2dp_compress_mute)
5430 ret = out_set_compr_volume(stream, left, right);
5431 out->volume_l = left;
5432 out->volume_r = right;
5433 pthread_mutex_unlock(&out->compr_mute_lock);
5434 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005435 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005436 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005437 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5438 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5439 if (!out->standby) {
5440 audio_extn_utils_send_app_type_gain(out->dev,
5441 out->app_type_cfg.app_type,
5442 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005443 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005444 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005445 out->volume_l = left;
5446 out->volume_r = right;
5447 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005448 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5449 ALOGV("%s: MMAP set volume called", __func__);
5450 if (!out->standby)
5451 ret = out_set_mmap_volume(stream, left, right);
5452 out->volume_l = left;
5453 out->volume_r = right;
5454 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305455 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305456 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5457 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305458 /* Volume control for pcm playback */
5459 if (!out->standby)
5460 ret = out_set_pcm_volume(stream, left, right);
5461 else
5462 out->apply_volume = true;
5463
5464 out->volume_l = left;
5465 out->volume_r = right;
5466 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005467 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5468 ALOGV("%s: bus device set volume called", __func__);
5469 if (!out->standby)
5470 ret = out_set_pcm_volume(stream, left, right);
5471 out->volume_l = left;
5472 out->volume_r = right;
5473 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005474 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 return -ENOSYS;
5477}
5478
Zhou Songc9672822017-08-16 16:01:39 +08005479static void update_frames_written(struct stream_out *out, size_t bytes)
5480{
5481 size_t bpf = 0;
5482
5483 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5484 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5485 bpf = 1;
5486 else if (!is_offload_usecase(out->usecase))
5487 bpf = audio_bytes_per_sample(out->format) *
5488 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005489
5490 pthread_mutex_lock(&out->position_query_lock);
5491 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005492 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005493 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5494 }
5495 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005496}
5497
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005498int split_and_write_audio_haptic_data(struct stream_out *out,
5499 const void *buffer, size_t bytes_to_write)
5500{
5501 struct audio_device *adev = out->dev;
5502
5503 int ret = 0;
5504 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5505 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5506 size_t frame_size = channel_count * bytes_per_sample;
5507 size_t frame_count = bytes_to_write / frame_size;
5508
5509 bool force_haptic_path =
5510 property_get_bool("vendor.audio.test_haptic", false);
5511
5512 // extract Haptics data from Audio buffer
5513 bool alloc_haptic_buffer = false;
5514 int haptic_channel_count = adev->haptics_config.channels;
5515 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5516 size_t audio_frame_size = frame_size - haptic_frame_size;
5517 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5518
5519 if (adev->haptic_buffer == NULL) {
5520 alloc_haptic_buffer = true;
5521 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5522 free(adev->haptic_buffer);
5523 adev->haptic_buffer_size = 0;
5524 alloc_haptic_buffer = true;
5525 }
5526
5527 if (alloc_haptic_buffer) {
5528 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005529 if(adev->haptic_buffer == NULL) {
5530 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5531 return -ENOMEM;
5532 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005533 adev->haptic_buffer_size = total_haptic_buffer_size;
5534 }
5535
5536 size_t src_index = 0, aud_index = 0, hap_index = 0;
5537 uint8_t *audio_buffer = (uint8_t *)buffer;
5538 uint8_t *haptic_buffer = adev->haptic_buffer;
5539
5540 // This is required for testing only. This works for stereo data only.
5541 // One channel is fed to audio stream and other to haptic stream for testing.
5542 if (force_haptic_path)
5543 audio_frame_size = haptic_frame_size = bytes_per_sample;
5544
5545 for (size_t i = 0; i < frame_count; i++) {
5546 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5547 audio_frame_size);
5548 aud_index += audio_frame_size;
5549 src_index += audio_frame_size;
5550
5551 if (adev->haptic_pcm)
5552 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5553 haptic_frame_size);
5554 hap_index += haptic_frame_size;
5555 src_index += haptic_frame_size;
5556
5557 // This is required for testing only.
5558 // Discard haptic channel data.
5559 if (force_haptic_path)
5560 src_index += haptic_frame_size;
5561 }
5562
5563 // write to audio pipeline
5564 ret = pcm_write(out->pcm, (void *)audio_buffer,
5565 frame_count * audio_frame_size);
5566
5567 // write to haptics pipeline
5568 if (adev->haptic_pcm)
5569 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5570 frame_count * haptic_frame_size);
5571
5572 return ret;
5573}
5574
Aalique Grahame22e49102018-12-18 14:23:57 -08005575#ifdef NO_AUDIO_OUT
5576static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5577 const void *buffer __unused, size_t bytes)
5578{
5579 struct stream_out *out = (struct stream_out *)stream;
5580
5581 /* No Output device supported other than BT for playback.
5582 * Sleep for the amount of buffer duration
5583 */
5584 lock_output_stream(out);
5585 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5586 (const struct audio_stream_out *)&out->stream) /
5587 out_get_sample_rate(&out->stream.common));
5588 pthread_mutex_unlock(&out->lock);
5589 return bytes;
5590}
5591#endif
5592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005593static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5594 size_t bytes)
5595{
5596 struct stream_out *out = (struct stream_out *)stream;
5597 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005598 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305599 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005600 const size_t frame_size = audio_stream_out_frame_size(stream);
5601 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305602 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005603 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604
Haynes Mathew George380745d2017-10-04 15:27:45 -07005605 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005606 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305607
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305608 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005609
Dhananjay Kumarac341582017-02-23 23:42:25 +05305610 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305611 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305612 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5613 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005614 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305615 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305616 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305617 ALOGD(" %s: sound card is not active/SSR state", __func__);
5618 ret= -EIO;
5619 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305620 }
5621 }
5622
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305623 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305624 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305625 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305626 goto exit;
5627 }
5628
Haynes Mathew George16081042017-05-31 17:16:49 -07005629 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5630 ret = -EINVAL;
5631 goto exit;
5632 }
5633
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005634 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305635 !out->is_iec61937_info_available) {
5636
5637 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5638 out->is_iec61937_info_available = true;
5639 } else if (audio_extn_passthru_is_enabled()) {
5640 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305641 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305642
5643 if((out->format == AUDIO_FORMAT_DTS) ||
5644 (out->format == AUDIO_FORMAT_DTS_HD)) {
5645 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5646 buffer, bytes);
5647 if (ret) {
5648 if (ret != -ENOSYS) {
5649 out->is_iec61937_info_available = false;
5650 ALOGD("iec61937 transmission info not yet updated retry");
5651 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305652 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305653 /* if stream has started and after that there is
5654 * stream config change (iec transmission config)
5655 * then trigger select_device to update backend configuration.
5656 */
5657 out->stream_config_changed = true;
5658 pthread_mutex_lock(&adev->lock);
5659 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305660 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005661 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305662 ret = -EINVAL;
5663 goto exit;
5664 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305665 pthread_mutex_unlock(&adev->lock);
5666 out->stream_config_changed = false;
5667 out->is_iec61937_info_available = true;
5668 }
5669 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305670
Meng Wang4c32fb42020-01-16 17:57:11 +08005671#ifdef AUDIO_GKI_ENABLED
5672 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5673 compr_passthr = out->compr_config.codec->reserved[0];
5674#else
5675 compr_passthr = out->compr_config.codec->compr_passthr;
5676#endif
5677
Garmond Leung317cbf12017-09-13 16:20:50 -07005678 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005679 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305680 (out->is_iec61937_info_available == true)) {
5681 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5682 ret = -EINVAL;
5683 goto exit;
5684 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305685 }
5686 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305687
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005688 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005689 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005690 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5691 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305692 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305693 ret = -EIO;
5694 goto exit;
5695 }
5696 }
5697 }
5698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005699 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005700 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005701 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005702 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5703 ret = voice_extn_compress_voip_start_output_stream(out);
5704 else
5705 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005707 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005709 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005710 goto exit;
5711 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305712 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005713 if (last_known_cal_step != -1) {
5714 ALOGD("%s: retry previous failed cal level set", __func__);
5715 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305716 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005717 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305718
5719 if ((out->is_iec61937_info_available == true) &&
5720 (audio_extn_passthru_is_passthrough_stream(out))&&
5721 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5722 ret = -EINVAL;
5723 goto exit;
5724 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305725 if (out->set_dual_mono)
5726 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005728
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005729 if (adev->is_channel_status_set == false &&
5730 compare_device_type(&out->device_list,
5731 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005732 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305733 adev->is_channel_status_set = true;
5734 }
5735
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305736 if ((adev->use_old_pspd_mix_ctrl == true) &&
5737 (out->pspd_coeff_sent == false)) {
5738 /*
5739 * Need to resend pspd coefficients after stream started for
5740 * older kernel version as it does not save the coefficients
5741 * and also stream has to be started for coeff to apply.
5742 */
5743 usecase = get_usecase_from_list(adev, out->usecase);
5744 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305745 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305746 out->pspd_coeff_sent = true;
5747 }
5748 }
5749
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005750 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005751 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005752 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005753 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005754 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5755 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305756 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5757 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005758 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305759 out->send_next_track_params = false;
5760 out->is_compr_metadata_avail = false;
5761 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005762 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305763 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305764 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005765
Ashish Jain83a6cc22016-06-28 14:34:17 +05305766 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305767 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305768 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305769 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005770 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305771 return -EINVAL;
5772 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305773 audio_format_t dst_format = out->hal_op_format;
5774 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305775
Dieter Luecking5d57def2018-09-07 14:23:37 +02005776 /* prevent division-by-zero */
5777 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5778 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5779 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5780 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305781 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005782 ATRACE_END();
5783 return -EINVAL;
5784 }
5785
Ashish Jainf1eaa582016-05-23 20:54:24 +05305786 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5787 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5788
Ashish Jain83a6cc22016-06-28 14:34:17 +05305789 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305790 dst_format,
5791 buffer,
5792 src_format,
5793 frames);
5794
Ashish Jain83a6cc22016-06-28 14:34:17 +05305795 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305796 bytes_to_write);
5797
5798 /*Convert written bytes in audio flinger format*/
5799 if (ret > 0)
5800 ret = ((ret * format_to_bitwidth_table[out->format]) /
5801 format_to_bitwidth_table[dst_format]);
5802 }
5803 } else
5804 ret = compress_write(out->compr, buffer, bytes);
5805
Zhou Songc9672822017-08-16 16:01:39 +08005806 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5807 update_frames_written(out, bytes);
5808
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305809 if (ret < 0)
5810 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005811 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305812 /*msg to cb thread only if non blocking write is enabled*/
5813 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305814 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005815 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305816 } else if (-ENETRESET == ret) {
5817 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305818 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305819 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305820 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005821 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305822 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005823 }
Ashish Jain5106d362016-05-11 19:23:33 +05305824
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305825 /* Call compr start only when non-zero bytes of data is there to be rendered */
5826 if (!out->playback_started && ret > 0) {
5827 int status = compress_start(out->compr);
5828 if (status < 0) {
5829 ret = status;
5830 ALOGE("%s: compr start failed with err %d", __func__, errno);
5831 goto exit;
5832 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005833 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005834 out->playback_started = 1;
5835 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005836
5837 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5838 popcount(out->channel_mask),
5839 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005840 }
5841 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005842 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005843 return ret;
5844 } else {
5845 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005846 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005847 if (out->muted)
5848 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005849 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5850 __func__, frames, frame_size, bytes_to_write);
5851
Aalique Grahame22e49102018-12-18 14:23:57 -08005852 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005853 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5854 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5855 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005856 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5857 int16_t *src = (int16_t *)buffer;
5858 int16_t *dst = (int16_t *)buffer;
5859
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005860 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005861 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005862 "out_write called for %s use case with wrong properties",
5863 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005864
5865 /*
5866 * FIXME: this can be removed once audio flinger mixer supports
5867 * mono output
5868 */
5869
5870 /*
5871 * Code below goes over each frame in the buffer and adds both
5872 * L and R samples and then divides by 2 to convert to mono
5873 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005874 if (channel_count == 2) {
5875 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5876 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5877 }
5878 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005879 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005880 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305881 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005882
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005883 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005884
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005885 if (out->config.rate)
5886 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5887 out->config.rate;
5888
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005889 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005890 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5891
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005892 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005893 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005894 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305895 out->convert_buffer != NULL) {
5896
5897 memcpy_by_audio_format(out->convert_buffer,
5898 out->hal_op_format,
5899 buffer,
5900 out->hal_ip_format,
5901 out->config.period_size * out->config.channels);
5902
5903 ret = pcm_write(out->pcm, out->convert_buffer,
5904 (out->config.period_size *
5905 out->config.channels *
5906 format_to_bitwidth_table[out->hal_op_format]));
5907 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305908 /*
5909 * To avoid underrun in DSP when the application is not pumping
5910 * data at required rate, check for the no. of bytes and ignore
5911 * pcm_write if it is less than actual buffer size.
5912 * It is a work around to a change in compress VOIP driver.
5913 */
5914 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5915 bytes < (out->config.period_size * out->config.channels *
5916 audio_bytes_per_sample(out->format))) {
5917 size_t voip_buf_size =
5918 out->config.period_size * out->config.channels *
5919 audio_bytes_per_sample(out->format);
5920 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5921 __func__, bytes, voip_buf_size);
5922 usleep(((uint64_t)voip_buf_size - bytes) *
5923 1000000 / audio_stream_out_frame_size(stream) /
5924 out_get_sample_rate(&out->stream.common));
5925 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005926 } else {
5927 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5928 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5929 else
5930 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5931 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305932 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005933
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005934 release_out_focus(out);
5935
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305936 if (ret < 0)
5937 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005938 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305939 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005941 }
5942
5943exit:
Zhou Songc9672822017-08-16 16:01:39 +08005944 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305945 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305946 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005948 pthread_mutex_unlock(&out->lock);
5949
5950 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005951 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005952 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305953 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305954 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305955 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305956 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305957 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305958 out->standby = true;
5959 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305960 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005961 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5962 /* prevent division-by-zero */
5963 uint32_t stream_size = audio_stream_out_frame_size(stream);
5964 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005965
Dieter Luecking5d57def2018-09-07 14:23:37 +02005966 if ((stream_size == 0) || (srate == 0)) {
5967 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5968 ATRACE_END();
5969 return -EINVAL;
5970 }
5971 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5972 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005973 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305974 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005975 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005976 return ret;
5977 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005978 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005979 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005980 return bytes;
5981}
5982
5983static int out_get_render_position(const struct audio_stream_out *stream,
5984 uint32_t *dsp_frames)
5985{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005986 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005987
5988 if (dsp_frames == NULL)
5989 return -EINVAL;
5990
5991 *dsp_frames = 0;
5992 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005993 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305994
5995 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5996 * this operation and adev_close_output_stream(where out gets reset).
5997 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305998 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005999 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306000 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006001 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306002 return 0;
6003 }
6004
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006005 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306006 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306007 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306009 if (ret < 0)
6010 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006011 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306012 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306014 if (-ENETRESET == ret) {
6015 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306016 out->card_status = CARD_STATUS_OFFLINE;
6017 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306018 } else if(ret < 0) {
6019 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306020 ret = -EINVAL;
6021 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306022 /*
6023 * Handle corner case where compress session is closed during SSR
6024 * and timestamp is queried
6025 */
6026 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306027 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306028 } else if (out->prev_card_status_offline) {
6029 ALOGE("ERROR: previously sound card was offline,return error");
6030 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306031 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306032 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006033 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306034 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306035 pthread_mutex_unlock(&out->lock);
6036 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006037 } else if (audio_is_linear_pcm(out->format)) {
6038 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006039 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006040 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006041 } else
6042 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006043}
6044
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006045static int out_add_audio_effect(const struct audio_stream *stream __unused,
6046 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006047{
6048 return 0;
6049}
6050
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006051static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6052 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006053{
6054 return 0;
6055}
6056
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006057static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6058 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006059{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306060 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006061}
6062
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006063static int out_get_presentation_position(const struct audio_stream_out *stream,
6064 uint64_t *frames, struct timespec *timestamp)
6065{
6066 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306067 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006068 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006069
Ashish Jain5106d362016-05-11 19:23:33 +05306070 /* below piece of code is not guarded against any lock because audioFliner serializes
6071 * this operation and adev_close_output_stream( where out gets reset).
6072 */
6073 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306074 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006075 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306076 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6077 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6078 return 0;
6079 }
6080
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006081 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006082
Ashish Jain5106d362016-05-11 19:23:33 +05306083 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6084 ret = compress_get_tstamp(out->compr, &dsp_frames,
6085 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006086 // Adjustment accounts for A2dp encoder latency with offload usecases
6087 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006088 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006089 unsigned long offset =
6090 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6091 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6092 }
Ashish Jain5106d362016-05-11 19:23:33 +05306093 ALOGVV("%s rendered frames %ld sample_rate %d",
6094 __func__, dsp_frames, out->sample_rate);
6095 *frames = dsp_frames;
6096 if (ret < 0)
6097 ret = -errno;
6098 if (-ENETRESET == ret) {
6099 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306100 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306101 ret = -EINVAL;
6102 } else
6103 ret = 0;
6104 /* this is the best we can do */
6105 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006106 } else {
6107 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006108 unsigned int avail;
6109 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6110 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006111
6112 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006113 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006114
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006115 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6116 if (out->written >= frames_temp)
6117 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006118
Weiyin Jiangd4633762018-03-16 12:05:03 +08006119 // This adjustment accounts for buffering after app processor.
6120 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006121 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6122 if (signed_frames >= frames_temp)
6123 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006124
Weiyin Jiangd4633762018-03-16 12:05:03 +08006125 // Adjustment accounts for A2dp encoder latency with non offload usecases
6126 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006127 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006128 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6129 if (signed_frames >= frames_temp)
6130 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006131 }
6132
6133 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006134 *frames = signed_frames;
6135 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006136 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306137 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306138 *frames = out->written;
6139 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306140 if (is_offload_usecase(out->usecase))
6141 ret = -EINVAL;
6142 else
6143 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006144 }
6145 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006146 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006147 return ret;
6148}
6149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006150static int out_set_callback(struct audio_stream_out *stream,
6151 stream_callback_t callback, void *cookie)
6152{
6153 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006154 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006155
6156 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006157 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006158 out->client_callback = callback;
6159 out->client_cookie = cookie;
6160 if (out->adsp_hdlr_stream_handle) {
6161 ret = audio_extn_adsp_hdlr_stream_set_callback(
6162 out->adsp_hdlr_stream_handle,
6163 callback,
6164 cookie);
6165 if (ret)
6166 ALOGW("%s:adsp hdlr callback registration failed %d",
6167 __func__, ret);
6168 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006169 pthread_mutex_unlock(&out->lock);
6170 return 0;
6171}
6172
6173static int out_pause(struct audio_stream_out* stream)
6174{
6175 struct stream_out *out = (struct stream_out *)stream;
6176 int status = -ENOSYS;
6177 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006178 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006179 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006180 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006181 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306182 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306183 status = compress_pause(out->compr);
6184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006185 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006186
Mingming Yin21854652016-04-13 11:54:02 -07006187 if (audio_extn_passthru_is_active()) {
6188 ALOGV("offload use case, pause passthru");
6189 audio_extn_passthru_on_pause(out);
6190 }
6191
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306192 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006193 audio_extn_dts_notify_playback_state(out->usecase, 0,
6194 out->sample_rate, popcount(out->channel_mask),
6195 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006196 }
6197 pthread_mutex_unlock(&out->lock);
6198 }
6199 return status;
6200}
6201
6202static int out_resume(struct audio_stream_out* stream)
6203{
6204 struct stream_out *out = (struct stream_out *)stream;
6205 int status = -ENOSYS;
6206 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006207 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006208 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006209 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006210 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006211 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306212 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306213 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006214 }
6215 if (!status) {
6216 out->offload_state = OFFLOAD_STATE_PLAYING;
6217 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306218 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006219 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6220 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006221 }
6222 pthread_mutex_unlock(&out->lock);
6223 }
6224 return status;
6225}
6226
6227static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6228{
6229 struct stream_out *out = (struct stream_out *)stream;
6230 int status = -ENOSYS;
6231 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006232 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006233 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006234 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6235 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6236 else
6237 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6238 pthread_mutex_unlock(&out->lock);
6239 }
6240 return status;
6241}
6242
6243static int out_flush(struct audio_stream_out* stream)
6244{
6245 struct stream_out *out = (struct stream_out *)stream;
6246 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006247 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006248 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006249 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006250 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6251 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006252 } else {
6253 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6254 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006255 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006256 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006257 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006258 return 0;
6259 }
6260 return -ENOSYS;
6261}
6262
Haynes Mathew George16081042017-05-31 17:16:49 -07006263static int out_stop(const struct audio_stream_out* stream)
6264{
6265 struct stream_out *out = (struct stream_out *)stream;
6266 struct audio_device *adev = out->dev;
6267 int ret = -ENOSYS;
6268
6269 ALOGV("%s", __func__);
6270 pthread_mutex_lock(&adev->lock);
6271 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6272 out->playback_started && out->pcm != NULL) {
6273 pcm_stop(out->pcm);
6274 ret = stop_output_stream(out);
6275 out->playback_started = false;
6276 }
6277 pthread_mutex_unlock(&adev->lock);
6278 return ret;
6279}
6280
6281static int out_start(const struct audio_stream_out* stream)
6282{
6283 struct stream_out *out = (struct stream_out *)stream;
6284 struct audio_device *adev = out->dev;
6285 int ret = -ENOSYS;
6286
6287 ALOGV("%s", __func__);
6288 pthread_mutex_lock(&adev->lock);
6289 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6290 !out->playback_started && out->pcm != NULL) {
6291 ret = start_output_stream(out);
6292 if (ret == 0) {
6293 out->playback_started = true;
6294 }
6295 }
6296 pthread_mutex_unlock(&adev->lock);
6297 return ret;
6298}
6299
6300/*
6301 * Modify config->period_count based on min_size_frames
6302 */
6303static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6304{
6305 int periodCountRequested = (min_size_frames + config->period_size - 1)
6306 / config->period_size;
6307 int periodCount = MMAP_PERIOD_COUNT_MIN;
6308
6309 ALOGV("%s original config.period_size = %d config.period_count = %d",
6310 __func__, config->period_size, config->period_count);
6311
6312 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6313 periodCount *= 2;
6314 }
6315 config->period_count = periodCount;
6316
6317 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6318}
6319
Phil Burkfe17efd2019-03-25 10:23:35 -07006320// Read offset for the positional timestamp from a persistent vendor property.
6321// This is to workaround apparent inaccuracies in the timing information that
6322// is used by the AAudio timing model. The inaccuracies can cause glitches.
6323static int64_t get_mmap_out_time_offset() {
6324 const int32_t kDefaultOffsetMicros = 0;
6325 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006326 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006327 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6328 return mmap_time_offset_micros * (int64_t)1000;
6329}
6330
Haynes Mathew George16081042017-05-31 17:16:49 -07006331static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6332 int32_t min_size_frames,
6333 struct audio_mmap_buffer_info *info)
6334{
6335 struct stream_out *out = (struct stream_out *)stream;
6336 struct audio_device *adev = out->dev;
6337 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006338 unsigned int offset1 = 0;
6339 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006340 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006341 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006342 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006343
Arun Mirpuri5d170872019-03-26 13:21:31 -07006344 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306345 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006346 pthread_mutex_lock(&adev->lock);
6347
Sharad Sanglec6f32552018-05-04 16:15:38 +05306348 if (CARD_STATUS_OFFLINE == out->card_status ||
6349 CARD_STATUS_OFFLINE == adev->card_status) {
6350 ALOGW("out->card_status or adev->card_status offline, try again");
6351 ret = -EIO;
6352 goto exit;
6353 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006354 if (info == NULL || min_size_frames == 0) {
6355 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6356 ret = -EINVAL;
6357 goto exit;
6358 }
6359 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6360 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6361 ret = -ENOSYS;
6362 goto exit;
6363 }
6364 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6365 if (out->pcm_device_id < 0) {
6366 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6367 __func__, out->pcm_device_id, out->usecase);
6368 ret = -EINVAL;
6369 goto exit;
6370 }
6371
6372 adjust_mmap_period_count(&out->config, min_size_frames);
6373
Arun Mirpuri5d170872019-03-26 13:21:31 -07006374 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006375 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6376 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6377 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306378 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306379 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6380 out->card_status = CARD_STATUS_OFFLINE;
6381 adev->card_status = CARD_STATUS_OFFLINE;
6382 ret = -EIO;
6383 goto exit;
6384 }
6385
Haynes Mathew George16081042017-05-31 17:16:49 -07006386 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6387 step = "open";
6388 ret = -ENODEV;
6389 goto exit;
6390 }
6391 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6392 if (ret < 0) {
6393 step = "begin";
6394 goto exit;
6395 }
6396 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006397 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006398 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006399 ret = platform_get_mmap_data_fd(adev->platform,
6400 out->pcm_device_id, 0 /*playback*/,
6401 &info->shared_memory_fd,
6402 &mmap_size);
6403 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006404 // Fall back to non exclusive mode
6405 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6406 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006407 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6408 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6409
Arun Mirpuri5d170872019-03-26 13:21:31 -07006410 if (mmap_size < buffer_size) {
6411 step = "mmap";
6412 goto exit;
6413 }
6414 // FIXME: indicate exclusive mode support by returning a negative buffer size
6415 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006416 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006417 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006418 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006419
6420 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6421 if (ret < 0) {
6422 step = "commit";
6423 goto exit;
6424 }
6425
Phil Burkfe17efd2019-03-25 10:23:35 -07006426 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6427
Haynes Mathew George16081042017-05-31 17:16:49 -07006428 out->standby = false;
6429 ret = 0;
6430
Arun Mirpuri5d170872019-03-26 13:21:31 -07006431 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006432 __func__, info->shared_memory_address, info->buffer_size_frames);
6433
6434exit:
6435 if (ret != 0) {
6436 if (out->pcm == NULL) {
6437 ALOGE("%s: %s - %d", __func__, step, ret);
6438 } else {
6439 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6440 pcm_close(out->pcm);
6441 out->pcm = NULL;
6442 }
6443 }
6444 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306445 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006446 return ret;
6447}
6448
6449static int out_get_mmap_position(const struct audio_stream_out *stream,
6450 struct audio_mmap_position *position)
6451{
6452 struct stream_out *out = (struct stream_out *)stream;
6453 ALOGVV("%s", __func__);
6454 if (position == NULL) {
6455 return -EINVAL;
6456 }
6457 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006458 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006459 return -ENOSYS;
6460 }
6461 if (out->pcm == NULL) {
6462 return -ENOSYS;
6463 }
6464
6465 struct timespec ts = { 0, 0 };
6466 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6467 if (ret < 0) {
6468 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6469 return ret;
6470 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006471 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6472 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006473 return 0;
6474}
6475
6476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006477/** audio_stream_in implementation **/
6478static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6479{
6480 struct stream_in *in = (struct stream_in *)stream;
6481
6482 return in->config.rate;
6483}
6484
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006485static int in_set_sample_rate(struct audio_stream *stream __unused,
6486 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006487{
6488 return -ENOSYS;
6489}
6490
6491static size_t in_get_buffer_size(const struct audio_stream *stream)
6492{
6493 struct stream_in *in = (struct stream_in *)stream;
6494
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006495 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6496 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006497 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6498 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306499 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306500 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006501
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006502 return in->config.period_size * in->af_period_multiplier *
6503 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006504}
6505
6506static uint32_t in_get_channels(const struct audio_stream *stream)
6507{
6508 struct stream_in *in = (struct stream_in *)stream;
6509
6510 return in->channel_mask;
6511}
6512
6513static audio_format_t in_get_format(const struct audio_stream *stream)
6514{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006515 struct stream_in *in = (struct stream_in *)stream;
6516
6517 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006518}
6519
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006520static int in_set_format(struct audio_stream *stream __unused,
6521 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006522{
6523 return -ENOSYS;
6524}
6525
6526static int in_standby(struct audio_stream *stream)
6527{
6528 struct stream_in *in = (struct stream_in *)stream;
6529 struct audio_device *adev = in->dev;
6530 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306531 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6532 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006533 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306534
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006535 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006536 if (!in->standby && in->is_st_session) {
6537 ALOGD("%s: sound trigger pcm stop lab", __func__);
6538 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006539 if (adev->num_va_sessions > 0)
6540 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006541 in->standby = 1;
6542 }
6543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006544 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006545 if (adev->adm_deregister_stream)
6546 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6547
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006548 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006549 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006550 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006551 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006552 voice_extn_compress_voip_close_input_stream(stream);
6553 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006554 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6555 do_stop = in->capture_started;
6556 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006557 if (in->mmap_shared_memory_fd >= 0) {
6558 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6559 __func__, in->mmap_shared_memory_fd);
6560 close(in->mmap_shared_memory_fd);
6561 in->mmap_shared_memory_fd = -1;
6562 }
Zhou Songa8895042016-07-05 17:54:22 +08006563 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306564 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306565 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006566 }
6567
Arun Mirpuri5d170872019-03-26 13:21:31 -07006568 if (in->pcm) {
6569 ATRACE_BEGIN("pcm_in_close");
6570 pcm_close(in->pcm);
6571 ATRACE_END();
6572 in->pcm = NULL;
6573 }
6574
Carter Hsu2e429db2019-05-14 18:50:52 +08006575 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006576 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006577
George Gao3018ede2019-10-23 13:23:00 -07006578 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6579 if (adev->num_va_sessions > 0)
6580 adev->num_va_sessions--;
6581 }
Quinn Malef6050362019-01-30 15:55:40 -08006582
Eric Laurent150dbfe2013-02-27 14:31:02 -08006583 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584 }
6585 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006586 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006587 return status;
6588}
6589
Aalique Grahame22e49102018-12-18 14:23:57 -08006590static int in_dump(const struct audio_stream *stream,
6591 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006592{
Aalique Grahame22e49102018-12-18 14:23:57 -08006593 struct stream_in *in = (struct stream_in *)stream;
6594
6595 // We try to get the lock for consistency,
6596 // but it isn't necessary for these variables.
6597 // If we're not in standby, we may be blocked on a read.
6598 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6599 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6600 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6601 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6602
6603 if (locked) {
6604 pthread_mutex_unlock(&in->lock);
6605 }
6606
6607 // dump error info
6608 (void)error_log_dump(
6609 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006611 return 0;
6612}
6613
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306614static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6615{
6616 if (!stream || !parms)
6617 return;
6618
6619 struct stream_in *in = (struct stream_in *)stream;
6620 struct audio_device *adev = in->dev;
6621
6622 card_status_t status;
6623 int card;
6624 if (parse_snd_card_status(parms, &card, &status) < 0)
6625 return;
6626
6627 pthread_mutex_lock(&adev->lock);
6628 bool valid_cb = (card == adev->snd_card);
6629 pthread_mutex_unlock(&adev->lock);
6630
6631 if (!valid_cb)
6632 return;
6633
6634 lock_input_stream(in);
6635 if (in->card_status != status)
6636 in->card_status = status;
6637 pthread_mutex_unlock(&in->lock);
6638
6639 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6640 use_case_table[in->usecase],
6641 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6642
6643 // a better solution would be to report error back to AF and let
6644 // it put the stream to standby
6645 if (status == CARD_STATUS_OFFLINE)
6646 in_standby(&in->stream.common);
6647
6648 return;
6649}
6650
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006651int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006652 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006653 audio_source_t source)
6654{
6655 struct audio_device *adev = in->dev;
6656 int ret = 0;
6657
6658 lock_input_stream(in);
6659 pthread_mutex_lock(&adev->lock);
6660
6661 /* no audio source uses val == 0 */
6662 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6663 in->source = source;
6664 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6665 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6666 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6667 (in->config.rate == 8000 || in->config.rate == 16000 ||
6668 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6669 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6670 ret = voice_extn_compress_voip_open_input_stream(in);
6671 if (ret != 0) {
6672 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6673 __func__, ret);
6674 }
6675 }
6676 }
6677
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006678 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6679 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006680 // Workaround: If routing to an non existing usb device, fail gracefully
6681 // The routing request will otherwise block during 10 second
6682 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006683 struct str_parms *usb_addr =
6684 str_parms_create_str(get_usb_device_address(devices));
6685 if (is_usb_in_device_type(devices) && usb_addr &&
6686 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006687 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6688 ret = -ENOSYS;
6689 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006690 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006691 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006692 if (!in->standby && !in->is_st_session) {
6693 ALOGV("update input routing change");
6694 // inform adm before actual routing to prevent glitches.
6695 if (adev->adm_on_routing_change) {
6696 adev->adm_on_routing_change(adev->adm_data,
6697 in->capture_handle);
6698 ret = select_devices(adev, in->usecase);
6699 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6700 adev->adm_routing_changed = true;
6701 }
6702 }
6703 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006704 if (usb_addr)
6705 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006706 }
6707 pthread_mutex_unlock(&adev->lock);
6708 pthread_mutex_unlock(&in->lock);
6709
6710 ALOGD("%s: exit: status(%d)", __func__, ret);
6711 return ret;
6712}
6713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6715{
6716 struct stream_in *in = (struct stream_in *)stream;
6717 struct audio_device *adev = in->dev;
6718 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006719 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006720 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306722 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723 parms = str_parms_create_str(kvpairs);
6724
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306725 if (!parms)
6726 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006727 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006728 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006729
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006730 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6731 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306732 strlcpy(in->profile, value, sizeof(in->profile));
6733 ALOGV("updating stream profile with value '%s'", in->profile);
6734 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6735 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006736 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306737 in->sample_rate, in->bit_width,
6738 in->profile, &in->app_type_cfg);
6739 }
6740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006741 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006742 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006743
6744 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306745error:
Eric Laurent994a6932013-07-17 11:51:42 -07006746 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006747 return ret;
6748}
6749
6750static char* in_get_parameters(const struct audio_stream *stream,
6751 const char *keys)
6752{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006753 struct stream_in *in = (struct stream_in *)stream;
6754 struct str_parms *query = str_parms_create_str(keys);
6755 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006756 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006757
6758 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006759 if (reply) {
6760 str_parms_destroy(reply);
6761 }
6762 if (query) {
6763 str_parms_destroy(query);
6764 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006765 ALOGE("in_get_parameters: failed to create query or reply");
6766 return NULL;
6767 }
6768
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006769 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006770
6771 voice_extn_in_get_parameters(in, query, reply);
6772
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006773 stream_get_parameter_channels(query, reply,
6774 &in->supported_channel_masks[0]);
6775 stream_get_parameter_formats(query, reply,
6776 &in->supported_formats[0]);
6777 stream_get_parameter_rates(query, reply,
6778 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006779 str = str_parms_to_str(reply);
6780 str_parms_destroy(query);
6781 str_parms_destroy(reply);
6782
6783 ALOGV("%s: exit: returns - %s", __func__, str);
6784 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785}
6786
Aalique Grahame22e49102018-12-18 14:23:57 -08006787static int in_set_gain(struct audio_stream_in *stream,
6788 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006789{
Aalique Grahame22e49102018-12-18 14:23:57 -08006790 struct stream_in *in = (struct stream_in *)stream;
6791 char mixer_ctl_name[128];
6792 struct mixer_ctl *ctl;
6793 int ctl_value;
6794
6795 ALOGV("%s: gain %f", __func__, gain);
6796
6797 if (stream == NULL)
6798 return -EINVAL;
6799
6800 /* in_set_gain() only used to silence MMAP capture for now */
6801 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6802 return -ENOSYS;
6803
6804 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6805
6806 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6807 if (!ctl) {
6808 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6809 __func__, mixer_ctl_name);
6810 return -ENOSYS;
6811 }
6812
6813 if (gain < RECORD_GAIN_MIN)
6814 gain = RECORD_GAIN_MIN;
6815 else if (gain > RECORD_GAIN_MAX)
6816 gain = RECORD_GAIN_MAX;
6817 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6818
6819 mixer_ctl_set_value(ctl, 0, ctl_value);
6820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006821 return 0;
6822}
6823
6824static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6825 size_t bytes)
6826{
6827 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306828
6829 if (in == NULL) {
6830 ALOGE("%s: stream_in ptr is NULL", __func__);
6831 return -EINVAL;
6832 }
6833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006834 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306835 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306836 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006837
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006838 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306839
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006840 if (in->is_st_session) {
6841 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6842 /* Read from sound trigger HAL */
6843 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006844 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006845 if (adev->num_va_sessions < UINT_MAX)
6846 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006847 in->standby = 0;
6848 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006849 pthread_mutex_unlock(&in->lock);
6850 return bytes;
6851 }
6852
Haynes Mathew George16081042017-05-31 17:16:49 -07006853 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6854 ret = -ENOSYS;
6855 goto exit;
6856 }
6857
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006858 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6859 !in->standby && adev->adm_routing_changed) {
6860 ret = -ENOSYS;
6861 goto exit;
6862 }
6863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006864 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006865 pthread_mutex_lock(&adev->lock);
6866 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6867 ret = voice_extn_compress_voip_start_input_stream(in);
6868 else
6869 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006870 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6871 if (adev->num_va_sessions < UINT_MAX)
6872 adev->num_va_sessions++;
6873 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006874 pthread_mutex_unlock(&adev->lock);
6875 if (ret != 0) {
6876 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 }
6878 in->standby = 0;
6879 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006880
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306881 /* Avoid read if capture_stopped is set */
6882 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6883 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6884 ret = -EINVAL;
6885 goto exit;
6886 }
6887
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006888 // what's the duration requested by the client?
6889 long ns = 0;
6890
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306891 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006892 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6893 in->config.rate;
6894
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006895 ret = request_in_focus(in, ns);
6896 if (ret != 0)
6897 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006898 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006899
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306900 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306901 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6902 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306903 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006904 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306905 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006906 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006907 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006908 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006909 } else if (audio_extn_ffv_get_stream() == in) {
6910 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306911 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006912 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306913 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6914 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6915 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6916 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306917 ret = -EINVAL;
6918 goto exit;
6919 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306920 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306921 ret = -errno;
6922 }
6923 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306924 /* bytes read is always set to bytes for non compress usecases */
6925 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006926 }
6927
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006928 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006930 /*
Quinn Malef6050362019-01-30 15:55:40 -08006931 * Instead of writing zeroes here, we could trust the hardware to always
6932 * provide zeroes when muted. This is also muted with voice recognition
6933 * usecases so that other clients do not have access to voice recognition
6934 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006935 */
Quinn Malef6050362019-01-30 15:55:40 -08006936 if ((ret == 0 && voice_get_mic_mute(adev) &&
6937 !voice_is_in_call_rec_stream(in) &&
6938 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6939 (adev->num_va_sessions &&
6940 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6941 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6942 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943 memset(buffer, 0, bytes);
6944
6945exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306946 frame_size = audio_stream_in_frame_size(stream);
6947 if (frame_size > 0)
6948 in->frames_read += bytes_read/frame_size;
6949
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006950 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306951 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006952 pthread_mutex_unlock(&in->lock);
6953
6954 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306955 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306956 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306957 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306958 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306959 in->standby = true;
6960 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306961 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05306962 bytes_read = bytes;
6963 memset(buffer, 0, bytes);
6964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006965 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006966 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6967 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006968 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306969 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306970 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006971 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306972 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973}
6974
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006975static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976{
6977 return 0;
6978}
6979
Aalique Grahame22e49102018-12-18 14:23:57 -08006980static int in_get_capture_position(const struct audio_stream_in *stream,
6981 int64_t *frames, int64_t *time)
6982{
6983 if (stream == NULL || frames == NULL || time == NULL) {
6984 return -EINVAL;
6985 }
6986 struct stream_in *in = (struct stream_in *)stream;
6987 int ret = -ENOSYS;
6988
6989 lock_input_stream(in);
6990 // note: ST sessions do not close the alsa pcm driver synchronously
6991 // on standby. Therefore, we may return an error even though the
6992 // pcm stream is still opened.
6993 if (in->standby) {
6994 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6995 "%s stream in standby but pcm not NULL for non ST session", __func__);
6996 goto exit;
6997 }
6998 if (in->pcm) {
6999 struct timespec timestamp;
7000 unsigned int avail;
7001 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7002 *frames = in->frames_read + avail;
7003 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7004 ret = 0;
7005 }
7006 }
7007exit:
7008 pthread_mutex_unlock(&in->lock);
7009 return ret;
7010}
7011
Carter Hsu2e429db2019-05-14 18:50:52 +08007012static int in_update_effect_list(bool add, effect_handle_t effect,
7013 struct listnode *head)
7014{
7015 struct listnode *node;
7016 struct in_effect_list *elist = NULL;
7017 struct in_effect_list *target = NULL;
7018 int ret = 0;
7019
7020 if (!head)
7021 return ret;
7022
7023 list_for_each(node, head) {
7024 elist = node_to_item(node, struct in_effect_list, list);
7025 if (elist->handle == effect) {
7026 target = elist;
7027 break;
7028 }
7029 }
7030
7031 if (add) {
7032 if (target) {
7033 ALOGD("effect %p already exist", effect);
7034 return ret;
7035 }
7036
7037 target = (struct in_effect_list *)
7038 calloc(1, sizeof(struct in_effect_list));
7039
7040 if (!target) {
7041 ALOGE("%s:fail to allocate memory", __func__);
7042 return -ENOMEM;
7043 }
7044
7045 target->handle = effect;
7046 list_add_tail(head, &target->list);
7047 } else {
7048 if (target) {
7049 list_remove(&target->list);
7050 free(target);
7051 }
7052 }
7053
7054 return ret;
7055}
7056
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007057static int add_remove_audio_effect(const struct audio_stream *stream,
7058 effect_handle_t effect,
7059 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007060{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007061 struct stream_in *in = (struct stream_in *)stream;
7062 int status = 0;
7063 effect_descriptor_t desc;
7064
7065 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007066 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7067
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007068 if (status != 0)
7069 return status;
7070
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007071 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007072 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007073 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007074 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7075 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007076 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007077
7078 in_update_effect_list(enable, effect, &in->aec_list);
7079 enable = !list_empty(&in->aec_list);
7080 if (enable == in->enable_aec)
7081 goto exit;
7082
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007083 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007084 ALOGD("AEC enable %d", enable);
7085
Aalique Grahame22e49102018-12-18 14:23:57 -08007086 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7087 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7088 in->dev->enable_voicerx = enable;
7089 struct audio_usecase *usecase;
7090 struct listnode *node;
7091 list_for_each(node, &in->dev->usecase_list) {
7092 usecase = node_to_item(node, struct audio_usecase, list);
7093 if (usecase->type == PCM_PLAYBACK)
7094 select_devices(in->dev, usecase->id);
7095 }
7096 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007097 if (!in->standby) {
7098 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7099 select_devices(in->dev, in->usecase);
7100 }
7101
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007102 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007103 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7104
7105 in_update_effect_list(enable, effect, &in->ns_list);
7106 enable = !list_empty(&in->ns_list);
7107 if (enable == in->enable_ns)
7108 goto exit;
7109
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007110 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007111 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007112 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007113 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7114 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007115 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7116 select_devices(in->dev, in->usecase);
7117 } else
7118 select_devices(in->dev, in->usecase);
7119 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007120 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007121exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007122 pthread_mutex_unlock(&in->dev->lock);
7123 pthread_mutex_unlock(&in->lock);
7124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125 return 0;
7126}
7127
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007128static int in_add_audio_effect(const struct audio_stream *stream,
7129 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007130{
Eric Laurent994a6932013-07-17 11:51:42 -07007131 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007132 return add_remove_audio_effect(stream, effect, true);
7133}
7134
7135static int in_remove_audio_effect(const struct audio_stream *stream,
7136 effect_handle_t effect)
7137{
Eric Laurent994a6932013-07-17 11:51:42 -07007138 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007139 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007140}
7141
Derek Chenf939fb72018-11-13 13:34:41 -08007142streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7143 audio_io_handle_t input)
7144{
7145 struct listnode *node;
7146
7147 list_for_each(node, &dev->active_inputs_list) {
7148 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7149 streams_input_ctxt_t,
7150 list);
7151 if (in_ctxt->input->capture_handle == input) {
7152 return in_ctxt;
7153 }
7154 }
7155 return NULL;
7156}
7157
7158streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7159 audio_io_handle_t output)
7160{
7161 struct listnode *node;
7162
7163 list_for_each(node, &dev->active_outputs_list) {
7164 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7165 streams_output_ctxt_t,
7166 list);
7167 if (out_ctxt->output->handle == output) {
7168 return out_ctxt;
7169 }
7170 }
7171 return NULL;
7172}
7173
Haynes Mathew George16081042017-05-31 17:16:49 -07007174static int in_stop(const struct audio_stream_in* stream)
7175{
7176 struct stream_in *in = (struct stream_in *)stream;
7177 struct audio_device *adev = in->dev;
7178
7179 int ret = -ENOSYS;
7180 ALOGV("%s", __func__);
7181 pthread_mutex_lock(&adev->lock);
7182 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7183 in->capture_started && in->pcm != NULL) {
7184 pcm_stop(in->pcm);
7185 ret = stop_input_stream(in);
7186 in->capture_started = false;
7187 }
7188 pthread_mutex_unlock(&adev->lock);
7189 return ret;
7190}
7191
7192static int in_start(const struct audio_stream_in* stream)
7193{
7194 struct stream_in *in = (struct stream_in *)stream;
7195 struct audio_device *adev = in->dev;
7196 int ret = -ENOSYS;
7197
7198 ALOGV("%s in %p", __func__, in);
7199 pthread_mutex_lock(&adev->lock);
7200 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7201 !in->capture_started && in->pcm != NULL) {
7202 if (!in->capture_started) {
7203 ret = start_input_stream(in);
7204 if (ret == 0) {
7205 in->capture_started = true;
7206 }
7207 }
7208 }
7209 pthread_mutex_unlock(&adev->lock);
7210 return ret;
7211}
7212
Phil Burke0a86d12019-02-16 22:28:11 -08007213// Read offset for the positional timestamp from a persistent vendor property.
7214// This is to workaround apparent inaccuracies in the timing information that
7215// is used by the AAudio timing model. The inaccuracies can cause glitches.
7216static int64_t in_get_mmap_time_offset() {
7217 const int32_t kDefaultOffsetMicros = 0;
7218 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007219 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007220 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7221 return mmap_time_offset_micros * (int64_t)1000;
7222}
7223
Haynes Mathew George16081042017-05-31 17:16:49 -07007224static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7225 int32_t min_size_frames,
7226 struct audio_mmap_buffer_info *info)
7227{
7228 struct stream_in *in = (struct stream_in *)stream;
7229 struct audio_device *adev = in->dev;
7230 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007231 unsigned int offset1 = 0;
7232 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007233 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007234 uint32_t mmap_size = 0;
7235 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007236
7237 pthread_mutex_lock(&adev->lock);
7238 ALOGV("%s in %p", __func__, in);
7239
Sharad Sanglec6f32552018-05-04 16:15:38 +05307240 if (CARD_STATUS_OFFLINE == in->card_status||
7241 CARD_STATUS_OFFLINE == adev->card_status) {
7242 ALOGW("in->card_status or adev->card_status offline, try again");
7243 ret = -EIO;
7244 goto exit;
7245 }
7246
Haynes Mathew George16081042017-05-31 17:16:49 -07007247 if (info == NULL || min_size_frames == 0) {
7248 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7249 ret = -EINVAL;
7250 goto exit;
7251 }
7252 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7253 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7254 ALOGV("%s in %p", __func__, in);
7255 ret = -ENOSYS;
7256 goto exit;
7257 }
7258 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7259 if (in->pcm_device_id < 0) {
7260 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7261 __func__, in->pcm_device_id, in->usecase);
7262 ret = -EINVAL;
7263 goto exit;
7264 }
7265
7266 adjust_mmap_period_count(&in->config, min_size_frames);
7267
7268 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7269 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7270 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7271 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307272 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307273 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7274 in->card_status = CARD_STATUS_OFFLINE;
7275 adev->card_status = CARD_STATUS_OFFLINE;
7276 ret = -EIO;
7277 goto exit;
7278 }
7279
Haynes Mathew George16081042017-05-31 17:16:49 -07007280 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7281 step = "open";
7282 ret = -ENODEV;
7283 goto exit;
7284 }
7285
7286 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7287 if (ret < 0) {
7288 step = "begin";
7289 goto exit;
7290 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007291
Arun Mirpuri5d170872019-03-26 13:21:31 -07007292 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7293 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7294 info->burst_size_frames = in->config.period_size;
7295 ret = platform_get_mmap_data_fd(adev->platform,
7296 in->pcm_device_id, 1 /*capture*/,
7297 &info->shared_memory_fd,
7298 &mmap_size);
7299 if (ret < 0) {
7300 // Fall back to non exclusive mode
7301 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7302 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007303 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7304 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7305
Arun Mirpuri5d170872019-03-26 13:21:31 -07007306 if (mmap_size < buffer_size) {
7307 step = "mmap";
7308 goto exit;
7309 }
7310 // FIXME: indicate exclusive mode support by returning a negative buffer size
7311 info->buffer_size_frames *= -1;
7312 }
7313
7314 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007315
7316 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7317 if (ret < 0) {
7318 step = "commit";
7319 goto exit;
7320 }
7321
Phil Burke0a86d12019-02-16 22:28:11 -08007322 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7323
Haynes Mathew George16081042017-05-31 17:16:49 -07007324 in->standby = false;
7325 ret = 0;
7326
7327 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7328 __func__, info->shared_memory_address, info->buffer_size_frames);
7329
7330exit:
7331 if (ret != 0) {
7332 if (in->pcm == NULL) {
7333 ALOGE("%s: %s - %d", __func__, step, ret);
7334 } else {
7335 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7336 pcm_close(in->pcm);
7337 in->pcm = NULL;
7338 }
7339 }
7340 pthread_mutex_unlock(&adev->lock);
7341 return ret;
7342}
7343
7344static int in_get_mmap_position(const struct audio_stream_in *stream,
7345 struct audio_mmap_position *position)
7346{
7347 struct stream_in *in = (struct stream_in *)stream;
7348 ALOGVV("%s", __func__);
7349 if (position == NULL) {
7350 return -EINVAL;
7351 }
7352 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7353 return -ENOSYS;
7354 }
7355 if (in->pcm == NULL) {
7356 return -ENOSYS;
7357 }
7358 struct timespec ts = { 0, 0 };
7359 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7360 if (ret < 0) {
7361 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7362 return ret;
7363 }
Phil Burke0a86d12019-02-16 22:28:11 -08007364 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7365 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007366 return 0;
7367}
7368
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307369static int in_get_active_microphones(const struct audio_stream_in *stream,
7370 struct audio_microphone_characteristic_t *mic_array,
7371 size_t *mic_count) {
7372 struct stream_in *in = (struct stream_in *)stream;
7373 struct audio_device *adev = in->dev;
7374 ALOGVV("%s", __func__);
7375
7376 lock_input_stream(in);
7377 pthread_mutex_lock(&adev->lock);
7378 int ret = platform_get_active_microphones(adev->platform,
7379 audio_channel_count_from_in_mask(in->channel_mask),
7380 in->usecase, mic_array, mic_count);
7381 pthread_mutex_unlock(&adev->lock);
7382 pthread_mutex_unlock(&in->lock);
7383
7384 return ret;
7385}
7386
7387static int adev_get_microphones(const struct audio_hw_device *dev,
7388 struct audio_microphone_characteristic_t *mic_array,
7389 size_t *mic_count) {
7390 struct audio_device *adev = (struct audio_device *)dev;
7391 ALOGVV("%s", __func__);
7392
7393 pthread_mutex_lock(&adev->lock);
7394 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7395 pthread_mutex_unlock(&adev->lock);
7396
7397 return ret;
7398}
juyuchendb308c22019-01-21 11:57:17 -07007399
7400static void in_update_sink_metadata(struct audio_stream_in *stream,
7401 const struct sink_metadata *sink_metadata) {
7402
7403 if (stream == NULL
7404 || sink_metadata == NULL
7405 || sink_metadata->tracks == NULL) {
7406 return;
7407 }
7408
7409 int error = 0;
7410 struct stream_in *in = (struct stream_in *)stream;
7411 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007412 struct listnode devices;
7413
7414 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007415
7416 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007417 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007418
7419 lock_input_stream(in);
7420 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007421 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007422
7423 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007424 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007425 && adev->voice_tx_output != NULL) {
7426 /* Use the rx device from afe-proxy record to route voice call because
7427 there is no routing if tx device is on primary hal and rx device
7428 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007429 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007430
7431 if (!voice_is_call_state_active(adev)) {
7432 if (adev->mode == AUDIO_MODE_IN_CALL) {
7433 adev->current_call_output = adev->voice_tx_output;
7434 error = voice_start_call(adev);
7435 if (error != 0)
7436 ALOGE("%s: start voice call failed %d", __func__, error);
7437 }
7438 } else {
7439 adev->current_call_output = adev->voice_tx_output;
7440 voice_update_devices_for_all_voice_usecases(adev);
7441 }
7442 }
7443
7444 pthread_mutex_unlock(&adev->lock);
7445 pthread_mutex_unlock(&in->lock);
7446}
7447
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307448int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007449 audio_io_handle_t handle,
7450 audio_devices_t devices,
7451 audio_output_flags_t flags,
7452 struct audio_config *config,
7453 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007454 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007455{
7456 struct audio_device *adev = (struct audio_device *)dev;
7457 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307458 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007459 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007460 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307461 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007462 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7463 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7464 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7465 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007466 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007467 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7468 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007469 bool force_haptic_path =
7470 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007471 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007472
kunleizdff872d2018-08-20 14:40:33 +08007473 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007474 is_usb_dev = false;
7475 devices = AUDIO_DEVICE_OUT_SPEAKER;
7476 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7477 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007478 if (config->format == AUDIO_FORMAT_DEFAULT)
7479 config->format = AUDIO_FORMAT_PCM_16_BIT;
7480 if (config->sample_rate == 0)
7481 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7482 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7483 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007484 }
7485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007486 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307487
Rahul Sharma99770982019-03-06 17:05:26 +05307488 pthread_mutex_lock(&adev->lock);
7489 if (out_get_stream(adev, handle) != NULL) {
7490 ALOGW("%s, output stream already opened", __func__);
7491 ret = -EEXIST;
7492 }
7493 pthread_mutex_unlock(&adev->lock);
7494 if (ret)
7495 return ret;
7496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007497 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7498
Mingming Yin3a941d42016-02-17 18:08:05 -08007499 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007500 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7501 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307502
7503
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007504 if (!out) {
7505 return -ENOMEM;
7506 }
7507
Haynes Mathew George204045b2015-02-25 20:32:03 -08007508 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007509 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307510 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007511 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007512 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007514 if (devices == AUDIO_DEVICE_NONE)
7515 devices = AUDIO_DEVICE_OUT_SPEAKER;
7516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007517 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007518 list_init(&out->device_list);
7519 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007520 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007521 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007522 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307523 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307524 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7525 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7526 else
7527 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007528 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007529 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007530 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307531 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307532 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307533 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007534 out->hal_output_suspend_supported = 0;
7535 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307536 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307537 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307538 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007539 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007540
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307541 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307542 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007543 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7544
Aalique Grahame22e49102018-12-18 14:23:57 -08007545 if (direct_dev &&
7546 (audio_is_linear_pcm(out->format) ||
7547 config->format == AUDIO_FORMAT_DEFAULT) &&
7548 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7549 audio_format_t req_format = config->format;
7550 audio_channel_mask_t req_channel_mask = config->channel_mask;
7551 uint32_t req_sample_rate = config->sample_rate;
7552
7553 pthread_mutex_lock(&adev->lock);
7554 if (is_hdmi) {
7555 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7556 ret = read_hdmi_sink_caps(out);
7557 if (config->sample_rate == 0)
7558 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7559 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7560 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7561 if (config->format == AUDIO_FORMAT_DEFAULT)
7562 config->format = AUDIO_FORMAT_PCM_16_BIT;
7563 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007564 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7565 &config->format,
7566 &out->supported_formats[0],
7567 MAX_SUPPORTED_FORMATS,
7568 &config->channel_mask,
7569 &out->supported_channel_masks[0],
7570 MAX_SUPPORTED_CHANNEL_MASKS,
7571 &config->sample_rate,
7572 &out->supported_sample_rates[0],
7573 MAX_SUPPORTED_SAMPLE_RATES);
7574 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007575 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007576
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007577 pthread_mutex_unlock(&adev->lock);
7578 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007579 if (ret == -ENOSYS) {
7580 /* ignore and go with default */
7581 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007582 }
7583 // For MMAP NO IRQ, allow conversions in ADSP
7584 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7585 goto error_open;
7586 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007587 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007588 goto error_open;
7589 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007590
7591 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7592 config->sample_rate = req_sample_rate;
7593 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7594 config->channel_mask = req_channel_mask;
7595 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7596 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007597 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007598
7599 out->sample_rate = config->sample_rate;
7600 out->channel_mask = config->channel_mask;
7601 out->format = config->format;
7602 if (is_hdmi) {
7603 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7604 out->config = pcm_config_hdmi_multi;
7605 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7606 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7607 out->config = pcm_config_mmap_playback;
7608 out->stream.start = out_start;
7609 out->stream.stop = out_stop;
7610 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7611 out->stream.get_mmap_position = out_get_mmap_position;
7612 } else {
7613 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7614 out->config = pcm_config_hifi;
7615 }
7616
7617 out->config.rate = out->sample_rate;
7618 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7619 if (is_hdmi) {
7620 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7621 audio_bytes_per_sample(out->format));
7622 }
7623 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007624 }
7625
Derek Chenf6318be2017-06-12 17:16:24 -04007626 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007627 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007628 /* extract car audio stream index */
7629 out->car_audio_stream =
7630 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7631 if (out->car_audio_stream < 0) {
7632 ALOGE("%s: invalid car audio stream %x",
7633 __func__, out->car_audio_stream);
7634 ret = -EINVAL;
7635 goto error_open;
7636 }
Derek Chen5f67a942020-02-24 23:08:13 -08007637 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007638 }
7639
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007640 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007641 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007642 if (!voice_extn_is_compress_voip_supported()) {
7643 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7644 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007645 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7646 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007647 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7648 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007649 out->volume_l = INVALID_OUT_VOLUME;
7650 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007651
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007652 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007653 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007654 uint32_t channel_count =
7655 audio_channel_count_from_out_mask(out->channel_mask);
7656 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7657 out->sample_rate, out->format,
7658 channel_count, false);
7659 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7660 if (frame_size != 0)
7661 out->config.period_size = buffer_size / frame_size;
7662 else
7663 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007664 }
7665 } else {
7666 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7667 voice_extn_compress_voip_is_active(out->dev)) &&
7668 (voice_extn_compress_voip_is_config_supported(config))) {
7669 ret = voice_extn_compress_voip_open_output_stream(out);
7670 if (ret != 0) {
7671 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7672 __func__, ret);
7673 goto error_open;
7674 }
Sujin Panicker19027262019-09-16 18:28:06 +05307675 } else {
7676 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7677 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007678 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007679 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007680 } else if (audio_is_linear_pcm(out->format) &&
7681 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7682 out->channel_mask = config->channel_mask;
7683 out->sample_rate = config->sample_rate;
7684 out->format = config->format;
7685 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7686 // does this change?
7687 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7688 out->config.rate = config->sample_rate;
7689 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7690 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7691 audio_bytes_per_sample(config->format));
7692 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007693 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307694 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307695 pthread_mutex_lock(&adev->lock);
7696 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7697 pthread_mutex_unlock(&adev->lock);
7698
7699 // reject offload during card offline to allow
7700 // fallback to s/w paths
7701 if (offline) {
7702 ret = -ENODEV;
7703 goto error_open;
7704 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007705
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007706 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7707 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7708 ALOGE("%s: Unsupported Offload information", __func__);
7709 ret = -EINVAL;
7710 goto error_open;
7711 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007712
Atul Khare3fa6e542017-08-09 00:56:17 +05307713 if (config->offload_info.format == 0)
7714 config->offload_info.format = config->format;
7715 if (config->offload_info.sample_rate == 0)
7716 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007717
Mingming Yin90310102013-11-13 16:57:00 -08007718 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307719 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007720 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007721 ret = -EINVAL;
7722 goto error_open;
7723 }
7724
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007725 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7726 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7727 (audio_extn_passthru_is_passthrough_stream(out)) &&
7728 !((config->sample_rate == 48000) ||
7729 (config->sample_rate == 96000) ||
7730 (config->sample_rate == 192000))) {
7731 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7732 __func__, config->sample_rate, config->offload_info.format);
7733 ret = -EINVAL;
7734 goto error_open;
7735 }
7736
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007737 out->compr_config.codec = (struct snd_codec *)
7738 calloc(1, sizeof(struct snd_codec));
7739
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007740 if (!out->compr_config.codec) {
7741 ret = -ENOMEM;
7742 goto error_open;
7743 }
7744
Dhananjay Kumarac341582017-02-23 23:42:25 +05307745 out->stream.pause = out_pause;
7746 out->stream.resume = out_resume;
7747 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307748 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307749 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007750 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307751 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007752 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307753 } else {
7754 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7755 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007756 }
vivek mehta446c3962015-09-14 10:57:35 -07007757
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307758 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7759 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007760#ifdef AUDIO_GKI_ENABLED
7761 /* out->compr_config.codec->reserved[1] is for flags */
7762 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7763#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307764 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007765#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307766 }
7767
vivek mehta446c3962015-09-14 10:57:35 -07007768 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007769 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007770 config->format == 0 && config->sample_rate == 0 &&
7771 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007772 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007773 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7774 } else {
7775 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7776 ret = -EEXIST;
7777 goto error_open;
7778 }
vivek mehta446c3962015-09-14 10:57:35 -07007779 }
7780
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007781 if (config->offload_info.channel_mask)
7782 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007783 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007784 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007785 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007786 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307787 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007788 ret = -EINVAL;
7789 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007790 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007791
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007792 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007793 out->sample_rate = config->offload_info.sample_rate;
7794
Mingming Yin3ee55c62014-08-04 14:23:35 -07007795 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007796
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307797 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307798 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307799 audio_extn_dolby_send_ddp_endp_params(adev);
7800 audio_extn_dolby_set_dmid(adev);
7801 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007802
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007803 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007804 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007805 out->compr_config.codec->bit_rate =
7806 config->offload_info.bit_rate;
7807 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307808 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007809 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307810 /* Update bit width only for non passthrough usecases.
7811 * For passthrough usecases, the output will always be opened @16 bit
7812 */
7813 if (!audio_extn_passthru_is_passthrough_stream(out))
7814 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307815
7816 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007817#ifdef AUDIO_GKI_ENABLED
7818 /* out->compr_config.codec->reserved[1] is for flags */
7819 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7820 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7821#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307822 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7823 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007824#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307825
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007826 /*TODO: Do we need to change it for passthrough */
7827 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007828
Manish Dewangana6fc5442015-08-24 20:30:31 +05307829 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7830 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307831 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307832 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307833 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7834 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307835
7836 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7837 AUDIO_FORMAT_PCM) {
7838
7839 /*Based on platform support, configure appropriate alsa format for corresponding
7840 *hal input format.
7841 */
7842 out->compr_config.codec->format = hal_format_to_alsa(
7843 config->offload_info.format);
7844
Ashish Jain83a6cc22016-06-28 14:34:17 +05307845 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307846 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307847 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307848
Dhananjay Kumarac341582017-02-23 23:42:25 +05307849 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307850 *hal input format and alsa format might differ based on platform support.
7851 */
7852 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307853 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307854
7855 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7856
Deeraj Soman93155a62019-09-30 19:00:37 +05307857 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7858 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7859 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7860 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7861 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307862
Ashish Jainf1eaa582016-05-23 20:54:24 +05307863 /* Check if alsa session is configured with the same format as HAL input format,
7864 * if not then derive correct fragment size needed to accomodate the
7865 * conversion of HAL input format to alsa format.
7866 */
7867 audio_extn_utils_update_direct_pcm_fragment_size(out);
7868
7869 /*if hal input and output fragment size is different this indicates HAL input format is
7870 *not same as the alsa format
7871 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307872 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307873 /*Allocate a buffer to convert input data to the alsa configured format.
7874 *size of convert buffer is equal to the size required to hold one fragment size
7875 *worth of pcm data, this is because flinger does not write more than fragment_size
7876 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307877 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7878 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307879 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7880 ret = -ENOMEM;
7881 goto error_open;
7882 }
7883 }
7884 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7885 out->compr_config.fragment_size =
7886 audio_extn_passthru_get_buffer_size(&config->offload_info);
7887 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7888 } else {
7889 out->compr_config.fragment_size =
7890 platform_get_compress_offload_buffer_size(&config->offload_info);
7891 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7892 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007893
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307894 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7895 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7896 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007897 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307898 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007899
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307900 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7901 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7902 }
7903
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007904 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7905 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007906
Manish Dewangan69426c82017-01-30 17:35:36 +05307907 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7908 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7909 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7910 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7911 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7912 } else {
7913 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7914 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007915
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307916 memset(&out->channel_map_param, 0,
7917 sizeof(struct audio_out_channel_map_param));
7918
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007919 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307920 out->send_next_track_params = false;
7921 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007922 out->offload_state = OFFLOAD_STATE_IDLE;
7923 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007924 out->writeAt.tv_sec = 0;
7925 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007926
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007927 audio_extn_dts_create_state_notifier_node(out->usecase);
7928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007929 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7930 __func__, config->offload_info.version,
7931 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307932
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307933 /* Check if DSD audio format is supported in codec
7934 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307935 */
7936
7937 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307938 (!platform_check_codec_dsd_support(adev->platform) ||
7939 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307940 ret = -EINVAL;
7941 goto error_open;
7942 }
7943
Ashish Jain5106d362016-05-11 19:23:33 +05307944 /* Disable gapless if any of the following is true
7945 * passthrough playback
7946 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307947 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307948 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307949 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307950 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007951 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307952 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307953 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307954 check_and_set_gapless_mode(adev, false);
7955 } else
7956 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007957
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307958 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007959 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7960 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307961 if (config->format == AUDIO_FORMAT_DSD) {
7962 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007963#ifdef AUDIO_GKI_ENABLED
7964 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7965 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7966#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307967 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007968#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307969 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007970
7971 create_offload_callback_thread(out);
7972
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007973 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007974 switch (config->sample_rate) {
7975 case 0:
7976 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7977 break;
7978 case 8000:
7979 case 16000:
7980 case 48000:
7981 out->sample_rate = config->sample_rate;
7982 break;
7983 default:
7984 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7985 config->sample_rate);
7986 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7987 ret = -EINVAL;
7988 goto error_open;
7989 }
7990 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7991 switch (config->channel_mask) {
7992 case AUDIO_CHANNEL_NONE:
7993 case AUDIO_CHANNEL_OUT_STEREO:
7994 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7995 break;
7996 default:
7997 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7998 config->channel_mask);
7999 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8000 ret = -EINVAL;
8001 goto error_open;
8002 }
8003 switch (config->format) {
8004 case AUDIO_FORMAT_DEFAULT:
8005 case AUDIO_FORMAT_PCM_16_BIT:
8006 out->format = AUDIO_FORMAT_PCM_16_BIT;
8007 break;
8008 default:
8009 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8010 config->format);
8011 config->format = AUDIO_FORMAT_PCM_16_BIT;
8012 ret = -EINVAL;
8013 goto error_open;
8014 }
8015
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308016 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008017 if (ret != 0) {
8018 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008019 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008020 goto error_open;
8021 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008022 } else if (is_single_device_type_equal(&out->device_list,
8023 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008024 switch (config->sample_rate) {
8025 case 0:
8026 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8027 break;
8028 case 8000:
8029 case 16000:
8030 case 48000:
8031 out->sample_rate = config->sample_rate;
8032 break;
8033 default:
8034 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8035 config->sample_rate);
8036 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8037 ret = -EINVAL;
8038 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008039 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008040 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8041 switch (config->channel_mask) {
8042 case AUDIO_CHANNEL_NONE:
8043 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8044 break;
8045 case AUDIO_CHANNEL_OUT_STEREO:
8046 out->channel_mask = config->channel_mask;
8047 break;
8048 default:
8049 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8050 config->channel_mask);
8051 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8052 ret = -EINVAL;
8053 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008054 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008055 switch (config->format) {
8056 case AUDIO_FORMAT_DEFAULT:
8057 out->format = AUDIO_FORMAT_PCM_16_BIT;
8058 break;
8059 case AUDIO_FORMAT_PCM_16_BIT:
8060 out->format = config->format;
8061 break;
8062 default:
8063 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8064 config->format);
8065 config->format = AUDIO_FORMAT_PCM_16_BIT;
8066 ret = -EINVAL;
8067 break;
8068 }
8069 if (ret != 0)
8070 goto error_open;
8071
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008072 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8073 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008074 out->config.rate = out->sample_rate;
8075 out->config.channels =
8076 audio_channel_count_from_out_mask(out->channel_mask);
8077 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008078 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008079 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308080 unsigned int channels = 0;
8081 /*Update config params to default if not set by the caller*/
8082 if (config->sample_rate == 0)
8083 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8084 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8085 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8086 if (config->format == AUDIO_FORMAT_DEFAULT)
8087 config->format = AUDIO_FORMAT_PCM_16_BIT;
8088
8089 channels = audio_channel_count_from_out_mask(out->channel_mask);
8090
Varun Balaraje49253e2017-07-06 19:48:56 +05308091 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8092 out->usecase = get_interactive_usecase(adev);
8093 out->config = pcm_config_low_latency;
8094 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308095 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008096 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8097 out->flags);
8098 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008099 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8100 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8101 out->config = pcm_config_mmap_playback;
8102 out->stream.start = out_start;
8103 out->stream.stop = out_stop;
8104 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8105 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308106 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8107 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008108 out->hal_output_suspend_supported =
8109 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8110 out->dynamic_pm_qos_config_supported =
8111 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8112 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008113 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8114 } else {
8115 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8116 //the mixer path will be a string similar to "low-latency-playback resume"
8117 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8118 strlcat(out->pm_qos_mixer_path,
8119 " resume", MAX_MIXER_PATH_LEN);
8120 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8121 out->pm_qos_mixer_path);
8122 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308123 out->config = pcm_config_low_latency;
8124 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8125 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8126 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308127 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8128 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8129 if (out->config.period_size <= 0) {
8130 ALOGE("Invalid configuration period size is not valid");
8131 ret = -EINVAL;
8132 goto error_open;
8133 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008134 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8135 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8136 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008137 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8138 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8139 out->config = pcm_config_haptics_audio;
8140 if (force_haptic_path)
8141 adev->haptics_config = pcm_config_haptics_audio;
8142 else
8143 adev->haptics_config = pcm_config_haptics;
8144
8145 out->config.channels =
8146 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8147
8148 if (force_haptic_path) {
8149 out->config.channels = 1;
8150 adev->haptics_config.channels = 1;
8151 } else
8152 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 -08008153 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008154 ret = audio_extn_auto_hal_open_output_stream(out);
8155 if (ret) {
8156 ALOGE("%s: Failed to open output stream for bus device", __func__);
8157 ret = -EINVAL;
8158 goto error_open;
8159 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308160 } else {
8161 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008162 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8163 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308164 }
8165 out->hal_ip_format = format = out->format;
8166 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8167 out->hal_op_format = pcm_format_to_hal(out->config.format);
8168 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8169 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008170 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308171 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308172 if (out->hal_ip_format != out->hal_op_format) {
8173 uint32_t buffer_size = out->config.period_size *
8174 format_to_bitwidth_table[out->hal_op_format] *
8175 out->config.channels;
8176 out->convert_buffer = calloc(1, buffer_size);
8177 if (out->convert_buffer == NULL){
8178 ALOGE("Allocation failed for convert buffer for size %d",
8179 out->compr_config.fragment_size);
8180 ret = -ENOMEM;
8181 goto error_open;
8182 }
8183 ALOGD("Convert buffer allocated of size %d", buffer_size);
8184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008185 }
8186
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008187 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8188 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308189
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008190 /* TODO remove this hardcoding and check why width is zero*/
8191 if (out->bit_width == 0)
8192 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308193 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008194 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008195 &out->device_list, out->flags,
8196 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308197 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308198 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008199 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008200 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8201 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008202 if(adev->primary_output == NULL)
8203 adev->primary_output = out;
8204 else {
8205 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008206 ret = -EEXIST;
8207 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008208 }
8209 }
8210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008211 /* Check if this usecase is already existing */
8212 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008213 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8214 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008215 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008216 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008217 ret = -EEXIST;
8218 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008219 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008221 pthread_mutex_unlock(&adev->lock);
8222
8223 out->stream.common.get_sample_rate = out_get_sample_rate;
8224 out->stream.common.set_sample_rate = out_set_sample_rate;
8225 out->stream.common.get_buffer_size = out_get_buffer_size;
8226 out->stream.common.get_channels = out_get_channels;
8227 out->stream.common.get_format = out_get_format;
8228 out->stream.common.set_format = out_set_format;
8229 out->stream.common.standby = out_standby;
8230 out->stream.common.dump = out_dump;
8231 out->stream.common.set_parameters = out_set_parameters;
8232 out->stream.common.get_parameters = out_get_parameters;
8233 out->stream.common.add_audio_effect = out_add_audio_effect;
8234 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8235 out->stream.get_latency = out_get_latency;
8236 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008237#ifdef NO_AUDIO_OUT
8238 out->stream.write = out_write_for_no_output;
8239#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008240 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008241#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008242 out->stream.get_render_position = out_get_render_position;
8243 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008244 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008245
Haynes Mathew George16081042017-05-31 17:16:49 -07008246 if (out->realtime)
8247 out->af_period_multiplier = af_period_multiplier;
8248 else
8249 out->af_period_multiplier = 1;
8250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008251 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008252 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008253 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008254
8255 config->format = out->stream.common.get_format(&out->stream.common);
8256 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8257 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308258 register_format(out->format, out->supported_formats);
8259 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8260 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008261
Aalique Grahame22e49102018-12-18 14:23:57 -08008262 out->error_log = error_log_create(
8263 ERROR_LOG_ENTRIES,
8264 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8265
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308266 /*
8267 By locking output stream before registering, we allow the callback
8268 to update stream's state only after stream's initial state is set to
8269 adev state.
8270 */
8271 lock_output_stream(out);
8272 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8273 pthread_mutex_lock(&adev->lock);
8274 out->card_status = adev->card_status;
8275 pthread_mutex_unlock(&adev->lock);
8276 pthread_mutex_unlock(&out->lock);
8277
Aalique Grahame22e49102018-12-18 14:23:57 -08008278 stream_app_type_cfg_init(&out->app_type_cfg);
8279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008280 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308281 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008282 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008283
8284 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8285 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8286 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008287 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308288 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008289 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008290 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308291 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8292 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008293 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8294 out->usecase, PCM_PLAYBACK);
8295 hdlr_stream_cfg.flags = out->flags;
8296 hdlr_stream_cfg.type = PCM_PLAYBACK;
8297 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8298 &hdlr_stream_cfg);
8299 if (ret) {
8300 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8301 out->adsp_hdlr_stream_handle = NULL;
8302 }
8303 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308304 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8305 is_direct_passthough, false);
8306 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8307 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008308 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008309 if (ret < 0) {
8310 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8311 out->ip_hdlr_handle = NULL;
8312 }
8313 }
Derek Chenf939fb72018-11-13 13:34:41 -08008314
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008315 ret = io_streams_map_insert(adev, &out->stream.common,
8316 out->handle, AUDIO_PATCH_HANDLE_NONE);
8317 if (ret != 0)
8318 goto error_open;
8319
Derek Chenf939fb72018-11-13 13:34:41 -08008320 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8321 calloc(1, sizeof(streams_output_ctxt_t));
8322 if (out_ctxt == NULL) {
8323 ALOGE("%s fail to allocate output ctxt", __func__);
8324 ret = -ENOMEM;
8325 goto error_open;
8326 }
8327 out_ctxt->output = out;
8328
8329 pthread_mutex_lock(&adev->lock);
8330 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8331 pthread_mutex_unlock(&adev->lock);
8332
Eric Laurent994a6932013-07-17 11:51:42 -07008333 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008334 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008335
8336error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308337 if (out->convert_buffer)
8338 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008339 free(out);
8340 *stream_out = NULL;
8341 ALOGD("%s: exit: ret %d", __func__, ret);
8342 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008343}
8344
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308345void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008346 struct audio_stream_out *stream)
8347{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008348 struct stream_out *out = (struct stream_out *)stream;
8349 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008350 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008351
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008352 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308353
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008354 io_streams_map_remove(adev, out->handle);
8355
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308356 // must deregister from sndmonitor first to prevent races
8357 // between the callback and close_stream
8358 audio_extn_snd_mon_unregister_listener(out);
8359
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008360 /* close adsp hdrl session before standby */
8361 if (out->adsp_hdlr_stream_handle) {
8362 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8363 if (ret)
8364 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8365 out->adsp_hdlr_stream_handle = NULL;
8366 }
8367
Manish Dewangan21a850a2017-08-14 12:03:55 +05308368 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008369 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8370 out->ip_hdlr_handle = NULL;
8371 }
8372
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008373 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308374 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008375 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308376 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308377 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008378 if(ret != 0)
8379 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8380 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008381 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008382 out_standby(&stream->common);
8383
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008384 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008385 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008386 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008387 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008388 if (out->compr_config.codec != NULL)
8389 free(out->compr_config.codec);
8390 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008391
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308392 out->a2dp_compress_mute = false;
8393
Varun Balaraje49253e2017-07-06 19:48:56 +05308394 if (is_interactive_usecase(out->usecase))
8395 free_interactive_usecase(adev, out->usecase);
8396
Ashish Jain83a6cc22016-06-28 14:34:17 +05308397 if (out->convert_buffer != NULL) {
8398 free(out->convert_buffer);
8399 out->convert_buffer = NULL;
8400 }
8401
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008402 if (adev->voice_tx_output == out)
8403 adev->voice_tx_output = NULL;
8404
Aalique Grahame22e49102018-12-18 14:23:57 -08008405 error_log_destroy(out->error_log);
8406 out->error_log = NULL;
8407
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308408 if (adev->primary_output == out)
8409 adev->primary_output = NULL;
8410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008411 pthread_cond_destroy(&out->cond);
8412 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008413
8414 pthread_mutex_lock(&adev->lock);
8415 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8416 if (out_ctxt != NULL) {
8417 list_remove(&out_ctxt->list);
8418 free(out_ctxt);
8419 } else {
8420 ALOGW("%s, output stream already closed", __func__);
8421 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008422 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008423 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008424 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008425}
8426
8427static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8428{
8429 struct audio_device *adev = (struct audio_device *)dev;
8430 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008431 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008432 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008433 int ret;
8434 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008435 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008436 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008437 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008438
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008439 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008440 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308442 if (!parms)
8443 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308444
Derek Chen6f293672019-04-01 01:40:24 -07008445 /* notify adev and input/output streams on the snd card status */
8446 adev_snd_mon_cb((void *)adev, parms);
8447
8448 list_for_each(node, &adev->active_outputs_list) {
8449 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8450 streams_output_ctxt_t,
8451 list);
8452 out_snd_mon_cb((void *)out_ctxt->output, parms);
8453 }
8454
8455 list_for_each(node, &adev->active_inputs_list) {
8456 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8457 streams_input_ctxt_t,
8458 list);
8459 in_snd_mon_cb((void *)in_ctxt->input, parms);
8460 }
8461
Zhou Songd6d71752019-05-21 18:08:51 +08008462 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308463 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8464 if (ret >= 0) {
8465 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008466 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308467 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008468 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308469 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008470 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008471 }
8472 }
8473
8474 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8475 if (ret>=0) {
8476 if (!strncmp(value, "false", 5) &&
8477 audio_extn_a2dp_source_is_suspended()) {
8478 struct audio_usecase *usecase;
8479 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008480 list_for_each(node, &adev->usecase_list) {
8481 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008482 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008483 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008484 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008485 reassign_device_list(&usecase->stream.in->device_list,
8486 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008487 select_devices(adev, usecase->id);
8488 }
Zhou Songd6d71752019-05-21 18:08:51 +08008489 }
8490 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308491 }
8492
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008493 status = voice_set_parameters(adev, parms);
8494 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008495 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008497 status = platform_set_parameters(adev->platform, parms);
8498 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008499 goto done;
8500
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008501 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8502 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008503 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008504 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8505 adev->bluetooth_nrec = true;
8506 else
8507 adev->bluetooth_nrec = false;
8508 }
8509
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008510 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8511 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008512 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8513 adev->screen_off = false;
8514 else
8515 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008516 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008517 }
8518
Eric Laurent4b084132018-10-19 17:33:43 -07008519 ret = str_parms_get_int(parms, "rotation", &val);
8520 if (ret >= 0) {
8521 bool reverse_speakers = false;
8522 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8523 switch (val) {
8524 // FIXME: note that the code below assumes that the speakers are in the correct placement
8525 // relative to the user when the device is rotated 90deg from its default rotation. This
8526 // assumption is device-specific, not platform-specific like this code.
8527 case 270:
8528 reverse_speakers = true;
8529 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8530 break;
8531 case 0:
8532 case 180:
8533 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8534 break;
8535 case 90:
8536 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8537 break;
8538 default:
8539 ALOGE("%s: unexpected rotation of %d", __func__, val);
8540 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008541 }
Eric Laurent4b084132018-10-19 17:33:43 -07008542 if (status == 0) {
8543 // check and set swap
8544 // - check if orientation changed and speaker active
8545 // - set rotation and cache the rotation value
8546 adev->camera_orientation =
8547 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8548 if (!audio_extn_is_maxx_audio_enabled())
8549 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8550 }
8551 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008552
Mingming Yin514a8bc2014-07-29 15:22:21 -07008553 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8554 if (ret >= 0) {
8555 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8556 adev->bt_wb_speech_enabled = true;
8557 else
8558 adev->bt_wb_speech_enabled = false;
8559 }
8560
Zhou Song12c29502019-03-16 10:37:18 +08008561 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8562 if (ret >= 0) {
8563 val = atoi(value);
8564 adev->swb_speech_mode = val;
8565 }
8566
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008567 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8568 if (ret >= 0) {
8569 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308570 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008571 if (audio_is_output_device(val) &&
8572 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008573 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008574 platform_get_controller_stream_from_params(parms, &controller, &stream);
8575 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8576 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008577 if (ret < 0) {
8578 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308579 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008580 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008581 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308582 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008583 /*
8584 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8585 * Per AudioPolicyManager, USB device is higher priority than WFD.
8586 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8587 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8588 * starting voice call on USB
8589 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008590 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308591 if (ret >= 0)
8592 audio_extn_usb_add_device(device, atoi(value));
8593
Zhou Song6f862822017-11-06 17:27:57 +08008594 if (!audio_extn_usb_is_tunnel_supported()) {
8595 ALOGV("detected USB connect .. disable proxy");
8596 adev->allow_afe_proxy_usage = false;
8597 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008598 }
8599 }
8600
8601 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8602 if (ret >= 0) {
8603 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308604 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008605 /*
8606 * The HDMI / Displayport disconnect handling has been moved to
8607 * audio extension to ensure that its parameters are not
8608 * invalidated prior to updating sysfs of the disconnect event
8609 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8610 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308611 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008612 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308613 if (ret >= 0)
8614 audio_extn_usb_remove_device(device, atoi(value));
8615
Zhou Song6f862822017-11-06 17:27:57 +08008616 if (!audio_extn_usb_is_tunnel_supported()) {
8617 ALOGV("detected USB disconnect .. enable proxy");
8618 adev->allow_afe_proxy_usage = true;
8619 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008620 }
8621 }
8622
Aalique Grahame22e49102018-12-18 14:23:57 -08008623 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008624 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008625
8626 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008627 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308628 struct audio_usecase *usecase;
8629 struct listnode *node;
8630 list_for_each(node, &adev->usecase_list) {
8631 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308632 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008633 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308634 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008635 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308636 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008637 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308638 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308639 ALOGD("Switching to speaker and muting the stream before select_devices");
8640 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308641 //force device switch to re configure encoder
8642 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308643 ALOGD("Unmuting the stream after select_devices");
8644 usecase->stream.out->a2dp_compress_mute = false;
8645 out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308646 audio_extn_a2dp_set_handoff_mode(false);
8647 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308648 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308649 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8650 usecase->stream.out->a2dp_compress_mute) {
8651 pthread_mutex_unlock(&adev->lock);
8652 lock_output_stream(usecase->stream.out);
8653 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008654 reassign_device_list(&usecase->stream.out->device_list,
8655 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308656 check_a2dp_restore_l(adev, usecase->stream.out, true);
8657 pthread_mutex_unlock(&usecase->stream.out->lock);
8658 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308659 }
8660 }
8661 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008662
8663 //handle vr audio setparam
8664 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8665 value, sizeof(value));
8666 if (ret >= 0) {
8667 ALOGI("Setting vr mode to be %s", value);
8668 if (!strncmp(value, "true", 4)) {
8669 adev->vr_audio_mode_enabled = true;
8670 ALOGI("Setting vr mode to true");
8671 } else if (!strncmp(value, "false", 5)) {
8672 adev->vr_audio_mode_enabled = false;
8673 ALOGI("Setting vr mode to false");
8674 } else {
8675 ALOGI("wrong vr mode set");
8676 }
8677 }
8678
Eric Laurent4b084132018-10-19 17:33:43 -07008679 //FIXME: to be replaced by proper video capture properties API
8680 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8681 if (ret >= 0) {
8682 int camera_facing = CAMERA_FACING_BACK;
8683 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8684 camera_facing = CAMERA_FACING_FRONT;
8685 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8686 camera_facing = CAMERA_FACING_BACK;
8687 else {
8688 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8689 goto done;
8690 }
8691 adev->camera_orientation =
8692 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8693 struct audio_usecase *usecase;
8694 struct listnode *node;
8695 list_for_each(node, &adev->usecase_list) {
8696 usecase = node_to_item(node, struct audio_usecase, list);
8697 struct stream_in *in = usecase->stream.in;
8698 if (usecase->type == PCM_CAPTURE && in != NULL &&
8699 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8700 select_devices(adev, in->usecase);
8701 }
8702 }
8703 }
8704
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308705 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008706done:
8707 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008708 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308709error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008710 ALOGV("%s: exit with code(%d)", __func__, status);
8711 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008712}
8713
8714static char* adev_get_parameters(const struct audio_hw_device *dev,
8715 const char *keys)
8716{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308717 ALOGD("%s:%s", __func__, keys);
8718
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008719 struct audio_device *adev = (struct audio_device *)dev;
8720 struct str_parms *reply = str_parms_create();
8721 struct str_parms *query = str_parms_create_str(keys);
8722 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308723 char value[256] = {0};
8724 int ret = 0;
8725
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008726 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008727 if (reply) {
8728 str_parms_destroy(reply);
8729 }
8730 if (query) {
8731 str_parms_destroy(query);
8732 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008733 ALOGE("adev_get_parameters: failed to create query or reply");
8734 return NULL;
8735 }
8736
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008737 //handle vr audio getparam
8738
8739 ret = str_parms_get_str(query,
8740 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8741 value, sizeof(value));
8742
8743 if (ret >= 0) {
8744 bool vr_audio_enabled = false;
8745 pthread_mutex_lock(&adev->lock);
8746 vr_audio_enabled = adev->vr_audio_mode_enabled;
8747 pthread_mutex_unlock(&adev->lock);
8748
8749 ALOGI("getting vr mode to %d", vr_audio_enabled);
8750
8751 if (vr_audio_enabled) {
8752 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8753 "true");
8754 goto exit;
8755 } else {
8756 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8757 "false");
8758 goto exit;
8759 }
8760 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008761
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008762 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008763 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008764 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008765 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008766 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308767 pthread_mutex_unlock(&adev->lock);
8768
Naresh Tannirud7205b62014-06-20 02:54:48 +05308769exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008770 str = str_parms_to_str(reply);
8771 str_parms_destroy(query);
8772 str_parms_destroy(reply);
8773
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308774 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008775 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008776}
8777
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008778static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779{
8780 return 0;
8781}
8782
8783static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8784{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008785 int ret;
8786 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008787
8788 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8789
Haynes Mathew George5191a852013-09-11 14:19:36 -07008790 pthread_mutex_lock(&adev->lock);
8791 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008792 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008793 pthread_mutex_unlock(&adev->lock);
8794 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008795}
8796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008797static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8798 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008799{
8800 return -ENOSYS;
8801}
8802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008803static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8804 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008805{
8806 return -ENOSYS;
8807}
8808
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008809static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8810 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008811{
8812 return -ENOSYS;
8813}
8814
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008815static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8816 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008817{
8818 return -ENOSYS;
8819}
8820
8821static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8822{
8823 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008824 struct listnode *node;
8825 struct audio_usecase *usecase = NULL;
8826 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008828 pthread_mutex_lock(&adev->lock);
8829 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308830 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8831 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008832 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308833 if( mode == AUDIO_MODE_CALL_SCREEN ){
8834 adev->current_call_output = adev->primary_output;
8835 voice_start_call(adev);
8836 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008837 (mode == AUDIO_MODE_NORMAL ||
8838 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008839 list_for_each(node, &adev->usecase_list) {
8840 usecase = node_to_item(node, struct audio_usecase, list);
8841 if (usecase->type == VOICE_CALL)
8842 break;
8843 }
8844 if (usecase &&
8845 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8846 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8847 true);
8848 if (ret != 0) {
8849 /* default service interval was successfully updated,
8850 reopen USB backend with new service interval */
8851 check_usecases_codec_backend(adev,
8852 usecase,
8853 usecase->out_snd_device);
8854 }
8855 }
8856
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008857 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008858 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008859 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008860 // restore device for other active usecases after stop call
8861 list_for_each(node, &adev->usecase_list) {
8862 usecase = node_to_item(node, struct audio_usecase, list);
8863 select_devices(adev, usecase->id);
8864 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008866 }
8867 pthread_mutex_unlock(&adev->lock);
8868 return 0;
8869}
8870
8871static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8872{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008873 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008874 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008875
8876 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008877 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008878 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008879
Derek Chend2530072014-11-24 12:39:14 -08008880 if (adev->ext_hw_plugin)
8881 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008882
8883 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008884 pthread_mutex_unlock(&adev->lock);
8885
8886 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008887}
8888
8889static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8890{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008891 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008892 return 0;
8893}
8894
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008895static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008896 const struct audio_config *config)
8897{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008898 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008899
Aalique Grahame22e49102018-12-18 14:23:57 -08008900 /* Don't know if USB HIFI in this context so use true to be conservative */
8901 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8902 true /*is_usb_hifi */) != 0)
8903 return 0;
8904
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008905 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8906 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008907}
8908
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008909static bool adev_input_allow_hifi_record(struct audio_device *adev,
8910 audio_devices_t devices,
8911 audio_input_flags_t flags,
8912 audio_source_t source) {
8913 const bool allowed = true;
8914
8915 if (!audio_is_usb_in_device(devices))
8916 return !allowed;
8917
8918 switch (flags) {
8919 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008920 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008921 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8922 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008923 default:
8924 return !allowed;
8925 }
8926
8927 switch (source) {
8928 case AUDIO_SOURCE_DEFAULT:
8929 case AUDIO_SOURCE_MIC:
8930 case AUDIO_SOURCE_UNPROCESSED:
8931 break;
8932 default:
8933 return !allowed;
8934 }
8935
8936 switch (adev->mode) {
8937 case 0:
8938 break;
8939 default:
8940 return !allowed;
8941 }
8942
8943 return allowed;
8944}
8945
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008946static int adev_update_voice_comm_input_stream(struct stream_in *in,
8947 struct audio_config *config)
8948{
8949 bool valid_rate = (config->sample_rate == 8000 ||
8950 config->sample_rate == 16000 ||
8951 config->sample_rate == 32000 ||
8952 config->sample_rate == 48000);
8953 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8954
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008955 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008956 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008957 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8958 in->config = default_pcm_config_voip_copp;
8959 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8960 DEFAULT_VOIP_BUF_DURATION_MS,
8961 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008962 } else {
8963 ALOGW("%s No valid input in voip, use defaults"
8964 "sample rate %u, channel mask 0x%X",
8965 __func__, config->sample_rate, in->channel_mask);
8966 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008967 in->config.rate = config->sample_rate;
8968 in->sample_rate = config->sample_rate;
8969 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008970 //XXX needed for voice_extn_compress_voip_open_input_stream
8971 in->config.rate = config->sample_rate;
8972 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308973 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008974 voice_extn_compress_voip_is_active(in->dev)) &&
8975 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8976 valid_rate && valid_ch) {
8977 voice_extn_compress_voip_open_input_stream(in);
8978 // update rate entries to match config from AF
8979 in->config.rate = config->sample_rate;
8980 in->sample_rate = config->sample_rate;
8981 } else {
8982 ALOGW("%s compress voip not active, use defaults", __func__);
8983 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008984 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008985 return 0;
8986}
8987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008988static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008989 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008990 audio_devices_t devices,
8991 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008992 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308993 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008994 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008995 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996{
8997 struct audio_device *adev = (struct audio_device *)dev;
8998 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008999 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009000 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009001 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309002 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009003 bool is_usb_dev = audio_is_usb_in_device(devices);
9004 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9005 devices,
9006 flags,
9007 source);
Andy Hung94320602018-10-29 18:31:12 -07009008 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9009 " sample_rate %u, channel_mask %#x, format %#x",
9010 __func__, flags, is_usb_dev, may_use_hifi_record,
9011 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309012
kunleizdff872d2018-08-20 14:40:33 +08009013 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009014 is_usb_dev = false;
9015 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9016 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9017 __func__, devices);
9018 }
9019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009020 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009021
9022 if (!(is_usb_dev && may_use_hifi_record)) {
9023 if (config->sample_rate == 0)
9024 config->sample_rate = 48000;
9025 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9026 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9027 if (config->format == AUDIO_FORMAT_DEFAULT)
9028 config->format = AUDIO_FORMAT_PCM_16_BIT;
9029
9030 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9031
Aalique Grahame22e49102018-12-18 14:23:57 -08009032 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9033 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009034 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309035 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036
Rahul Sharma99770982019-03-06 17:05:26 +05309037 pthread_mutex_lock(&adev->lock);
9038 if (in_get_stream(adev, handle) != NULL) {
9039 ALOGW("%s, input stream already opened", __func__);
9040 ret = -EEXIST;
9041 }
9042 pthread_mutex_unlock(&adev->lock);
9043 if (ret)
9044 return ret;
9045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009046 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009047
9048 if (!in) {
9049 ALOGE("failed to allocate input stream");
9050 return -ENOMEM;
9051 }
9052
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309053 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309054 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9055 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009056 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009057 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009059 in->stream.common.get_sample_rate = in_get_sample_rate;
9060 in->stream.common.set_sample_rate = in_set_sample_rate;
9061 in->stream.common.get_buffer_size = in_get_buffer_size;
9062 in->stream.common.get_channels = in_get_channels;
9063 in->stream.common.get_format = in_get_format;
9064 in->stream.common.set_format = in_set_format;
9065 in->stream.common.standby = in_standby;
9066 in->stream.common.dump = in_dump;
9067 in->stream.common.set_parameters = in_set_parameters;
9068 in->stream.common.get_parameters = in_get_parameters;
9069 in->stream.common.add_audio_effect = in_add_audio_effect;
9070 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9071 in->stream.set_gain = in_set_gain;
9072 in->stream.read = in_read;
9073 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009074 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309075 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009076 in->stream.set_microphone_direction = in_set_microphone_direction;
9077 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009078 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009079
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009080 list_init(&in->device_list);
9081 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009082 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009083 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009084 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009085 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009086 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009087 in->bit_width = 16;
9088 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009089 in->direction = MIC_DIRECTION_UNSPECIFIED;
9090 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009091 list_init(&in->aec_list);
9092 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009093 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009094
Andy Hung94320602018-10-29 18:31:12 -07009095 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009096 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9097 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9098 /* Force channel config requested to mono if incall
9099 record is being requested for only uplink/downlink */
9100 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9101 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9102 ret = -EINVAL;
9103 goto err_open;
9104 }
9105 }
9106
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009107 if (is_usb_dev && may_use_hifi_record) {
9108 /* HiFi record selects an appropriate format, channel, rate combo
9109 depending on sink capabilities*/
9110 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9111 &config->format,
9112 &in->supported_formats[0],
9113 MAX_SUPPORTED_FORMATS,
9114 &config->channel_mask,
9115 &in->supported_channel_masks[0],
9116 MAX_SUPPORTED_CHANNEL_MASKS,
9117 &config->sample_rate,
9118 &in->supported_sample_rates[0],
9119 MAX_SUPPORTED_SAMPLE_RATES);
9120 if (ret != 0) {
9121 ret = -EINVAL;
9122 goto err_open;
9123 }
9124 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009125 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309126 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309127 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9128 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9129 in->config.format = PCM_FORMAT_S32_LE;
9130 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309131 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9132 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9133 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9134 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9135 bool ret_error = false;
9136 in->bit_width = 24;
9137 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9138 from HAL is 24_packed and 8_24
9139 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9140 24_packed return error indicating supported format is 24_packed
9141 *> In case of any other source requesting 24 bit or float return error
9142 indicating format supported is 16 bit only.
9143
9144 on error flinger will retry with supported format passed
9145 */
9146 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9147 (source != AUDIO_SOURCE_CAMCORDER)) {
9148 config->format = AUDIO_FORMAT_PCM_16_BIT;
9149 if (config->sample_rate > 48000)
9150 config->sample_rate = 48000;
9151 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009152 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9153 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309154 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9155 ret_error = true;
9156 }
9157
9158 if (ret_error) {
9159 ret = -EINVAL;
9160 goto err_open;
9161 }
9162 }
9163
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009164 in->channel_mask = config->channel_mask;
9165 in->format = config->format;
9166
9167 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309168
9169 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9170 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9171 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9172 else {
9173 ret = -EINVAL;
9174 goto err_open;
9175 }
9176 }
9177
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009178 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309179 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9180 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009181 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9182 is_low_latency = true;
9183#if LOW_LATENCY_CAPTURE_USE_CASE
9184 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9185#endif
9186 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009187 if (!in->realtime) {
9188 in->config = pcm_config_audio_capture;
9189 frame_size = audio_stream_in_frame_size(&in->stream);
9190 buffer_size = get_input_buffer_size(config->sample_rate,
9191 config->format,
9192 channel_count,
9193 is_low_latency);
9194 in->config.period_size = buffer_size / frame_size;
9195 in->config.rate = config->sample_rate;
9196 in->af_period_multiplier = 1;
9197 } else {
9198 // period size is left untouched for rt mode playback
9199 in->config = pcm_config_audio_capture_rt;
9200 in->af_period_multiplier = af_period_multiplier;
9201 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009202 }
9203
9204 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9205 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9206 in->realtime = 0;
9207 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9208 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009209 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009210 in->stream.start = in_start;
9211 in->stream.stop = in_stop;
9212 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9213 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009214 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009215 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009216 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9217 in->config = pcm_config_audio_capture;
9218 frame_size = audio_stream_in_frame_size(&in->stream);
9219 buffer_size = get_input_buffer_size(config->sample_rate,
9220 config->format,
9221 channel_count,
9222 false /*is_low_latency*/);
9223 in->config.period_size = buffer_size / frame_size;
9224 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009225 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009226 switch (config->format) {
9227 case AUDIO_FORMAT_PCM_32_BIT:
9228 in->bit_width = 32;
9229 break;
9230 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9231 case AUDIO_FORMAT_PCM_8_24_BIT:
9232 in->bit_width = 24;
9233 break;
9234 default:
9235 in->bit_width = 16;
9236 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009237 } else if (is_single_device_type_equal(&in->device_list,
9238 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9239 is_single_device_type_equal(&in->device_list,
9240 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009241 if (config->sample_rate == 0)
9242 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9243 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9244 config->sample_rate != 8000) {
9245 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9246 ret = -EINVAL;
9247 goto err_open;
9248 }
9249 if (config->format == AUDIO_FORMAT_DEFAULT)
9250 config->format = AUDIO_FORMAT_PCM_16_BIT;
9251 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9252 config->format = AUDIO_FORMAT_PCM_16_BIT;
9253 ret = -EINVAL;
9254 goto err_open;
9255 }
9256
9257 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9258 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009259 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009260 in->af_period_multiplier = 1;
9261 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9262 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9263 (config->sample_rate == 8000 ||
9264 config->sample_rate == 16000 ||
9265 config->sample_rate == 32000 ||
9266 config->sample_rate == 48000) &&
9267 channel_count == 1) {
9268 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9269 in->config = pcm_config_audio_capture;
9270 frame_size = audio_stream_in_frame_size(&in->stream);
9271 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9272 config->sample_rate,
9273 config->format,
9274 channel_count, false /*is_low_latency*/);
9275 in->config.period_size = buffer_size / frame_size;
9276 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9277 in->config.rate = config->sample_rate;
9278 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009279 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309280 int ret_val;
9281 pthread_mutex_lock(&adev->lock);
9282 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9283 in, config, &channel_mask_updated);
9284 pthread_mutex_unlock(&adev->lock);
9285
9286 if (!ret_val) {
9287 if (channel_mask_updated == true) {
9288 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9289 __func__, config->channel_mask);
9290 ret = -EINVAL;
9291 goto err_open;
9292 }
9293 ALOGD("%s: created multi-channel session succesfully",__func__);
9294 } else if (audio_extn_compr_cap_enabled() &&
9295 audio_extn_compr_cap_format_supported(config->format) &&
9296 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9297 audio_extn_compr_cap_init(in);
9298 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309299 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309300 if (ret)
9301 goto err_open;
9302 } else {
9303 in->config = pcm_config_audio_capture;
9304 in->config.rate = config->sample_rate;
9305 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309306 in->format = config->format;
9307 frame_size = audio_stream_in_frame_size(&in->stream);
9308 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009309 config->format,
9310 channel_count,
9311 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009312 /* prevent division-by-zero */
9313 if (frame_size == 0) {
9314 ALOGE("%s: Error frame_size==0", __func__);
9315 ret = -EINVAL;
9316 goto err_open;
9317 }
9318
Revathi Uddarajud2634032017-12-07 14:42:34 +05309319 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009320 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009321
Revathi Uddarajud2634032017-12-07 14:42:34 +05309322 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9323 /* optionally use VOIP usecase depending on config(s) */
9324 ret = adev_update_voice_comm_input_stream(in, config);
9325 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009326
Revathi Uddarajud2634032017-12-07 14:42:34 +05309327 if (ret) {
9328 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9329 goto err_open;
9330 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009331 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309332
9333 /* assign concurrent capture usecase if record has to caried out from
9334 * actual hardware input source */
9335 if (audio_extn_is_concurrent_capture_enabled() &&
9336 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309337 /* Acquire lock to avoid two concurrent use cases initialized to
9338 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009339
Samyak Jainc37062f2019-04-25 18:41:06 +05309340 if (in->usecase == USECASE_AUDIO_RECORD) {
9341 pthread_mutex_lock(&adev->lock);
9342 if (!(adev->pcm_record_uc_state)) {
9343 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9344 adev->pcm_record_uc_state = 1;
9345 pthread_mutex_unlock(&adev->lock);
9346 } else {
9347 pthread_mutex_unlock(&adev->lock);
9348 /* Assign compress record use case for second record */
9349 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9350 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9351 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9352 if (audio_extn_cin_applicable_stream(in)) {
9353 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309354 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309355 if (ret)
9356 goto err_open;
9357 }
9358 }
9359 }
kunleiz28c73e72019-03-27 17:24:04 +08009360 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009361 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309362 if (audio_extn_ssr_get_stream() != in)
9363 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009364
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009365 in->sample_rate = in->config.rate;
9366
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309367 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9368 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009369 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009370 in->sample_rate, in->bit_width,
9371 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309372 register_format(in->format, in->supported_formats);
9373 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9374 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309375
Aalique Grahame22e49102018-12-18 14:23:57 -08009376 in->error_log = error_log_create(
9377 ERROR_LOG_ENTRIES,
9378 1000000000 /* aggregate consecutive identical errors within one second */);
9379
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009380 /* This stream could be for sound trigger lab,
9381 get sound trigger pcm if present */
9382 audio_extn_sound_trigger_check_and_get_session(in);
9383
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309384 lock_input_stream(in);
9385 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9386 pthread_mutex_lock(&adev->lock);
9387 in->card_status = adev->card_status;
9388 pthread_mutex_unlock(&adev->lock);
9389 pthread_mutex_unlock(&in->lock);
9390
Aalique Grahame22e49102018-12-18 14:23:57 -08009391 stream_app_type_cfg_init(&in->app_type_cfg);
9392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009393 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009394
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009395 ret = io_streams_map_insert(adev, &in->stream.common,
9396 handle, AUDIO_PATCH_HANDLE_NONE);
9397 if (ret != 0)
9398 goto err_open;
9399
Derek Chenf939fb72018-11-13 13:34:41 -08009400 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9401 calloc(1, sizeof(streams_input_ctxt_t));
9402 if (in_ctxt == NULL) {
9403 ALOGE("%s fail to allocate input ctxt", __func__);
9404 ret = -ENOMEM;
9405 goto err_open;
9406 }
9407 in_ctxt->input = in;
9408
9409 pthread_mutex_lock(&adev->lock);
9410 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9411 pthread_mutex_unlock(&adev->lock);
9412
Eric Laurent994a6932013-07-17 11:51:42 -07009413 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009414 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009415
9416err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309417 if (in->usecase == USECASE_AUDIO_RECORD) {
9418 pthread_mutex_lock(&adev->lock);
9419 adev->pcm_record_uc_state = 0;
9420 pthread_mutex_unlock(&adev->lock);
9421 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009422 free(in);
9423 *stream_in = NULL;
9424 return ret;
9425}
9426
9427static void adev_close_input_stream(struct audio_hw_device *dev,
9428 struct audio_stream_in *stream)
9429{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009430 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009431 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009432 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309433
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309434 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009435
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009436 if (in == NULL) {
9437 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9438 return;
9439 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009440 io_streams_map_remove(adev, in->capture_handle);
9441
kunleiz70e57612018-12-28 17:50:23 +08009442 /* must deregister from sndmonitor first to prevent races
9443 * between the callback and close_stream
9444 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309445 audio_extn_snd_mon_unregister_listener(stream);
9446
kunleiz70e57612018-12-28 17:50:23 +08009447 /* Disable echo reference if there are no active input, hfp call
9448 * and sound trigger while closing input stream
9449 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009450 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009451 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009452 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9453 struct listnode out_devices;
9454 list_init(&out_devices);
9455 platform_set_echo_reference(adev, false, &out_devices);
9456 } else
kunleiz70e57612018-12-28 17:50:23 +08009457 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309458
Weiyin Jiang2995f662019-04-17 14:25:12 +08009459 error_log_destroy(in->error_log);
9460 in->error_log = NULL;
9461
Pallavid7c7a272018-01-16 11:22:55 +05309462
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009463 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309464 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009465 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309466 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009467 if (ret != 0)
9468 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9469 __func__, ret);
9470 } else
9471 in_standby(&stream->common);
9472
Revathi Uddarajud2634032017-12-07 14:42:34 +05309473 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309474 if (in->usecase == USECASE_AUDIO_RECORD) {
9475 adev->pcm_record_uc_state = 0;
9476 }
9477
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009478 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9479 adev->enable_voicerx = false;
9480 }
9481
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009482 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009483 audio_extn_ssr_deinit();
9484 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009485
Garmond Leunge2433c32017-09-28 21:51:22 -07009486 if (audio_extn_ffv_get_stream() == in) {
9487 audio_extn_ffv_stream_deinit();
9488 }
9489
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309490 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009491 audio_extn_compr_cap_format_supported(in->config.format))
9492 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309493
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309494 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309495 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009496
Mingming Yinfd7607b2016-01-22 12:48:44 -08009497 if (in->is_st_session) {
9498 ALOGV("%s: sound trigger pcm stop lab", __func__);
9499 audio_extn_sound_trigger_stop_lab(in);
9500 }
Derek Chenf939fb72018-11-13 13:34:41 -08009501 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9502 if (in_ctxt != NULL) {
9503 list_remove(&in_ctxt->list);
9504 free(in_ctxt);
9505 } else {
9506 ALOGW("%s, input stream already closed", __func__);
9507 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009508 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309509 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009510 return;
9511}
9512
Aalique Grahame22e49102018-12-18 14:23:57 -08009513/* verifies input and output devices and their capabilities.
9514 *
9515 * This verification is required when enabling extended bit-depth or
9516 * sampling rates, as not all qcom products support it.
9517 *
9518 * Suitable for calling only on initialization such as adev_open().
9519 * It fills the audio_device use_case_table[] array.
9520 *
9521 * Has a side-effect that it needs to configure audio routing / devices
9522 * in order to power up the devices and read the device parameters.
9523 * It does not acquire any hw device lock. Should restore the devices
9524 * back to "normal state" upon completion.
9525 */
9526static int adev_verify_devices(struct audio_device *adev)
9527{
9528 /* enumeration is a bit difficult because one really wants to pull
9529 * the use_case, device id, etc from the hidden pcm_device_table[].
9530 * In this case there are the following use cases and device ids.
9531 *
9532 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9533 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9534 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9535 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9536 * [USECASE_AUDIO_RECORD] = {0, 0},
9537 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9538 * [USECASE_VOICE_CALL] = {2, 2},
9539 *
9540 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9541 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9542 */
9543
9544 /* should be the usecases enabled in adev_open_input_stream() */
9545 static const int test_in_usecases[] = {
9546 USECASE_AUDIO_RECORD,
9547 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9548 };
9549 /* should be the usecases enabled in adev_open_output_stream()*/
9550 static const int test_out_usecases[] = {
9551 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9552 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9553 };
9554 static const usecase_type_t usecase_type_by_dir[] = {
9555 PCM_PLAYBACK,
9556 PCM_CAPTURE,
9557 };
9558 static const unsigned flags_by_dir[] = {
9559 PCM_OUT,
9560 PCM_IN,
9561 };
9562
9563 size_t i;
9564 unsigned dir;
9565 const unsigned card_id = adev->snd_card;
9566
9567 for (dir = 0; dir < 2; ++dir) {
9568 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9569 const unsigned flags_dir = flags_by_dir[dir];
9570 const size_t testsize =
9571 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9572 const int *testcases =
9573 dir ? test_in_usecases : test_out_usecases;
9574 const audio_devices_t audio_device =
9575 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9576
9577 for (i = 0; i < testsize; ++i) {
9578 const audio_usecase_t audio_usecase = testcases[i];
9579 int device_id;
9580 struct pcm_params **pparams;
9581 struct stream_out out;
9582 struct stream_in in;
9583 struct audio_usecase uc_info;
9584 int retval;
9585
9586 pparams = &adev->use_case_table[audio_usecase];
9587 pcm_params_free(*pparams); /* can accept null input */
9588 *pparams = NULL;
9589
9590 /* find the device ID for the use case (signed, for error) */
9591 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9592 if (device_id < 0)
9593 continue;
9594
9595 /* prepare structures for device probing */
9596 memset(&uc_info, 0, sizeof(uc_info));
9597 uc_info.id = audio_usecase;
9598 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009599 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009600 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009601 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009602 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009603 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009604 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9605 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009606 }
9607 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009608 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009609 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009610 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009611 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009612 uc_info.in_snd_device = SND_DEVICE_NONE;
9613 uc_info.out_snd_device = SND_DEVICE_NONE;
9614 list_add_tail(&adev->usecase_list, &uc_info.list);
9615
9616 /* select device - similar to start_(in/out)put_stream() */
9617 retval = select_devices(adev, audio_usecase);
9618 if (retval >= 0) {
9619 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9620#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009621 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009622 if (*pparams) {
9623 ALOGV("%s: (%s) card %d device %d", __func__,
9624 dir ? "input" : "output", card_id, device_id);
9625 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9626 } else {
9627 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9628 }
9629#endif
9630 }
9631
9632 /* deselect device - similar to stop_(in/out)put_stream() */
9633 /* 1. Get and set stream specific mixer controls */
9634 retval = disable_audio_route(adev, &uc_info);
9635 /* 2. Disable the rx device */
9636 retval = disable_snd_device(adev,
9637 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9638 list_remove(&uc_info.list);
9639 }
9640 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009641 return 0;
9642}
9643
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009644int update_patch(unsigned int num_sources,
9645 const struct audio_port_config *sources,
9646 unsigned int num_sinks,
9647 const struct audio_port_config *sinks,
9648 audio_patch_handle_t handle,
9649 struct audio_patch_info *p_info,
9650 patch_type_t patch_type, bool new_patch)
9651{
9652 ALOGD("%s: enter", __func__);
9653
9654 if (p_info == NULL) {
9655 ALOGE("%s: Invalid patch pointer", __func__);
9656 return -EINVAL;
9657 }
9658
9659 if (new_patch) {
9660 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9661 if (p_info->patch == NULL) {
9662 ALOGE("%s: Could not allocate patch", __func__);
9663 return -ENOMEM;
9664 }
9665 }
9666
9667 p_info->patch->id = handle;
9668 p_info->patch->num_sources = num_sources;
9669 p_info->patch->num_sinks = num_sinks;
9670
9671 for (int i = 0; i < num_sources; i++)
9672 p_info->patch->sources[i] = sources[i];
9673 for (int i = 0; i < num_sinks; i++)
9674 p_info->patch->sinks[i] = sinks[i];
9675
9676 p_info->patch_type = patch_type;
9677 return 0;
9678}
9679
9680audio_patch_handle_t generate_patch_handle()
9681{
9682 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9683 if (++patch_handle < 0)
9684 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9685 return patch_handle;
9686}
9687
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309688int adev_create_audio_patch(struct audio_hw_device *dev,
9689 unsigned int num_sources,
9690 const struct audio_port_config *sources,
9691 unsigned int num_sinks,
9692 const struct audio_port_config *sinks,
9693 audio_patch_handle_t *handle)
9694{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009695 int ret = 0;
9696 struct audio_device *adev = (struct audio_device *)dev;
9697 struct audio_patch_info *p_info = NULL;
9698 patch_type_t patch_type = PATCH_NONE;
9699 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9700 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9701 struct audio_stream_info *s_info = NULL;
9702 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009703 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009704 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9705 bool new_patch = false;
9706 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309707
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009708 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9709 num_sources, num_sinks, *handle);
9710
9711 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9712 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9713 ALOGE("%s: Invalid patch arguments", __func__);
9714 ret = -EINVAL;
9715 goto done;
9716 }
9717
9718 if (num_sources > 1) {
9719 ALOGE("%s: Multiple sources are not supported", __func__);
9720 ret = -EINVAL;
9721 goto done;
9722 }
9723
9724 if (sources == NULL || sinks == NULL) {
9725 ALOGE("%s: Invalid sources or sinks port config", __func__);
9726 ret = -EINVAL;
9727 goto done;
9728 }
9729
9730 ALOGV("%s: source role %d, source type %d", __func__,
9731 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009732 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009733
9734 // Populate source/sink information and fetch stream info
9735 switch (sources[0].type) {
9736 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9737 device_type = sources[0].ext.device.type;
9738 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009739 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009740 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9741 patch_type = PATCH_CAPTURE;
9742 io_handle = sinks[0].ext.mix.handle;
9743 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009744 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009745 __func__, device_type, io_handle);
9746 } else {
9747 // Device to device patch is not implemented.
9748 // This space will need changes if audio HAL
9749 // handles device to device patches in the future.
9750 patch_type = PATCH_DEVICE_LOOPBACK;
9751 }
9752 break;
9753 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9754 io_handle = sources[0].ext.mix.handle;
9755 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009756 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009757 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009758 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009759 }
9760 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009761 ALOGD("%s: Playback patch from mix handle %d to device %x",
9762 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009763 break;
9764 case AUDIO_PORT_TYPE_SESSION:
9765 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009766 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9767 ret = -EINVAL;
9768 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009769 }
9770
9771 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009772
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009773 // Generate patch info and update patch
9774 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009775 *handle = generate_patch_handle();
9776 p_info = (struct audio_patch_info *)
9777 calloc(1, sizeof(struct audio_patch_info));
9778 if (p_info == NULL) {
9779 ALOGE("%s: Failed to allocate memory", __func__);
9780 pthread_mutex_unlock(&adev->lock);
9781 ret = -ENOMEM;
9782 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009783 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009784 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009785 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009786 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009787 if (p_info == NULL) {
9788 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9789 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009790 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009791 ret = -EINVAL;
9792 goto done;
9793 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009794 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009795 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009796 *handle, p_info, patch_type, new_patch);
9797
9798 // Fetch stream info of associated mix for playback or capture patches
9799 if (p_info->patch_type == PATCH_PLAYBACK ||
9800 p_info->patch_type == PATCH_CAPTURE) {
9801 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9802 if (s_info == NULL) {
9803 ALOGE("%s: Failed to obtain stream info", __func__);
9804 if (new_patch)
9805 free(p_info);
9806 pthread_mutex_unlock(&adev->lock);
9807 ret = -EINVAL;
9808 goto done;
9809 }
9810 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9811 s_info->patch_handle = *handle;
9812 stream = s_info->stream;
9813 }
9814 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009815
9816 // Update routing for stream
9817 if (stream != NULL) {
9818 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009819 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009820 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009821 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009822 if (ret < 0) {
9823 pthread_mutex_lock(&adev->lock);
9824 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9825 if (new_patch)
9826 free(p_info);
9827 pthread_mutex_unlock(&adev->lock);
9828 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9829 goto done;
9830 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009831 }
9832
9833 // Add new patch to patch map
9834 if (!ret && new_patch) {
9835 pthread_mutex_lock(&adev->lock);
9836 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009837 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009838 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009839 }
9840
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009841done:
9842 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009843 num_sources,
9844 sources,
9845 num_sinks,
9846 sinks,
9847 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009848 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009849 num_sources,
9850 sources,
9851 num_sinks,
9852 sinks,
9853 handle);
9854 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309855}
9856
9857int adev_release_audio_patch(struct audio_hw_device *dev,
9858 audio_patch_handle_t handle)
9859{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009860 struct audio_device *adev = (struct audio_device *) dev;
9861 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009862 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009863 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009864
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009865 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9866 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9867 ret = -EINVAL;
9868 goto done;
9869 }
9870
9871 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009872 pthread_mutex_lock(&adev->lock);
9873 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009874 if (p_info == NULL) {
9875 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009876 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009877 ret = -EINVAL;
9878 goto done;
9879 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009880 struct audio_patch *patch = p_info->patch;
9881 if (patch == NULL) {
9882 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009883 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009884 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009885 goto done;
9886 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009887 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9888 switch (patch->sources[0].type) {
9889 case AUDIO_PORT_TYPE_MIX:
9890 io_handle = patch->sources[0].ext.mix.handle;
9891 break;
9892 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009893 if (p_info->patch_type == PATCH_CAPTURE)
9894 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009895 break;
9896 case AUDIO_PORT_TYPE_SESSION:
9897 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009898 pthread_mutex_unlock(&adev->lock);
9899 ret = -EINVAL;
9900 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009901 }
9902
9903 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009904 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009905 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009906 if (patch_type == PATCH_PLAYBACK ||
9907 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009908 struct audio_stream_info *s_info =
9909 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9910 if (s_info == NULL) {
9911 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9912 pthread_mutex_unlock(&adev->lock);
9913 goto done;
9914 }
9915 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9916 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009917 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009918 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009919
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009920 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009921 struct listnode devices;
9922 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009923 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009924 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009925 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009926 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009927 }
9928
9929 if (ret < 0)
9930 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9931
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009932done:
9933 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9934 audio_extn_auto_hal_release_audio_patch(dev, handle);
9935
9936 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009937 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309938}
9939
9940int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9941{
Derek Chenf13dd492018-11-13 14:53:51 -08009942 int ret = 0;
9943
9944 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9945 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9946 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309947}
9948
9949int adev_set_audio_port_config(struct audio_hw_device *dev,
9950 const struct audio_port_config *config)
9951{
Derek Chenf13dd492018-11-13 14:53:51 -08009952 int ret = 0;
9953
9954 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9955 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9956 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309957}
9958
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009959static int adev_dump(const audio_hw_device_t *device __unused,
9960 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009961{
9962 return 0;
9963}
9964
9965static int adev_close(hw_device_t *device)
9966{
Aalique Grahame22e49102018-12-18 14:23:57 -08009967 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309968 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009969
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309970 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009971 return 0;
9972
9973 pthread_mutex_lock(&adev_init_lock);
9974
9975 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309976 if (audio_extn_spkr_prot_is_enabled())
9977 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309978 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309979 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009980 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009981 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009982 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009983 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309984 audio_extn_utils_release_streams_cfg_lists(
9985 &adev->streams_output_cfg_list,
9986 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309987 if (audio_extn_qap_is_enabled())
9988 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309989 if (audio_extn_qaf_is_enabled())
9990 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009991 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009992 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009993 free(adev->snd_dev_ref_cnt);
9994 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009995 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9996 pcm_params_free(adev->use_case_table[i]);
9997 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009998 if (adev->adm_deinit)
9999 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010000 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010001 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010002 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010003 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010004 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010005 if (adev->device_cfg_params) {
10006 free(adev->device_cfg_params);
10007 adev->device_cfg_params = NULL;
10008 }
Derek Chend2530072014-11-24 12:39:14 -080010009 if(adev->ext_hw_plugin)
10010 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010011 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010012 free_map(adev->patch_map);
10013 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010014 free(device);
10015 adev = NULL;
10016 }
10017 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010018 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010019 return 0;
10020}
10021
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010022/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10023 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10024 * just that it _might_ work.
10025 */
10026static int period_size_is_plausible_for_low_latency(int period_size)
10027{
10028 switch (period_size) {
10029 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010030 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010031 case 240:
10032 case 320:
10033 case 480:
10034 return 1;
10035 default:
10036 return 0;
10037 }
10038}
10039
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010040static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10041{
10042 bool is_snd_card_status = false;
10043 bool is_ext_device_status = false;
10044 char value[32];
10045 int card = -1;
10046 card_status_t status;
10047
10048 if (cookie != adev || !parms)
10049 return;
10050
10051 if (!parse_snd_card_status(parms, &card, &status)) {
10052 is_snd_card_status = true;
10053 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10054 is_ext_device_status = true;
10055 } else {
10056 // not a valid event
10057 return;
10058 }
10059
10060 pthread_mutex_lock(&adev->lock);
10061 if (card == adev->snd_card || is_ext_device_status) {
10062 if (is_snd_card_status && adev->card_status != status) {
10063 adev->card_status = status;
10064 platform_snd_card_update(adev->platform, status);
10065 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010066 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010067 if (status == CARD_STATUS_OFFLINE)
10068 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010069 } else if (is_ext_device_status) {
10070 platform_set_parameters(adev->platform, parms);
10071 }
10072 }
10073 pthread_mutex_unlock(&adev->lock);
10074 return;
10075}
10076
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010077/* out and adev lock held */
10078static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10079{
10080 struct audio_usecase *uc_info;
10081 float left_p;
10082 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010083 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010084
10085 uc_info = get_usecase_from_list(adev, out->usecase);
10086 if (uc_info == NULL) {
10087 ALOGE("%s: Could not find the usecase (%d) in the list",
10088 __func__, out->usecase);
10089 return -EINVAL;
10090 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010091 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010092
10093 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10094 out->usecase, use_case_table[out->usecase]);
10095
10096 if (restore) {
10097 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010098 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010099 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010100 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10101 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010102 pthread_mutex_lock(&out->compr_mute_lock);
10103 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010104 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010105 out->a2dp_compress_mute = false;
10106 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10107 }
10108 pthread_mutex_unlock(&out->compr_mute_lock);
10109 }
10110 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010111 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10112 // mute compress stream if suspended
10113 pthread_mutex_lock(&out->compr_mute_lock);
10114 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010115 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010116 assign_devices(&devices, &out->device_list);
10117 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010118 left_p = out->volume_l;
10119 right_p = out->volume_r;
10120 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10121 compress_pause(out->compr);
10122 out_set_compr_volume(&out->stream, (float)0, (float)0);
10123 out->a2dp_compress_mute = true;
10124 select_devices(adev, out->usecase);
10125 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10126 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010127 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010128 out->volume_l = left_p;
10129 out->volume_r = right_p;
10130 }
Zhou Songc576a452019-09-09 14:17:40 +080010131 pthread_mutex_unlock(&out->compr_mute_lock);
10132 } else {
10133 // tear down a2dp path for non offloaded streams
10134 if (audio_extn_a2dp_source_is_suspended())
10135 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010136 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010137 }
10138 ALOGV("%s: exit", __func__);
10139 return 0;
10140}
10141
10142int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10143{
10144 int ret = 0;
10145
10146 lock_output_stream(out);
10147 pthread_mutex_lock(&adev->lock);
10148
10149 ret = check_a2dp_restore_l(adev, out, restore);
10150
10151 pthread_mutex_unlock(&adev->lock);
10152 pthread_mutex_unlock(&out->lock);
10153 return ret;
10154}
10155
Haynes Mathew George01156f92018-04-13 15:29:54 -070010156void adev_on_battery_status_changed(bool charging)
10157{
10158 pthread_mutex_lock(&adev->lock);
10159 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10160 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010161 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010162 pthread_mutex_unlock(&adev->lock);
10163}
10164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010165static int adev_open(const hw_module_t *module, const char *name,
10166 hw_device_t **device)
10167{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010168 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010169 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010170 char mixer_ctl_name[128] = {0};
10171 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010172
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010173 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010174 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10175
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010176 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010177 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010178 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010179 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010180 ALOGD("%s: returning existing instance of adev", __func__);
10181 ALOGD("%s: exit", __func__);
10182 pthread_mutex_unlock(&adev_init_lock);
10183 return 0;
10184 }
10185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010186 adev = calloc(1, sizeof(struct audio_device));
10187
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010188 if (!adev) {
10189 pthread_mutex_unlock(&adev_init_lock);
10190 return -ENOMEM;
10191 }
10192
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010193 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10194
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010195 // register audio ext hidl at the earliest
10196 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010197#ifdef DYNAMIC_LOG_ENABLED
10198 register_for_dynamic_logging("hal");
10199#endif
10200
Derek Chenf939fb72018-11-13 13:34:41 -080010201 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010202 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010203 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10204 maj_version = atoi(value);
10205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010206 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010207 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010208 adev->device.common.module = (struct hw_module_t *)module;
10209 adev->device.common.close = adev_close;
10210
10211 adev->device.init_check = adev_init_check;
10212 adev->device.set_voice_volume = adev_set_voice_volume;
10213 adev->device.set_master_volume = adev_set_master_volume;
10214 adev->device.get_master_volume = adev_get_master_volume;
10215 adev->device.set_master_mute = adev_set_master_mute;
10216 adev->device.get_master_mute = adev_get_master_mute;
10217 adev->device.set_mode = adev_set_mode;
10218 adev->device.set_mic_mute = adev_set_mic_mute;
10219 adev->device.get_mic_mute = adev_get_mic_mute;
10220 adev->device.set_parameters = adev_set_parameters;
10221 adev->device.get_parameters = adev_get_parameters;
10222 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10223 adev->device.open_output_stream = adev_open_output_stream;
10224 adev->device.close_output_stream = adev_close_output_stream;
10225 adev->device.open_input_stream = adev_open_input_stream;
10226 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010227 adev->device.create_audio_patch = adev_create_audio_patch;
10228 adev->device.release_audio_patch = adev_release_audio_patch;
10229 adev->device.get_audio_port = adev_get_audio_port;
10230 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010231 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010232 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010233
10234 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010235 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010236 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010237 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010238 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010239 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010240 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010241 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010242 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010243 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010244 /* Init audio and voice feature */
10245 audio_extn_feature_init();
10246 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010247 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010248 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010249 list_init(&adev->active_inputs_list);
10250 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010251 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010252 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10253 audio_extn_utils_hash_eq);
10254 if (!adev->io_streams_map) {
10255 ALOGE("%s: Could not create io streams map", __func__);
10256 ret = -ENOMEM;
10257 goto adev_open_err;
10258 }
10259 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10260 audio_extn_utils_hash_eq);
10261 if (!adev->patch_map) {
10262 ALOGE("%s: Could not create audio patch map", __func__);
10263 ret = -ENOMEM;
10264 goto adev_open_err;
10265 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010266 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010267 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010268 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010269 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010270 adev->perf_lock_opts[0] = 0x101;
10271 adev->perf_lock_opts[1] = 0x20E;
10272 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010273 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010274 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010275 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010276 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010278 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010279 adev->platform = platform_init(adev);
10280 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010281 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010282 ret = -EINVAL;
10283 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010284 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010285
Aalique Grahame22e49102018-12-18 14:23:57 -080010286 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010287 if (audio_extn_qap_is_enabled()) {
10288 ret = audio_extn_qap_init(adev);
10289 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010290 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010291 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010292 }
10293 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10294 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10295 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010296
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010297 if (audio_extn_qaf_is_enabled()) {
10298 ret = audio_extn_qaf_init(adev);
10299 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010300 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010301 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010302 }
10303
10304 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10305 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10306 }
10307
Derek Chenae7b0342019-02-08 15:17:04 -080010308 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010309 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10310
Eric Laurentc4aef752013-09-12 17:45:53 -070010311 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10312 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10313 if (adev->visualizer_lib == NULL) {
10314 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10315 } else {
10316 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10317 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010318 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010319 "visualizer_hal_start_output");
10320 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010321 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010322 "visualizer_hal_stop_output");
10323 }
10324 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010325 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010326 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010327 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010328 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010329 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010330 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010331
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010332 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10333 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10334 if (adev->offload_effects_lib == NULL) {
10335 ALOGE("%s: DLOPEN failed for %s", __func__,
10336 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10337 } else {
10338 ALOGV("%s: DLOPEN successful for %s", __func__,
10339 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10340 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010341 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010342 "offload_effects_bundle_hal_start_output");
10343 adev->offload_effects_stop_output =
10344 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10345 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010346 adev->offload_effects_set_hpx_state =
10347 (int (*)(bool))dlsym(adev->offload_effects_lib,
10348 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010349 adev->offload_effects_get_parameters =
10350 (void (*)(struct str_parms *, struct str_parms *))
10351 dlsym(adev->offload_effects_lib,
10352 "offload_effects_bundle_get_parameters");
10353 adev->offload_effects_set_parameters =
10354 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10355 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010356 }
10357 }
10358
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010359 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10360 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10361 if (adev->adm_lib == NULL) {
10362 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10363 } else {
10364 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10365 adev->adm_init = (adm_init_t)
10366 dlsym(adev->adm_lib, "adm_init");
10367 adev->adm_deinit = (adm_deinit_t)
10368 dlsym(adev->adm_lib, "adm_deinit");
10369 adev->adm_register_input_stream = (adm_register_input_stream_t)
10370 dlsym(adev->adm_lib, "adm_register_input_stream");
10371 adev->adm_register_output_stream = (adm_register_output_stream_t)
10372 dlsym(adev->adm_lib, "adm_register_output_stream");
10373 adev->adm_deregister_stream = (adm_deregister_stream_t)
10374 dlsym(adev->adm_lib, "adm_deregister_stream");
10375 adev->adm_request_focus = (adm_request_focus_t)
10376 dlsym(adev->adm_lib, "adm_request_focus");
10377 adev->adm_abandon_focus = (adm_abandon_focus_t)
10378 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010379 adev->adm_set_config = (adm_set_config_t)
10380 dlsym(adev->adm_lib, "adm_set_config");
10381 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10382 dlsym(adev->adm_lib, "adm_request_focus_v2");
10383 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10384 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10385 adev->adm_on_routing_change = (adm_on_routing_change_t)
10386 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010387 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10388 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010389 }
10390 }
10391
Aalique Grahame22e49102018-12-18 14:23:57 -080010392 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010393 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010394 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010395 //initialize this to false for now,
10396 //this will be set to true through set param
10397 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010398
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010399 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010400 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010401
10402 if (k_enable_extended_precision)
10403 adev_verify_devices(adev);
10404
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010405 adev->dsp_bit_width_enforce_mode =
10406 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010407
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010408 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10409 &adev->streams_output_cfg_list,
10410 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010411
Kiran Kandi910e1862013-10-29 13:29:42 -070010412 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010413
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010414 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010415 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010416 trial = atoi(value);
10417 if (period_size_is_plausible_for_low_latency(trial)) {
10418 pcm_config_low_latency.period_size = trial;
10419 pcm_config_low_latency.start_threshold = trial / 4;
10420 pcm_config_low_latency.avail_min = trial / 4;
10421 configured_low_latency_capture_period_size = trial;
10422 }
10423 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010424 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10425 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010426 trial = atoi(value);
10427 if (period_size_is_plausible_for_low_latency(trial)) {
10428 configured_low_latency_capture_period_size = trial;
10429 }
10430 }
10431
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010432 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10433
Eric Laurent4b084132018-10-19 17:33:43 -070010434 adev->camera_orientation = CAMERA_DEFAULT;
10435
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010436 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010437 af_period_multiplier = atoi(value);
10438 if (af_period_multiplier < 0)
10439 af_period_multiplier = 2;
10440 else if (af_period_multiplier > 4)
10441 af_period_multiplier = 4;
10442
10443 ALOGV("new period_multiplier = %d", af_period_multiplier);
10444 }
10445
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010446 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010447
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010448 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010449 pthread_mutex_unlock(&adev_init_lock);
10450
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010451 if (adev->adm_init)
10452 adev->adm_data = adev->adm_init();
10453
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010454 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010455 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010456 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010457
10458 audio_extn_snd_mon_init();
10459 pthread_mutex_lock(&adev->lock);
10460 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10461 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010462 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10463 /*
10464 * if the battery state callback happens before charging can be queried,
10465 * it will be guarded with the adev->lock held in the cb function and so
10466 * the callback value will reflect the latest state
10467 */
10468 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010469 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010470 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010471 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010472 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010473 /* Allocate memory for Device config params */
10474 adev->device_cfg_params = (struct audio_device_config_param*)
10475 calloc(platform_get_max_codec_backend(),
10476 sizeof(struct audio_device_config_param));
10477 if (adev->device_cfg_params == NULL)
10478 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010479
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010480 /*
10481 * Check if new PSPD matrix mixer control is supported. If not
10482 * supported, then set flag so that old mixer ctrl is sent while
10483 * sending pspd coefficients on older kernel version. Query mixer
10484 * control for default pcm id and channel value one.
10485 */
10486 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10487 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10488
10489 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10490 if (!ctl) {
10491 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10492 __func__, mixer_ctl_name);
10493 adev->use_old_pspd_mix_ctrl = true;
10494 }
10495
Eric Laurent994a6932013-07-17 11:51:42 -070010496 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010497 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010498
10499adev_open_err:
10500 free_map(adev->patch_map);
10501 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010502 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010503 pthread_mutex_destroy(&adev->lock);
10504 free(adev);
10505 adev = NULL;
10506 *device = NULL;
10507 pthread_mutex_unlock(&adev_init_lock);
10508 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010509}
10510
10511static struct hw_module_methods_t hal_module_methods = {
10512 .open = adev_open,
10513};
10514
10515struct audio_module HAL_MODULE_INFO_SYM = {
10516 .common = {
10517 .tag = HARDWARE_MODULE_TAG,
10518 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10519 .hal_api_version = HARDWARE_HAL_API_VERSION,
10520 .id = AUDIO_HARDWARE_MODULE_ID,
10521 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010522 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010523 .methods = &hal_module_methods,
10524 },
10525};