blob: de72fe7106abce1cb76f14dd2666b337c277322c [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 {
Zhou Song79929fe2020-01-20 17:57:43 +08003930 /*
3931 * set custom channel map if:
3932 * 1. neither mono nor stereo clips i.e. channels > 2 OR
3933 * 2. custom channel map has been set by client
3934 * else default channel map of FC/FR/FL can always be set to DSP
3935 */
3936 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
3937 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3938 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003939 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3940 adev->dsp_bit_width_enforce_mode,
3941 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003943 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003944 out->compr = compress_open(adev->snd_card,
3945 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003946 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003947 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303948 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303949 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3950 adev->card_status = CARD_STATUS_OFFLINE;
3951 out->card_status = CARD_STATUS_OFFLINE;
3952 ret = -EIO;
3953 goto error_open;
3954 }
3955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003956 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003957 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003958 compress_close(out->compr);
3959 out->compr = NULL;
3960 ret = -EIO;
3961 goto error_open;
3962 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303963 /* compress_open sends params of the track, so reset the flag here */
3964 out->is_compr_metadata_avail = false;
3965
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003966 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003967 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003968
Fred Oh3f43e742015-03-04 18:42:34 -08003969 /* Since small bufs uses blocking writes, a write will be blocked
3970 for the default max poll time (20s) in the event of an SSR.
3971 Reduce the poll time to observe and deal with SSR faster.
3972 */
Ashish Jain5106d362016-05-11 19:23:33 +05303973 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003974 compress_set_max_poll_wait(out->compr, 1000);
3975 }
3976
Manish Dewangan69426c82017-01-30 17:35:36 +05303977 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303978 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303979
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003980 audio_extn_dts_create_state_notifier_node(out->usecase);
3981 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3982 popcount(out->channel_mask),
3983 out->playback_started);
3984
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003985#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303986 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003987 audio_extn_dolby_send_ddp_endp_params(adev);
3988#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303989 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3990 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003991 if (adev->visualizer_start_output != NULL)
3992 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3993 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303994 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003995 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003996 }
Derek Chenf13dd492018-11-13 14:53:51 -08003997
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003998 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003999 /* Update cached volume from media to offload/direct stream */
4000 struct listnode *node = NULL;
4001 list_for_each(node, &adev->active_outputs_list) {
4002 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4003 streams_output_ctxt_t,
4004 list);
4005 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4006 out->volume_l = out_ctxt->output->volume_l;
4007 out->volume_r = out_ctxt->output->volume_r;
4008 }
4009 }
4010 out_set_compr_volume(&out->stream,
4011 out->volume_l, out->volume_r);
4012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004014
4015 if (ret == 0) {
4016 register_out_stream(out);
4017 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004018 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4019 ALOGE("%s: pcm stream not ready", __func__);
4020 goto error_open;
4021 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004022 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004023 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004024 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004025 if (ret < 0)
4026 goto error_open;
4027 }
4028 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004029 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304030 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004031 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004032
vivek mehtad15d2bf2019-05-17 13:35:10 -07004033 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4034 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4035 audio_low_latency_hint_start();
4036 }
4037
Manish Dewangan21a850a2017-08-14 12:03:55 +05304038 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004039 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004040 if (ret < 0)
4041 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4042 }
4043
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004044 // consider a scenario where on pause lower layers are tear down.
4045 // so on resume, swap mixer control need to be sent only when
4046 // backend is active, hence rather than sending from enable device
4047 // sending it from start of streamtream
4048
4049 platform_set_swap_channels(adev, true);
4050
Haynes Mathew George380745d2017-10-04 15:27:45 -07004051 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304052 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004053 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004054error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004055 if (adev->haptic_pcm) {
4056 pcm_close(adev->haptic_pcm);
4057 adev->haptic_pcm = NULL;
4058 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004059 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304060 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004062error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304063 /*
4064 * sleep 50ms to allow sufficient time for kernel
4065 * drivers to recover incases like SSR.
4066 */
4067 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004068error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004069 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304070 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004071 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072}
4073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074static int check_input_parameters(uint32_t sample_rate,
4075 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004076 int channel_count,
4077 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004079 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304081 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4082 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4083 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004084 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004085 !audio_extn_compr_cap_format_supported(format) &&
4086 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004087 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004088
Aalique Grahame22e49102018-12-18 14:23:57 -08004089 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4090 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4091 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4092 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4093 return -EINVAL;
4094 }
4095
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004096 switch (channel_count) {
4097 case 1:
4098 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304099 case 3:
4100 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004101 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004102 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304103 case 10:
4104 case 12:
4105 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004106 break;
4107 default:
4108 ret = -EINVAL;
4109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110
4111 switch (sample_rate) {
4112 case 8000:
4113 case 11025:
4114 case 12000:
4115 case 16000:
4116 case 22050:
4117 case 24000:
4118 case 32000:
4119 case 44100:
4120 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004121 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304122 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004123 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304124 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 break;
4126 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004127 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128 }
4129
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004130 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131}
4132
Naresh Tanniru04f71882018-06-26 17:46:22 +05304133
4134/** Add a value in a list if not already present.
4135 * @return true if value was successfully inserted or already present,
4136 * false if the list is full and does not contain the value.
4137 */
4138static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4139 for (size_t i = 0; i < list_length; i++) {
4140 if (list[i] == value) return true; // value is already present
4141 if (list[i] == 0) { // no values in this slot
4142 list[i] = value;
4143 return true; // value inserted
4144 }
4145 }
4146 return false; // could not insert value
4147}
4148
4149/** Add channel_mask in supported_channel_masks if not already present.
4150 * @return true if channel_mask was successfully inserted or already present,
4151 * false if supported_channel_masks is full and does not contain channel_mask.
4152 */
4153static void register_channel_mask(audio_channel_mask_t channel_mask,
4154 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4155 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4156 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4157}
4158
4159/** Add format in supported_formats if not already present.
4160 * @return true if format was successfully inserted or already present,
4161 * false if supported_formats is full and does not contain format.
4162 */
4163static void register_format(audio_format_t format,
4164 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4165 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4166 "%s: stream can not declare supporting its format %x", __func__, format);
4167}
4168/** Add sample_rate in supported_sample_rates if not already present.
4169 * @return true if sample_rate was successfully inserted or already present,
4170 * false if supported_sample_rates is full and does not contain sample_rate.
4171 */
4172static void register_sample_rate(uint32_t sample_rate,
4173 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4174 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4175 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4176}
4177
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004178static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4179{
4180 uint32_t high = num1, low = num2, temp = 0;
4181
4182 if (!num1 || !num2)
4183 return 0;
4184
4185 if (num1 < num2) {
4186 high = num2;
4187 low = num1;
4188 }
4189
4190 while (low != 0) {
4191 temp = low;
4192 low = high % low;
4193 high = temp;
4194 }
4195 return (num1 * num2)/high;
4196}
4197
4198static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4199{
4200 uint32_t remainder = 0;
4201
4202 if (!multiplier)
4203 return num;
4204
4205 remainder = num % multiplier;
4206 if (remainder)
4207 num += (multiplier - remainder);
4208
4209 return num;
4210}
4211
Aalique Grahame22e49102018-12-18 14:23:57 -08004212static size_t get_stream_buffer_size(size_t duration_ms,
4213 uint32_t sample_rate,
4214 audio_format_t format,
4215 int channel_count,
4216 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217{
4218 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004219 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220
Aalique Grahame22e49102018-12-18 14:23:57 -08004221 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004222 if (is_low_latency)
4223 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304224
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004225 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004226 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227
Ralf Herzbd08d632018-09-28 15:50:49 +02004228 /* make sure the size is multiple of 32 bytes and additionally multiple of
4229 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004230 * At 48 kHz mono 16-bit PCM:
4231 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4232 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004233 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004234 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004235 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004236
4237 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238}
4239
Aalique Grahame22e49102018-12-18 14:23:57 -08004240static size_t get_input_buffer_size(uint32_t sample_rate,
4241 audio_format_t format,
4242 int channel_count,
4243 bool is_low_latency)
4244{
4245 /* Don't know if USB HIFI in this context so use true to be conservative */
4246 if (check_input_parameters(sample_rate, format, channel_count,
4247 true /*is_usb_hifi */) != 0)
4248 return 0;
4249
4250 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4251 sample_rate,
4252 format,
4253 channel_count,
4254 is_low_latency);
4255}
4256
Derek Chenf6318be2017-06-12 17:16:24 -04004257size_t get_output_period_size(uint32_t sample_rate,
4258 audio_format_t format,
4259 int channel_count,
4260 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304261{
4262 size_t size = 0;
4263 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4264
4265 if ((duration == 0) || (sample_rate == 0) ||
4266 (bytes_per_sample == 0) || (channel_count == 0)) {
4267 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4268 bytes_per_sample, channel_count);
4269 return -EINVAL;
4270 }
4271
4272 size = (sample_rate *
4273 duration *
4274 bytes_per_sample *
4275 channel_count) / 1000;
4276 /*
4277 * To have same PCM samples for all channels, the buffer size requires to
4278 * be multiple of (number of channels * bytes per sample)
4279 * For writes to succeed, the buffer must be written at address which is multiple of 32
4280 */
4281 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4282
4283 return (size/(channel_count * bytes_per_sample));
4284}
4285
Zhou Song48453a02018-01-10 17:50:59 +08004286static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304287{
4288 uint64_t actual_frames_rendered = 0;
4289 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4290
4291 /* This adjustment accounts for buffering after app processor.
4292 * It is based on estimated DSP latency per use case, rather than exact.
4293 */
4294 int64_t platform_latency = platform_render_latency(out->usecase) *
4295 out->sample_rate / 1000000LL;
4296
Zhou Song48453a02018-01-10 17:50:59 +08004297 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304298 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4299 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4300 * hence only estimate.
4301 */
George Gao62ebc722019-07-29 16:29:44 -07004302 uint64_t signed_frames = 0;
4303 if (out->written >= kernel_buffer_size)
4304 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304305
George Gao62ebc722019-07-29 16:29:44 -07004306 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4307 if (signed_frames >= platform_latency)
4308 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304309
Zhou Song48453a02018-01-10 17:50:59 +08004310 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304311 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004312 if (timestamp != NULL )
4313 *timestamp = out->writeAt;
4314 } else if (timestamp != NULL) {
4315 clock_gettime(CLOCK_MONOTONIC, timestamp);
4316 }
4317 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304318
4319 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004320 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304321 (long long int)out->written, (int)kernel_buffer_size,
4322 audio_bytes_per_sample(out->compr_config.codec->format),
4323 popcount(out->channel_mask));
4324
4325 return actual_frames_rendered;
4326}
4327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4329{
4330 struct stream_out *out = (struct stream_out *)stream;
4331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004332 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333}
4334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004335static int out_set_sample_rate(struct audio_stream *stream __unused,
4336 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337{
4338 return -ENOSYS;
4339}
4340
4341static size_t out_get_buffer_size(const struct audio_stream *stream)
4342{
4343 struct stream_out *out = (struct stream_out *)stream;
4344
Varun Balaraje49253e2017-07-06 19:48:56 +05304345 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304346 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304347 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304348 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4349 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4350 else
4351 return out->compr_config.fragment_size;
4352 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004353 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304354 else if (is_offload_usecase(out->usecase) &&
4355 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304356 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004357
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004358 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004359 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360}
4361
4362static uint32_t out_get_channels(const struct audio_stream *stream)
4363{
4364 struct stream_out *out = (struct stream_out *)stream;
4365
4366 return out->channel_mask;
4367}
4368
4369static audio_format_t out_get_format(const struct audio_stream *stream)
4370{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004371 struct stream_out *out = (struct stream_out *)stream;
4372
4373 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374}
4375
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004376static int out_set_format(struct audio_stream *stream __unused,
4377 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378{
4379 return -ENOSYS;
4380}
4381
4382static int out_standby(struct audio_stream *stream)
4383{
4384 struct stream_out *out = (struct stream_out *)stream;
4385 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004386 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004387
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304388 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4389 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004391 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004393 if (adev->adm_deregister_stream)
4394 adev->adm_deregister_stream(adev->adm_data, out->handle);
4395
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004396 if (is_offload_usecase(out->usecase))
4397 stop_compressed_output_l(out);
4398
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004399 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004401 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4402 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304403 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004404 pthread_mutex_unlock(&adev->lock);
4405 pthread_mutex_unlock(&out->lock);
4406 ALOGD("VOIP output entered standby");
4407 return 0;
4408 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004409 if (out->pcm) {
4410 pcm_close(out->pcm);
4411 out->pcm = NULL;
4412 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004413 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4414 do_stop = out->playback_started;
4415 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004416
4417 if (out->mmap_shared_memory_fd >= 0) {
4418 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4419 __func__, out->mmap_shared_memory_fd);
4420 close(out->mmap_shared_memory_fd);
4421 out->mmap_shared_memory_fd = -1;
4422 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004423 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004424 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004425 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304426 out->send_next_track_params = false;
4427 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004428 out->gapless_mdata.encoder_delay = 0;
4429 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004430 if (out->compr != NULL) {
4431 compress_close(out->compr);
4432 out->compr = NULL;
4433 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004434 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004435 if (do_stop) {
4436 stop_output_stream(out);
4437 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304438 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004439 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004440 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 }
4442 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304443 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 return 0;
4445}
4446
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304447static int out_on_error(struct audio_stream *stream)
4448{
4449 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004450 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304451
4452 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004453 // always send CMD_ERROR for offload streams, this
4454 // is needed e.g. when SSR happens within compress_open
4455 // since the stream is active, offload_callback_thread is also active.
4456 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4457 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004458 }
4459 pthread_mutex_unlock(&out->lock);
4460
4461 status = out_standby(&out->stream.common);
4462
4463 lock_output_stream(out);
4464 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004465 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304466 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304467
4468 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4469 ALOGD("Setting previous card status if offline");
4470 out->prev_card_status_offline = true;
4471 }
4472
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304473 pthread_mutex_unlock(&out->lock);
4474
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004475 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304476}
4477
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304478/*
4479 *standby implementation without locks, assumes that the callee already
4480 *has taken adev and out lock.
4481 */
4482int out_standby_l(struct audio_stream *stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
4485 struct audio_device *adev = out->dev;
4486
4487 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4488 stream, out->usecase, use_case_table[out->usecase]);
4489
4490 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004491 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304492 if (adev->adm_deregister_stream)
4493 adev->adm_deregister_stream(adev->adm_data, out->handle);
4494
4495 if (is_offload_usecase(out->usecase))
4496 stop_compressed_output_l(out);
4497
4498 out->standby = true;
4499 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4500 voice_extn_compress_voip_close_output_stream(stream);
4501 out->started = 0;
4502 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004503 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304504 return 0;
4505 } else if (!is_offload_usecase(out->usecase)) {
4506 if (out->pcm) {
4507 pcm_close(out->pcm);
4508 out->pcm = NULL;
4509 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004510 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4511 if (adev->haptic_pcm) {
4512 pcm_close(adev->haptic_pcm);
4513 adev->haptic_pcm = NULL;
4514 }
4515
4516 if (adev->haptic_buffer != NULL) {
4517 free(adev->haptic_buffer);
4518 adev->haptic_buffer = NULL;
4519 adev->haptic_buffer_size = 0;
4520 }
4521 adev->haptic_pcm_device_id = 0;
4522 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304523 } else {
4524 ALOGD("copl(%p):standby", out);
4525 out->send_next_track_params = false;
4526 out->is_compr_metadata_avail = false;
4527 out->gapless_mdata.encoder_delay = 0;
4528 out->gapless_mdata.encoder_padding = 0;
4529 if (out->compr != NULL) {
4530 compress_close(out->compr);
4531 out->compr = NULL;
4532 }
4533 }
4534 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004535 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304536 }
4537 ALOGD("%s: exit", __func__);
4538 return 0;
4539}
4540
Aalique Grahame22e49102018-12-18 14:23:57 -08004541static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542{
Aalique Grahame22e49102018-12-18 14:23:57 -08004543 struct stream_out *out = (struct stream_out *)stream;
4544
4545 // We try to get the lock for consistency,
4546 // but it isn't necessary for these variables.
4547 // If we're not in standby, we may be blocked on a write.
4548 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4549 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4550 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4551
4552 if (locked) {
4553 pthread_mutex_unlock(&out->lock);
4554 }
4555
4556 // dump error info
4557 (void)error_log_dump(
4558 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 return 0;
4561}
4562
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004563static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4564{
4565 int ret = 0;
4566 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004567
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004568 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004569 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004570 return -EINVAL;
4571 }
4572
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304573 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004574
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004575 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4576 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304577 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004578 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004579 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4580 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304581 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004582 }
4583
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004584 ALOGV("%s new encoder delay %u and padding %u", __func__,
4585 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4586
4587 return 0;
4588}
4589
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004590static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4591{
4592 return out == adev->primary_output || out == adev->voice_tx_output;
4593}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004594
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304595// note: this call is safe only if the stream_cb is
4596// removed first in close_output_stream (as is done now).
4597static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4598{
4599 if (!stream || !parms)
4600 return;
4601
4602 struct stream_out *out = (struct stream_out *)stream;
4603 struct audio_device *adev = out->dev;
4604
4605 card_status_t status;
4606 int card;
4607 if (parse_snd_card_status(parms, &card, &status) < 0)
4608 return;
4609
4610 pthread_mutex_lock(&adev->lock);
4611 bool valid_cb = (card == adev->snd_card);
4612 pthread_mutex_unlock(&adev->lock);
4613
4614 if (!valid_cb)
4615 return;
4616
4617 lock_output_stream(out);
4618 if (out->card_status != status)
4619 out->card_status = status;
4620 pthread_mutex_unlock(&out->lock);
4621
4622 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4623 use_case_table[out->usecase],
4624 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4625
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304626 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304627 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304628 if (voice_is_call_state_active(adev) &&
4629 out == adev->primary_output) {
4630 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4631 pthread_mutex_lock(&adev->lock);
4632 voice_stop_call(adev);
4633 adev->mode = AUDIO_MODE_NORMAL;
4634 pthread_mutex_unlock(&adev->lock);
4635 }
4636 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304637 return;
4638}
4639
Kevin Rocardfce19002017-08-07 19:21:36 -07004640static int get_alive_usb_card(struct str_parms* parms) {
4641 int card;
4642 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4643 !audio_extn_usb_alive(card)) {
4644 return card;
4645 }
4646 return -ENODEV;
4647}
4648
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004649int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004650 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004651{
4652 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004653 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004654 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004655 bool bypass_a2dp = false;
4656 bool reconfig = false;
4657 unsigned long service_interval = 0;
4658
4659 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004660 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4661
4662 list_init(&new_devices);
4663 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004664
4665 lock_output_stream(out);
4666 pthread_mutex_lock(&adev->lock);
4667
4668 /*
4669 * When HDMI cable is unplugged the music playback is paused and
4670 * the policy manager sends routing=0. But the audioflinger continues
4671 * to write data until standby time (3sec). As the HDMI core is
4672 * turned off, the write gets blocked.
4673 * Avoid this by routing audio to speaker until standby.
4674 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004675 if (is_single_device_type_equal(&out->device_list,
4676 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004677 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004678 !audio_extn_passthru_is_passthrough_stream(out) &&
4679 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004680 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004681 }
4682 /*
4683 * When A2DP is disconnected the
4684 * music playback is paused and the policy manager sends routing=0
4685 * But the audioflinger continues to write data until standby time
4686 * (3sec). As BT is turned off, the write gets blocked.
4687 * Avoid this by routing audio to speaker until standby.
4688 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004689 if (is_a2dp_out_device_type(&out->device_list) &&
4690 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004691 !audio_extn_a2dp_source_is_ready() &&
4692 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004693 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004694 }
4695 /*
4696 * When USB headset is disconnected the music platback paused
4697 * and the policy manager send routing=0. But if the USB is connected
4698 * back before the standby time, AFE is not closed and opened
4699 * when USB is connected back. So routing to speker will guarantee
4700 * AFE reconfiguration and AFE will be opend once USB is connected again
4701 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004702 if (is_usb_out_device_type(&out->device_list) &&
4703 list_empty(&new_devices) &&
4704 !audio_extn_usb_connected(NULL)) {
4705 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4706 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004707 /* To avoid a2dp to sco overlapping / BT device improper state
4708 * check with BT lib about a2dp streaming support before routing
4709 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004710 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004711 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004712 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4713 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004714 //combo usecase just by pass a2dp
4715 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4716 bypass_a2dp = true;
4717 } else {
4718 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4719 /* update device to a2dp and don't route as BT returned error
4720 * However it is still possible a2dp routing called because
4721 * of current active device disconnection (like wired headset)
4722 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004723 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004724 pthread_mutex_unlock(&adev->lock);
4725 pthread_mutex_unlock(&out->lock);
4726 goto error;
4727 }
4728 }
4729 }
4730
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004731 // Workaround: If routing to an non existing usb device, fail gracefully
4732 // The routing request will otherwise block during 10 second
4733 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004734 if (is_usb_out_device_type(&new_devices)) {
4735 struct str_parms *parms =
4736 str_parms_create_str(get_usb_device_address(&new_devices));
4737 if (!parms)
4738 goto error;
4739 if ((card = get_alive_usb_card(parms)) >= 0) {
4740 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4741 pthread_mutex_unlock(&adev->lock);
4742 pthread_mutex_unlock(&out->lock);
4743 str_parms_destroy(parms);
4744 ret = -ENOSYS;
4745 goto error;
4746 }
4747 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004748 }
4749
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004750 // Workaround: If routing to an non existing hdmi device, fail gracefully
4751 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4752 (platform_get_edid_info_v2(adev->platform,
4753 out->extconn.cs.controller,
4754 out->extconn.cs.stream) != 0)) {
4755 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4756 pthread_mutex_unlock(&adev->lock);
4757 pthread_mutex_unlock(&out->lock);
4758 ret = -ENOSYS;
4759 goto error;
4760 }
4761
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004762 /*
4763 * select_devices() call below switches all the usecases on the same
4764 * backend to the new device. Refer to check_usecases_codec_backend() in
4765 * the select_devices(). But how do we undo this?
4766 *
4767 * For example, music playback is active on headset (deep-buffer usecase)
4768 * and if we go to ringtones and select a ringtone, low-latency usecase
4769 * will be started on headset+speaker. As we can't enable headset+speaker
4770 * and headset devices at the same time, select_devices() switches the music
4771 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4772 * So when the ringtone playback is completed, how do we undo the same?
4773 *
4774 * We are relying on the out_set_parameters() call on deep-buffer output,
4775 * once the ringtone playback is ended.
4776 * NOTE: We should not check if the current devices are same as new devices.
4777 * Because select_devices() must be called to switch back the music
4778 * playback to headset.
4779 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004780 if (!list_empty(&new_devices)) {
4781 bool same_dev = compare_devices(&out->device_list, &new_devices);
4782 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004783
4784 if (output_drives_call(adev, out)) {
4785 if (!voice_is_call_state_active(adev)) {
4786 if (adev->mode == AUDIO_MODE_IN_CALL) {
4787 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004788 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004789 service_interval =
4790 audio_extn_usb_find_service_interval(true, true /*playback*/);
4791 audio_extn_usb_set_service_interval(true /*playback*/,
4792 service_interval,
4793 &reconfig);
4794 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4795 }
4796 ret = voice_start_call(adev);
4797 }
4798 } else {
4799 adev->current_call_output = out;
4800 voice_update_devices_for_all_voice_usecases(adev);
4801 }
4802 }
4803
4804 if (!out->standby) {
4805 if (!same_dev) {
4806 ALOGV("update routing change");
4807 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4808 adev->perf_lock_opts,
4809 adev->perf_lock_opts_size);
4810 if (adev->adm_on_routing_change)
4811 adev->adm_on_routing_change(adev->adm_data,
4812 out->handle);
4813 }
4814 if (!bypass_a2dp) {
4815 select_devices(adev, out->usecase);
4816 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004817 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4818 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004820 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004821 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004822 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004823 }
4824
4825 if (!same_dev) {
4826 // on device switch force swap, lower functions will make sure
4827 // to check if swap is allowed or not.
4828 platform_set_swap_channels(adev, true);
4829 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4830 }
4831 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4832 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004833 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004834 pthread_mutex_lock(&out->compr_mute_lock);
4835 out->a2dp_compress_mute = false;
4836 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4837 pthread_mutex_unlock(&out->compr_mute_lock);
4838 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4839 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4840 }
4841 }
4842 }
4843
4844 pthread_mutex_unlock(&adev->lock);
4845 pthread_mutex_unlock(&out->lock);
4846
4847 /*handles device and call state changes*/
4848 audio_extn_extspk_update(adev->extspk);
4849
4850error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004851 ALOGV("%s: exit: code(%d)", __func__, ret);
4852 return ret;
4853}
4854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4856{
4857 struct stream_out *out = (struct stream_out *)stream;
4858 struct audio_device *adev = out->dev;
4859 struct str_parms *parms;
4860 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004861 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004862 int ext_controller = -1;
4863 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864
sangwoobc677242013-08-08 16:53:43 +09004865 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004866 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304868 if (!parms)
4869 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004870
4871 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4872 &ext_stream);
4873 if (err >= 0) {
4874 out->extconn.cs.controller = ext_controller;
4875 out->extconn.cs.stream = ext_stream;
4876 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4877 use_case_table[out->usecase], out->extconn.cs.controller,
4878 out->extconn.cs.stream);
4879 }
4880
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004881 if (out == adev->primary_output) {
4882 pthread_mutex_lock(&adev->lock);
4883 audio_extn_set_parameters(adev, parms);
4884 pthread_mutex_unlock(&adev->lock);
4885 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004886 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004887 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004888 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004889
4890 audio_extn_dts_create_state_notifier_node(out->usecase);
4891 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4892 popcount(out->channel_mask),
4893 out->playback_started);
4894
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004895 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004896 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004897
Surendar Karkaf51b5842018-04-26 11:28:38 +05304898 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4899 sizeof(value));
4900 if (err >= 0) {
4901 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4902 audio_extn_send_dual_mono_mixing_coefficients(out);
4903 }
4904
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304905 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4906 if (err >= 0) {
4907 strlcpy(out->profile, value, sizeof(out->profile));
4908 ALOGV("updating stream profile with value '%s'", out->profile);
4909 lock_output_stream(out);
4910 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4911 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004912 &out->device_list, out->flags,
4913 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304914 out->sample_rate, out->bit_width,
4915 out->channel_mask, out->profile,
4916 &out->app_type_cfg);
4917 pthread_mutex_unlock(&out->lock);
4918 }
4919
Alexy Joseph98988832017-01-13 14:56:59 -08004920 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004921 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4922 // and vendor.audio.hal.output.suspend.supported is set to true
4923 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004924 //check suspend parameter only for low latency and if the property
4925 //is enabled
4926 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4927 ALOGI("%s: got suspend_playback %s", __func__, value);
4928 lock_output_stream(out);
4929 if (!strncmp(value, "false", 5)) {
4930 //suspend_playback=false is supposed to set QOS value back to 75%
4931 //the mixer control sent with value Enable will achieve that
4932 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4933 } else if (!strncmp (value, "true", 4)) {
4934 //suspend_playback=true is supposed to remove QOS value
4935 //resetting the mixer control will set the default value
4936 //for the mixer control which is Disable and this removes the QOS vote
4937 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4938 } else {
4939 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4940 " got %s", __func__, value);
4941 ret = -1;
4942 }
4943
4944 if (ret != 0) {
4945 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4946 __func__, out->pm_qos_mixer_path, ret);
4947 }
4948
4949 pthread_mutex_unlock(&out->lock);
4950 }
4951 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004952
Alexy Joseph98988832017-01-13 14:56:59 -08004953 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004954 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304955error:
Eric Laurent994a6932013-07-17 11:51:42 -07004956 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957 return ret;
4958}
4959
Paul McLeana50b7332018-12-17 08:24:21 -07004960static int in_set_microphone_direction(const struct audio_stream_in *stream,
4961 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004962 struct stream_in *in = (struct stream_in *)stream;
4963
4964 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4965
4966 in->direction = dir;
4967
4968 if (in->standby)
4969 return 0;
4970
4971 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004972}
4973
4974static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004975 struct stream_in *in = (struct stream_in *)stream;
4976
4977 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4978
4979 if (zoom > 1.0 || zoom < -1.0)
4980 return -EINVAL;
4981
4982 in->zoom = zoom;
4983
4984 if (in->standby)
4985 return 0;
4986
4987 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004988}
4989
4990
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004991static bool stream_get_parameter_channels(struct str_parms *query,
4992 struct str_parms *reply,
4993 audio_channel_mask_t *supported_channel_masks) {
4994 int ret = -1;
4995 char value[512];
4996 bool first = true;
4997 size_t i, j;
4998
4999 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5000 ret = 0;
5001 value[0] = '\0';
5002 i = 0;
5003 while (supported_channel_masks[i] != 0) {
5004 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5005 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5006 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305007 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005008
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305009 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005010 first = false;
5011 break;
5012 }
5013 }
5014 i++;
5015 }
5016 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5017 }
5018 return ret == 0;
5019}
5020
5021static bool stream_get_parameter_formats(struct str_parms *query,
5022 struct str_parms *reply,
5023 audio_format_t *supported_formats) {
5024 int ret = -1;
5025 char value[256];
5026 size_t i, j;
5027 bool first = true;
5028
5029 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5030 ret = 0;
5031 value[0] = '\0';
5032 i = 0;
5033 while (supported_formats[i] != 0) {
5034 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5035 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5036 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305037 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005038 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305039 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005040 first = false;
5041 break;
5042 }
5043 }
5044 i++;
5045 }
5046 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5047 }
5048 return ret == 0;
5049}
5050
5051static bool stream_get_parameter_rates(struct str_parms *query,
5052 struct str_parms *reply,
5053 uint32_t *supported_sample_rates) {
5054
5055 int i;
5056 char value[256];
5057 int ret = -1;
5058 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5059 ret = 0;
5060 value[0] = '\0';
5061 i=0;
5062 int cursor = 0;
5063 while (supported_sample_rates[i]) {
5064 int avail = sizeof(value) - cursor;
5065 ret = snprintf(value + cursor, avail, "%s%d",
5066 cursor > 0 ? "|" : "",
5067 supported_sample_rates[i]);
5068 if (ret < 0 || ret >= avail) {
5069 // if cursor is at the last element of the array
5070 // overwrite with \0 is duplicate work as
5071 // snprintf already put a \0 in place.
5072 // else
5073 // we had space to write the '|' at value[cursor]
5074 // (which will be overwritten) or no space to fill
5075 // the first element (=> cursor == 0)
5076 value[cursor] = '\0';
5077 break;
5078 }
5079 cursor += ret;
5080 ++i;
5081 }
5082 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5083 value);
5084 }
5085 return ret >= 0;
5086}
5087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5089{
5090 struct stream_out *out = (struct stream_out *)stream;
5091 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005092 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005093 char value[256];
5094 struct str_parms *reply = str_parms_create();
5095 size_t i, j;
5096 int ret;
5097 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005098
5099 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005100 if (reply) {
5101 str_parms_destroy(reply);
5102 }
5103 if (query) {
5104 str_parms_destroy(query);
5105 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005106 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5107 return NULL;
5108 }
5109
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005110 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5112 if (ret >= 0) {
5113 value[0] = '\0';
5114 i = 0;
5115 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005116 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5117 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005119 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005120 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005121 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005122 first = false;
5123 break;
5124 }
5125 }
5126 i++;
5127 }
5128 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5129 str = str_parms_to_str(reply);
5130 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005131 voice_extn_out_get_parameters(out, query, reply);
5132 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005133 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005134
Alexy Joseph62142aa2015-11-16 15:10:34 -08005135
5136 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5137 if (ret >= 0) {
5138 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305139 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5140 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005141 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305142 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005143 } else {
5144 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305145 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005146 }
5147 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005148 if (str)
5149 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005150 str = str_parms_to_str(reply);
5151 }
5152
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005153 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5154 if (ret >= 0) {
5155 value[0] = '\0';
5156 i = 0;
5157 first = true;
5158 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005159 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5160 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005161 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005162 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005163 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005164 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005165 first = false;
5166 break;
5167 }
5168 }
5169 i++;
5170 }
5171 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005172 if (str)
5173 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005174 str = str_parms_to_str(reply);
5175 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005176
5177 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5178 if (ret >= 0) {
5179 value[0] = '\0';
5180 i = 0;
5181 first = true;
5182 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005183 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5184 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005185 if (!first) {
5186 strlcat(value, "|", sizeof(value));
5187 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005188 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005189 first = false;
5190 break;
5191 }
5192 }
5193 i++;
5194 }
5195 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5196 if (str)
5197 free(str);
5198 str = str_parms_to_str(reply);
5199 }
5200
Alexy Joseph98988832017-01-13 14:56:59 -08005201 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5202 //only low latency track supports suspend_resume
5203 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005204 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005205 if (str)
5206 free(str);
5207 str = str_parms_to_str(reply);
5208 }
5209
5210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 str_parms_destroy(query);
5212 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005213 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 return str;
5215}
5216
5217static uint32_t out_get_latency(const struct audio_stream_out *stream)
5218{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005219 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005221 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222
Alexy Josephaa54c872014-12-03 02:46:47 -08005223 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305224 lock_output_stream(out);
5225 latency = audio_extn_utils_compress_get_dsp_latency(out);
5226 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005227 } else if ((out->realtime) ||
5228 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005229 // since the buffer won't be filled up faster than realtime,
5230 // return a smaller number
5231 if (out->config.rate)
5232 period_ms = (out->af_period_multiplier * out->config.period_size *
5233 1000) / (out->config.rate);
5234 else
5235 period_ms = 0;
5236 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005237 } else {
5238 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005239 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005240 }
5241
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005242 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005243 latency += audio_extn_a2dp_get_encoder_latency();
5244
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305245 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005246 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247}
5248
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305249static float AmpToDb(float amplification)
5250{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305251 float db = DSD_VOLUME_MIN_DB;
5252 if (amplification > 0) {
5253 db = 20 * log10(amplification);
5254 if(db < DSD_VOLUME_MIN_DB)
5255 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305256 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305257 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305258}
5259
Arun Mirpuri5d170872019-03-26 13:21:31 -07005260static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5261 float right)
5262{
5263 struct stream_out *out = (struct stream_out *)stream;
5264 long volume = 0;
5265 char mixer_ctl_name[128] = "";
5266 struct audio_device *adev = out->dev;
5267 struct mixer_ctl *ctl = NULL;
5268 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5269 PCM_PLAYBACK);
5270
5271 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5272 "Playback %d Volume", pcm_device_id);
5273 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5274 if (!ctl) {
5275 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5276 __func__, mixer_ctl_name);
5277 return -EINVAL;
5278 }
5279 if (left != right)
5280 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5281 __func__, left, right);
5282 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5283 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5284 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5285 __func__, mixer_ctl_name, volume);
5286 return -EINVAL;
5287 }
5288 return 0;
5289}
5290
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305291static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5292 float right)
5293{
5294 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305295 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305296 char mixer_ctl_name[128];
5297 struct audio_device *adev = out->dev;
5298 struct mixer_ctl *ctl;
5299 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5300 PCM_PLAYBACK);
5301
5302 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5303 "Compress Playback %d Volume", pcm_device_id);
5304 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5305 if (!ctl) {
5306 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5307 __func__, mixer_ctl_name);
5308 return -EINVAL;
5309 }
5310 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5311 __func__, mixer_ctl_name, left, right);
5312 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5313 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5314 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5315
5316 return 0;
5317}
5318
Zhou Song2b8f28f2017-09-11 10:51:38 +08005319static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5320 float right)
5321{
5322 struct stream_out *out = (struct stream_out *)stream;
5323 char mixer_ctl_name[] = "App Type Gain";
5324 struct audio_device *adev = out->dev;
5325 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305326 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005327
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005328 if (!is_valid_volume(left, right)) {
5329 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5330 __func__, left, right);
5331 return -EINVAL;
5332 }
5333
Zhou Song2b8f28f2017-09-11 10:51:38 +08005334 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5335 if (!ctl) {
5336 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5337 __func__, mixer_ctl_name);
5338 return -EINVAL;
5339 }
5340
5341 set_values[0] = 0; //0: Rx Session 1:Tx Session
5342 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305343 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5344 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005345
5346 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5347 return 0;
5348}
5349
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305350static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5351 float right)
5352{
5353 struct stream_out *out = (struct stream_out *)stream;
5354 /* Volume control for pcm playback */
5355 if (left != right) {
5356 return -EINVAL;
5357 } else {
5358 char mixer_ctl_name[128];
5359 struct audio_device *adev = out->dev;
5360 struct mixer_ctl *ctl;
5361 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5362 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5363 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5364 if (!ctl) {
5365 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5366 return -EINVAL;
5367 }
5368
5369 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5370 int ret = mixer_ctl_set_value(ctl, 0, volume);
5371 if (ret < 0) {
5372 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5373 return -EINVAL;
5374 }
5375
5376 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5377
5378 return 0;
5379 }
5380}
5381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005382static int out_set_volume(struct audio_stream_out *stream, float left,
5383 float right)
5384{
Eric Laurenta9024de2013-04-04 09:19:12 -07005385 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005386 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305387 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005388
Arun Mirpuri5d170872019-03-26 13:21:31 -07005389 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005390 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5391 /* only take left channel into account: the API is for stereo anyway */
5392 out->muted = (left == 0.0f);
5393 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005394 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305395 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005396 /*
5397 * Set mute or umute on HDMI passthrough stream.
5398 * Only take left channel into account.
5399 * Mute is 0 and unmute 1
5400 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305401 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305402 } else if (out->format == AUDIO_FORMAT_DSD){
5403 char mixer_ctl_name[128] = "DSD Volume";
5404 struct audio_device *adev = out->dev;
5405 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5406
5407 if (!ctl) {
5408 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5409 __func__, mixer_ctl_name);
5410 return -EINVAL;
5411 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305412 volume[0] = (long)(AmpToDb(left));
5413 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305414 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5415 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005416 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005417 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005418 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5419 struct listnode *node = NULL;
5420 list_for_each(node, &adev->active_outputs_list) {
5421 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5422 streams_output_ctxt_t,
5423 list);
5424 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5425 out->volume_l = out_ctxt->output->volume_l;
5426 out->volume_r = out_ctxt->output->volume_r;
5427 }
5428 }
5429 if (!out->a2dp_compress_mute) {
5430 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5431 }
5432 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005433 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305434 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005435 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305436 if (!out->a2dp_compress_mute)
5437 ret = out_set_compr_volume(stream, left, right);
5438 out->volume_l = left;
5439 out->volume_r = right;
5440 pthread_mutex_unlock(&out->compr_mute_lock);
5441 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005442 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005443 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005444 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5445 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5446 if (!out->standby) {
5447 audio_extn_utils_send_app_type_gain(out->dev,
5448 out->app_type_cfg.app_type,
5449 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005450 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005451 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005452 out->volume_l = left;
5453 out->volume_r = right;
5454 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005455 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5456 ALOGV("%s: MMAP set volume called", __func__);
5457 if (!out->standby)
5458 ret = out_set_mmap_volume(stream, left, right);
5459 out->volume_l = left;
5460 out->volume_r = right;
5461 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305462 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305463 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5464 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305465 /* Volume control for pcm playback */
5466 if (!out->standby)
5467 ret = out_set_pcm_volume(stream, left, right);
5468 else
5469 out->apply_volume = true;
5470
5471 out->volume_l = left;
5472 out->volume_r = right;
5473 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005474 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5475 ALOGV("%s: bus device set volume called", __func__);
5476 if (!out->standby)
5477 ret = out_set_pcm_volume(stream, left, right);
5478 out->volume_l = left;
5479 out->volume_r = right;
5480 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005481 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483 return -ENOSYS;
5484}
5485
Zhou Songc9672822017-08-16 16:01:39 +08005486static void update_frames_written(struct stream_out *out, size_t bytes)
5487{
5488 size_t bpf = 0;
5489
5490 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5491 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5492 bpf = 1;
5493 else if (!is_offload_usecase(out->usecase))
5494 bpf = audio_bytes_per_sample(out->format) *
5495 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005496
5497 pthread_mutex_lock(&out->position_query_lock);
5498 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005499 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005500 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5501 }
5502 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005503}
5504
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005505int split_and_write_audio_haptic_data(struct stream_out *out,
5506 const void *buffer, size_t bytes_to_write)
5507{
5508 struct audio_device *adev = out->dev;
5509
5510 int ret = 0;
5511 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5512 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5513 size_t frame_size = channel_count * bytes_per_sample;
5514 size_t frame_count = bytes_to_write / frame_size;
5515
5516 bool force_haptic_path =
5517 property_get_bool("vendor.audio.test_haptic", false);
5518
5519 // extract Haptics data from Audio buffer
5520 bool alloc_haptic_buffer = false;
5521 int haptic_channel_count = adev->haptics_config.channels;
5522 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5523 size_t audio_frame_size = frame_size - haptic_frame_size;
5524 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5525
5526 if (adev->haptic_buffer == NULL) {
5527 alloc_haptic_buffer = true;
5528 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5529 free(adev->haptic_buffer);
5530 adev->haptic_buffer_size = 0;
5531 alloc_haptic_buffer = true;
5532 }
5533
5534 if (alloc_haptic_buffer) {
5535 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005536 if(adev->haptic_buffer == NULL) {
5537 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5538 return -ENOMEM;
5539 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005540 adev->haptic_buffer_size = total_haptic_buffer_size;
5541 }
5542
5543 size_t src_index = 0, aud_index = 0, hap_index = 0;
5544 uint8_t *audio_buffer = (uint8_t *)buffer;
5545 uint8_t *haptic_buffer = adev->haptic_buffer;
5546
5547 // This is required for testing only. This works for stereo data only.
5548 // One channel is fed to audio stream and other to haptic stream for testing.
5549 if (force_haptic_path)
5550 audio_frame_size = haptic_frame_size = bytes_per_sample;
5551
5552 for (size_t i = 0; i < frame_count; i++) {
5553 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5554 audio_frame_size);
5555 aud_index += audio_frame_size;
5556 src_index += audio_frame_size;
5557
5558 if (adev->haptic_pcm)
5559 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5560 haptic_frame_size);
5561 hap_index += haptic_frame_size;
5562 src_index += haptic_frame_size;
5563
5564 // This is required for testing only.
5565 // Discard haptic channel data.
5566 if (force_haptic_path)
5567 src_index += haptic_frame_size;
5568 }
5569
5570 // write to audio pipeline
5571 ret = pcm_write(out->pcm, (void *)audio_buffer,
5572 frame_count * audio_frame_size);
5573
5574 // write to haptics pipeline
5575 if (adev->haptic_pcm)
5576 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5577 frame_count * haptic_frame_size);
5578
5579 return ret;
5580}
5581
Aalique Grahame22e49102018-12-18 14:23:57 -08005582#ifdef NO_AUDIO_OUT
5583static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5584 const void *buffer __unused, size_t bytes)
5585{
5586 struct stream_out *out = (struct stream_out *)stream;
5587
5588 /* No Output device supported other than BT for playback.
5589 * Sleep for the amount of buffer duration
5590 */
5591 lock_output_stream(out);
5592 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5593 (const struct audio_stream_out *)&out->stream) /
5594 out_get_sample_rate(&out->stream.common));
5595 pthread_mutex_unlock(&out->lock);
5596 return bytes;
5597}
5598#endif
5599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5601 size_t bytes)
5602{
5603 struct stream_out *out = (struct stream_out *)stream;
5604 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005605 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305606 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005607 const size_t frame_size = audio_stream_out_frame_size(stream);
5608 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305609 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005610 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005611
Haynes Mathew George380745d2017-10-04 15:27:45 -07005612 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005613 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305614
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305615 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005616
Dhananjay Kumarac341582017-02-23 23:42:25 +05305617 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305618 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305619 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5620 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005621 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305622 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305623 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305624 ALOGD(" %s: sound card is not active/SSR state", __func__);
5625 ret= -EIO;
5626 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305627 }
5628 }
5629
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305630 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305631 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305632 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305633 goto exit;
5634 }
5635
Haynes Mathew George16081042017-05-31 17:16:49 -07005636 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5637 ret = -EINVAL;
5638 goto exit;
5639 }
5640
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005641 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305642 !out->is_iec61937_info_available) {
5643
5644 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5645 out->is_iec61937_info_available = true;
5646 } else if (audio_extn_passthru_is_enabled()) {
5647 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305648 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305649
5650 if((out->format == AUDIO_FORMAT_DTS) ||
5651 (out->format == AUDIO_FORMAT_DTS_HD)) {
5652 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5653 buffer, bytes);
5654 if (ret) {
5655 if (ret != -ENOSYS) {
5656 out->is_iec61937_info_available = false;
5657 ALOGD("iec61937 transmission info not yet updated retry");
5658 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305659 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305660 /* if stream has started and after that there is
5661 * stream config change (iec transmission config)
5662 * then trigger select_device to update backend configuration.
5663 */
5664 out->stream_config_changed = true;
5665 pthread_mutex_lock(&adev->lock);
5666 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305667 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005668 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305669 ret = -EINVAL;
5670 goto exit;
5671 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305672 pthread_mutex_unlock(&adev->lock);
5673 out->stream_config_changed = false;
5674 out->is_iec61937_info_available = true;
5675 }
5676 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305677
Meng Wang4c32fb42020-01-16 17:57:11 +08005678#ifdef AUDIO_GKI_ENABLED
5679 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5680 compr_passthr = out->compr_config.codec->reserved[0];
5681#else
5682 compr_passthr = out->compr_config.codec->compr_passthr;
5683#endif
5684
Garmond Leung317cbf12017-09-13 16:20:50 -07005685 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005686 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305687 (out->is_iec61937_info_available == true)) {
5688 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5689 ret = -EINVAL;
5690 goto exit;
5691 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305692 }
5693 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305694
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005695 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005696 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005697 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5698 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305699 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305700 ret = -EIO;
5701 goto exit;
5702 }
5703 }
5704 }
5705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005706 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005707 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005708 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005709 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5710 ret = voice_extn_compress_voip_start_output_stream(out);
5711 else
5712 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005713 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005714 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005716 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005717 goto exit;
5718 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305719 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005720 if (last_known_cal_step != -1) {
5721 ALOGD("%s: retry previous failed cal level set", __func__);
5722 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305723 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005724 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305725
5726 if ((out->is_iec61937_info_available == true) &&
5727 (audio_extn_passthru_is_passthrough_stream(out))&&
5728 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5729 ret = -EINVAL;
5730 goto exit;
5731 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305732 if (out->set_dual_mono)
5733 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005735
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005736 if (adev->is_channel_status_set == false &&
5737 compare_device_type(&out->device_list,
5738 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005739 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305740 adev->is_channel_status_set = true;
5741 }
5742
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305743 if ((adev->use_old_pspd_mix_ctrl == true) &&
5744 (out->pspd_coeff_sent == false)) {
5745 /*
5746 * Need to resend pspd coefficients after stream started for
5747 * older kernel version as it does not save the coefficients
5748 * and also stream has to be started for coeff to apply.
5749 */
5750 usecase = get_usecase_from_list(adev, out->usecase);
5751 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305752 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305753 out->pspd_coeff_sent = true;
5754 }
5755 }
5756
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005757 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005758 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005759 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005760 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005761 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5762 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305763 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5764 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005765 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305766 out->send_next_track_params = false;
5767 out->is_compr_metadata_avail = false;
5768 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005769 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305770 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305771 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005772
Ashish Jain83a6cc22016-06-28 14:34:17 +05305773 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305774 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305775 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305776 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005777 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305778 return -EINVAL;
5779 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305780 audio_format_t dst_format = out->hal_op_format;
5781 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305782
Dieter Luecking5d57def2018-09-07 14:23:37 +02005783 /* prevent division-by-zero */
5784 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5785 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5786 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5787 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305788 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005789 ATRACE_END();
5790 return -EINVAL;
5791 }
5792
Ashish Jainf1eaa582016-05-23 20:54:24 +05305793 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5794 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5795
Ashish Jain83a6cc22016-06-28 14:34:17 +05305796 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305797 dst_format,
5798 buffer,
5799 src_format,
5800 frames);
5801
Ashish Jain83a6cc22016-06-28 14:34:17 +05305802 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305803 bytes_to_write);
5804
5805 /*Convert written bytes in audio flinger format*/
5806 if (ret > 0)
5807 ret = ((ret * format_to_bitwidth_table[out->format]) /
5808 format_to_bitwidth_table[dst_format]);
5809 }
5810 } else
5811 ret = compress_write(out->compr, buffer, bytes);
5812
Zhou Songc9672822017-08-16 16:01:39 +08005813 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5814 update_frames_written(out, bytes);
5815
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305816 if (ret < 0)
5817 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005818 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305819 /*msg to cb thread only if non blocking write is enabled*/
5820 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305821 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005822 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305823 } else if (-ENETRESET == ret) {
5824 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305825 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305826 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305827 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005828 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305829 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005830 }
Ashish Jain5106d362016-05-11 19:23:33 +05305831
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305832 /* Call compr start only when non-zero bytes of data is there to be rendered */
5833 if (!out->playback_started && ret > 0) {
5834 int status = compress_start(out->compr);
5835 if (status < 0) {
5836 ret = status;
5837 ALOGE("%s: compr start failed with err %d", __func__, errno);
5838 goto exit;
5839 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005840 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005841 out->playback_started = 1;
5842 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005843
5844 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5845 popcount(out->channel_mask),
5846 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005847 }
5848 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005849 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005850 return ret;
5851 } else {
5852 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005853 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005854 if (out->muted)
5855 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005856 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5857 __func__, frames, frame_size, bytes_to_write);
5858
Aalique Grahame22e49102018-12-18 14:23:57 -08005859 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005860 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5861 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5862 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005863 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5864 int16_t *src = (int16_t *)buffer;
5865 int16_t *dst = (int16_t *)buffer;
5866
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005867 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005868 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005869 "out_write called for %s use case with wrong properties",
5870 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005871
5872 /*
5873 * FIXME: this can be removed once audio flinger mixer supports
5874 * mono output
5875 */
5876
5877 /*
5878 * Code below goes over each frame in the buffer and adds both
5879 * L and R samples and then divides by 2 to convert to mono
5880 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005881 if (channel_count == 2) {
5882 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5883 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5884 }
5885 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005886 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005887 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305888 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005889
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005890 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005891
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005892 if (out->config.rate)
5893 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5894 out->config.rate;
5895
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005896 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005897 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5898
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005899 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005900 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005901 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305902 out->convert_buffer != NULL) {
5903
5904 memcpy_by_audio_format(out->convert_buffer,
5905 out->hal_op_format,
5906 buffer,
5907 out->hal_ip_format,
5908 out->config.period_size * out->config.channels);
5909
5910 ret = pcm_write(out->pcm, out->convert_buffer,
5911 (out->config.period_size *
5912 out->config.channels *
5913 format_to_bitwidth_table[out->hal_op_format]));
5914 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305915 /*
5916 * To avoid underrun in DSP when the application is not pumping
5917 * data at required rate, check for the no. of bytes and ignore
5918 * pcm_write if it is less than actual buffer size.
5919 * It is a work around to a change in compress VOIP driver.
5920 */
5921 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5922 bytes < (out->config.period_size * out->config.channels *
5923 audio_bytes_per_sample(out->format))) {
5924 size_t voip_buf_size =
5925 out->config.period_size * out->config.channels *
5926 audio_bytes_per_sample(out->format);
5927 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5928 __func__, bytes, voip_buf_size);
5929 usleep(((uint64_t)voip_buf_size - bytes) *
5930 1000000 / audio_stream_out_frame_size(stream) /
5931 out_get_sample_rate(&out->stream.common));
5932 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005933 } else {
5934 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5935 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5936 else
5937 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5938 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305939 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005940
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005941 release_out_focus(out);
5942
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305943 if (ret < 0)
5944 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005945 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305946 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005948 }
5949
5950exit:
Zhou Songc9672822017-08-16 16:01:39 +08005951 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305952 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305953 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005955 pthread_mutex_unlock(&out->lock);
5956
5957 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005958 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005959 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305960 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305961 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305962 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305963 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305964 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305965 out->standby = true;
5966 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305967 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005968 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5969 /* prevent division-by-zero */
5970 uint32_t stream_size = audio_stream_out_frame_size(stream);
5971 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005972
Dieter Luecking5d57def2018-09-07 14:23:37 +02005973 if ((stream_size == 0) || (srate == 0)) {
5974 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5975 ATRACE_END();
5976 return -EINVAL;
5977 }
5978 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5979 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005980 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305981 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005982 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005983 return ret;
5984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005986 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005987 return bytes;
5988}
5989
5990static int out_get_render_position(const struct audio_stream_out *stream,
5991 uint32_t *dsp_frames)
5992{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005993 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005994
5995 if (dsp_frames == NULL)
5996 return -EINVAL;
5997
5998 *dsp_frames = 0;
5999 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006000 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306001
6002 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6003 * this operation and adev_close_output_stream(where out gets reset).
6004 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306005 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006006 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306007 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006008 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306009 return 0;
6010 }
6011
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006012 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306013 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306014 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306016 if (ret < 0)
6017 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306019 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006020 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306021 if (-ENETRESET == ret) {
6022 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306023 out->card_status = CARD_STATUS_OFFLINE;
6024 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306025 } else if(ret < 0) {
6026 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306027 ret = -EINVAL;
6028 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306029 /*
6030 * Handle corner case where compress session is closed during SSR
6031 * and timestamp is queried
6032 */
6033 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306034 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306035 } else if (out->prev_card_status_offline) {
6036 ALOGE("ERROR: previously sound card was offline,return error");
6037 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306038 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306039 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006040 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306041 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306042 pthread_mutex_unlock(&out->lock);
6043 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006044 } else if (audio_is_linear_pcm(out->format)) {
6045 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006046 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006047 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006048 } else
6049 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006050}
6051
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006052static int out_add_audio_effect(const struct audio_stream *stream __unused,
6053 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006054{
6055 return 0;
6056}
6057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006058static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6059 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006060{
6061 return 0;
6062}
6063
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006064static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6065 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306067 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006068}
6069
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006070static int out_get_presentation_position(const struct audio_stream_out *stream,
6071 uint64_t *frames, struct timespec *timestamp)
6072{
6073 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306074 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006075 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006076
Ashish Jain5106d362016-05-11 19:23:33 +05306077 /* below piece of code is not guarded against any lock because audioFliner serializes
6078 * this operation and adev_close_output_stream( where out gets reset).
6079 */
6080 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306081 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006082 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306083 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6084 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6085 return 0;
6086 }
6087
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006088 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006089
Ashish Jain5106d362016-05-11 19:23:33 +05306090 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6091 ret = compress_get_tstamp(out->compr, &dsp_frames,
6092 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006093 // Adjustment accounts for A2dp encoder latency with offload usecases
6094 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006095 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006096 unsigned long offset =
6097 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6098 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6099 }
Ashish Jain5106d362016-05-11 19:23:33 +05306100 ALOGVV("%s rendered frames %ld sample_rate %d",
6101 __func__, dsp_frames, out->sample_rate);
6102 *frames = dsp_frames;
6103 if (ret < 0)
6104 ret = -errno;
6105 if (-ENETRESET == ret) {
6106 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306107 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306108 ret = -EINVAL;
6109 } else
6110 ret = 0;
6111 /* this is the best we can do */
6112 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006113 } else {
6114 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006115 unsigned int avail;
6116 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6117 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006118
6119 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006120 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006121
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006122 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6123 if (out->written >= frames_temp)
6124 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006125
Weiyin Jiangd4633762018-03-16 12:05:03 +08006126 // This adjustment accounts for buffering after app processor.
6127 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006128 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6129 if (signed_frames >= frames_temp)
6130 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006131
Weiyin Jiangd4633762018-03-16 12:05:03 +08006132 // Adjustment accounts for A2dp encoder latency with non offload usecases
6133 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006134 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006135 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6136 if (signed_frames >= frames_temp)
6137 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006138 }
6139
6140 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006141 *frames = signed_frames;
6142 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006143 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306144 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306145 *frames = out->written;
6146 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306147 if (is_offload_usecase(out->usecase))
6148 ret = -EINVAL;
6149 else
6150 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006151 }
6152 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006153 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006154 return ret;
6155}
6156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006157static int out_set_callback(struct audio_stream_out *stream,
6158 stream_callback_t callback, void *cookie)
6159{
6160 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006161 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006162
6163 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006164 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006165 out->client_callback = callback;
6166 out->client_cookie = cookie;
6167 if (out->adsp_hdlr_stream_handle) {
6168 ret = audio_extn_adsp_hdlr_stream_set_callback(
6169 out->adsp_hdlr_stream_handle,
6170 callback,
6171 cookie);
6172 if (ret)
6173 ALOGW("%s:adsp hdlr callback registration failed %d",
6174 __func__, ret);
6175 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006176 pthread_mutex_unlock(&out->lock);
6177 return 0;
6178}
6179
6180static int out_pause(struct audio_stream_out* stream)
6181{
6182 struct stream_out *out = (struct stream_out *)stream;
6183 int status = -ENOSYS;
6184 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006185 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006186 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006187 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006188 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306189 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306190 status = compress_pause(out->compr);
6191
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006192 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006193
Mingming Yin21854652016-04-13 11:54:02 -07006194 if (audio_extn_passthru_is_active()) {
6195 ALOGV("offload use case, pause passthru");
6196 audio_extn_passthru_on_pause(out);
6197 }
6198
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306199 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006200 audio_extn_dts_notify_playback_state(out->usecase, 0,
6201 out->sample_rate, popcount(out->channel_mask),
6202 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006203 }
6204 pthread_mutex_unlock(&out->lock);
6205 }
6206 return status;
6207}
6208
6209static int out_resume(struct audio_stream_out* stream)
6210{
6211 struct stream_out *out = (struct stream_out *)stream;
6212 int status = -ENOSYS;
6213 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006214 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006215 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006216 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006217 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006218 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306219 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306220 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006221 }
6222 if (!status) {
6223 out->offload_state = OFFLOAD_STATE_PLAYING;
6224 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306225 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006226 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6227 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006228 }
6229 pthread_mutex_unlock(&out->lock);
6230 }
6231 return status;
6232}
6233
6234static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6235{
6236 struct stream_out *out = (struct stream_out *)stream;
6237 int status = -ENOSYS;
6238 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006239 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006240 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006241 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6242 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6243 else
6244 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6245 pthread_mutex_unlock(&out->lock);
6246 }
6247 return status;
6248}
6249
6250static int out_flush(struct audio_stream_out* stream)
6251{
6252 struct stream_out *out = (struct stream_out *)stream;
6253 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006254 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006255 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006256 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006257 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6258 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006259 } else {
6260 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6261 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006262 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006263 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006264 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006265 return 0;
6266 }
6267 return -ENOSYS;
6268}
6269
Haynes Mathew George16081042017-05-31 17:16:49 -07006270static int out_stop(const struct audio_stream_out* stream)
6271{
6272 struct stream_out *out = (struct stream_out *)stream;
6273 struct audio_device *adev = out->dev;
6274 int ret = -ENOSYS;
6275
6276 ALOGV("%s", __func__);
6277 pthread_mutex_lock(&adev->lock);
6278 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6279 out->playback_started && out->pcm != NULL) {
6280 pcm_stop(out->pcm);
6281 ret = stop_output_stream(out);
6282 out->playback_started = false;
6283 }
6284 pthread_mutex_unlock(&adev->lock);
6285 return ret;
6286}
6287
6288static int out_start(const struct audio_stream_out* stream)
6289{
6290 struct stream_out *out = (struct stream_out *)stream;
6291 struct audio_device *adev = out->dev;
6292 int ret = -ENOSYS;
6293
6294 ALOGV("%s", __func__);
6295 pthread_mutex_lock(&adev->lock);
6296 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6297 !out->playback_started && out->pcm != NULL) {
6298 ret = start_output_stream(out);
6299 if (ret == 0) {
6300 out->playback_started = true;
6301 }
6302 }
6303 pthread_mutex_unlock(&adev->lock);
6304 return ret;
6305}
6306
6307/*
6308 * Modify config->period_count based on min_size_frames
6309 */
6310static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6311{
6312 int periodCountRequested = (min_size_frames + config->period_size - 1)
6313 / config->period_size;
6314 int periodCount = MMAP_PERIOD_COUNT_MIN;
6315
6316 ALOGV("%s original config.period_size = %d config.period_count = %d",
6317 __func__, config->period_size, config->period_count);
6318
6319 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6320 periodCount *= 2;
6321 }
6322 config->period_count = periodCount;
6323
6324 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6325}
6326
Phil Burkfe17efd2019-03-25 10:23:35 -07006327// Read offset for the positional timestamp from a persistent vendor property.
6328// This is to workaround apparent inaccuracies in the timing information that
6329// is used by the AAudio timing model. The inaccuracies can cause glitches.
6330static int64_t get_mmap_out_time_offset() {
6331 const int32_t kDefaultOffsetMicros = 0;
6332 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006333 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006334 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6335 return mmap_time_offset_micros * (int64_t)1000;
6336}
6337
Haynes Mathew George16081042017-05-31 17:16:49 -07006338static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6339 int32_t min_size_frames,
6340 struct audio_mmap_buffer_info *info)
6341{
6342 struct stream_out *out = (struct stream_out *)stream;
6343 struct audio_device *adev = out->dev;
6344 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006345 unsigned int offset1 = 0;
6346 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006347 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006348 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006349 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006350
Arun Mirpuri5d170872019-03-26 13:21:31 -07006351 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306352 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006353 pthread_mutex_lock(&adev->lock);
6354
Sharad Sanglec6f32552018-05-04 16:15:38 +05306355 if (CARD_STATUS_OFFLINE == out->card_status ||
6356 CARD_STATUS_OFFLINE == adev->card_status) {
6357 ALOGW("out->card_status or adev->card_status offline, try again");
6358 ret = -EIO;
6359 goto exit;
6360 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006361 if (info == NULL || min_size_frames == 0) {
6362 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6363 ret = -EINVAL;
6364 goto exit;
6365 }
6366 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6367 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6368 ret = -ENOSYS;
6369 goto exit;
6370 }
6371 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6372 if (out->pcm_device_id < 0) {
6373 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6374 __func__, out->pcm_device_id, out->usecase);
6375 ret = -EINVAL;
6376 goto exit;
6377 }
6378
6379 adjust_mmap_period_count(&out->config, min_size_frames);
6380
Arun Mirpuri5d170872019-03-26 13:21:31 -07006381 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006382 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6383 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6384 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306385 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306386 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6387 out->card_status = CARD_STATUS_OFFLINE;
6388 adev->card_status = CARD_STATUS_OFFLINE;
6389 ret = -EIO;
6390 goto exit;
6391 }
6392
Haynes Mathew George16081042017-05-31 17:16:49 -07006393 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6394 step = "open";
6395 ret = -ENODEV;
6396 goto exit;
6397 }
6398 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6399 if (ret < 0) {
6400 step = "begin";
6401 goto exit;
6402 }
6403 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006404 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006405 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006406 ret = platform_get_mmap_data_fd(adev->platform,
6407 out->pcm_device_id, 0 /*playback*/,
6408 &info->shared_memory_fd,
6409 &mmap_size);
6410 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006411 // Fall back to non exclusive mode
6412 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6413 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006414 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6415 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6416
Arun Mirpuri5d170872019-03-26 13:21:31 -07006417 if (mmap_size < buffer_size) {
6418 step = "mmap";
6419 goto exit;
6420 }
6421 // FIXME: indicate exclusive mode support by returning a negative buffer size
6422 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006423 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006424 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006425 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006426
6427 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6428 if (ret < 0) {
6429 step = "commit";
6430 goto exit;
6431 }
6432
Phil Burkfe17efd2019-03-25 10:23:35 -07006433 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6434
Haynes Mathew George16081042017-05-31 17:16:49 -07006435 out->standby = false;
6436 ret = 0;
6437
Arun Mirpuri5d170872019-03-26 13:21:31 -07006438 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006439 __func__, info->shared_memory_address, info->buffer_size_frames);
6440
6441exit:
6442 if (ret != 0) {
6443 if (out->pcm == NULL) {
6444 ALOGE("%s: %s - %d", __func__, step, ret);
6445 } else {
6446 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6447 pcm_close(out->pcm);
6448 out->pcm = NULL;
6449 }
6450 }
6451 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306452 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006453 return ret;
6454}
6455
6456static int out_get_mmap_position(const struct audio_stream_out *stream,
6457 struct audio_mmap_position *position)
6458{
6459 struct stream_out *out = (struct stream_out *)stream;
6460 ALOGVV("%s", __func__);
6461 if (position == NULL) {
6462 return -EINVAL;
6463 }
6464 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006465 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006466 return -ENOSYS;
6467 }
6468 if (out->pcm == NULL) {
6469 return -ENOSYS;
6470 }
6471
6472 struct timespec ts = { 0, 0 };
6473 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6474 if (ret < 0) {
6475 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6476 return ret;
6477 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006478 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6479 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006480 return 0;
6481}
6482
6483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006484/** audio_stream_in implementation **/
6485static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6486{
6487 struct stream_in *in = (struct stream_in *)stream;
6488
6489 return in->config.rate;
6490}
6491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006492static int in_set_sample_rate(struct audio_stream *stream __unused,
6493 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006494{
6495 return -ENOSYS;
6496}
6497
6498static size_t in_get_buffer_size(const struct audio_stream *stream)
6499{
6500 struct stream_in *in = (struct stream_in *)stream;
6501
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006502 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6503 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006504 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6505 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306506 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306507 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006508
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006509 return in->config.period_size * in->af_period_multiplier *
6510 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006511}
6512
6513static uint32_t in_get_channels(const struct audio_stream *stream)
6514{
6515 struct stream_in *in = (struct stream_in *)stream;
6516
6517 return in->channel_mask;
6518}
6519
6520static audio_format_t in_get_format(const struct audio_stream *stream)
6521{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006522 struct stream_in *in = (struct stream_in *)stream;
6523
6524 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006525}
6526
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006527static int in_set_format(struct audio_stream *stream __unused,
6528 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006529{
6530 return -ENOSYS;
6531}
6532
6533static int in_standby(struct audio_stream *stream)
6534{
6535 struct stream_in *in = (struct stream_in *)stream;
6536 struct audio_device *adev = in->dev;
6537 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306538 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6539 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006540 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306541
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006542 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006543 if (!in->standby && in->is_st_session) {
6544 ALOGD("%s: sound trigger pcm stop lab", __func__);
6545 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006546 if (adev->num_va_sessions > 0)
6547 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006548 in->standby = 1;
6549 }
6550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006551 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006552 if (adev->adm_deregister_stream)
6553 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6554
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006555 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006556 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006557 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006558 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006559 voice_extn_compress_voip_close_input_stream(stream);
6560 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006561 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6562 do_stop = in->capture_started;
6563 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006564 if (in->mmap_shared_memory_fd >= 0) {
6565 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6566 __func__, in->mmap_shared_memory_fd);
6567 close(in->mmap_shared_memory_fd);
6568 in->mmap_shared_memory_fd = -1;
6569 }
Zhou Songa8895042016-07-05 17:54:22 +08006570 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306571 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306572 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006573 }
6574
Arun Mirpuri5d170872019-03-26 13:21:31 -07006575 if (in->pcm) {
6576 ATRACE_BEGIN("pcm_in_close");
6577 pcm_close(in->pcm);
6578 ATRACE_END();
6579 in->pcm = NULL;
6580 }
6581
Carter Hsu2e429db2019-05-14 18:50:52 +08006582 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006583 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006584
George Gao3018ede2019-10-23 13:23:00 -07006585 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6586 if (adev->num_va_sessions > 0)
6587 adev->num_va_sessions--;
6588 }
Quinn Malef6050362019-01-30 15:55:40 -08006589
Eric Laurent150dbfe2013-02-27 14:31:02 -08006590 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591 }
6592 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006593 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006594 return status;
6595}
6596
Aalique Grahame22e49102018-12-18 14:23:57 -08006597static int in_dump(const struct audio_stream *stream,
6598 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006599{
Aalique Grahame22e49102018-12-18 14:23:57 -08006600 struct stream_in *in = (struct stream_in *)stream;
6601
6602 // We try to get the lock for consistency,
6603 // but it isn't necessary for these variables.
6604 // If we're not in standby, we may be blocked on a read.
6605 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6606 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6607 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6608 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6609
6610 if (locked) {
6611 pthread_mutex_unlock(&in->lock);
6612 }
6613
6614 // dump error info
6615 (void)error_log_dump(
6616 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618 return 0;
6619}
6620
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306621static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6622{
6623 if (!stream || !parms)
6624 return;
6625
6626 struct stream_in *in = (struct stream_in *)stream;
6627 struct audio_device *adev = in->dev;
6628
6629 card_status_t status;
6630 int card;
6631 if (parse_snd_card_status(parms, &card, &status) < 0)
6632 return;
6633
6634 pthread_mutex_lock(&adev->lock);
6635 bool valid_cb = (card == adev->snd_card);
6636 pthread_mutex_unlock(&adev->lock);
6637
6638 if (!valid_cb)
6639 return;
6640
6641 lock_input_stream(in);
6642 if (in->card_status != status)
6643 in->card_status = status;
6644 pthread_mutex_unlock(&in->lock);
6645
6646 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6647 use_case_table[in->usecase],
6648 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6649
6650 // a better solution would be to report error back to AF and let
6651 // it put the stream to standby
6652 if (status == CARD_STATUS_OFFLINE)
6653 in_standby(&in->stream.common);
6654
6655 return;
6656}
6657
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006658int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006659 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006660 audio_source_t source)
6661{
6662 struct audio_device *adev = in->dev;
6663 int ret = 0;
6664
6665 lock_input_stream(in);
6666 pthread_mutex_lock(&adev->lock);
6667
6668 /* no audio source uses val == 0 */
6669 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6670 in->source = source;
6671 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6672 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6673 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6674 (in->config.rate == 8000 || in->config.rate == 16000 ||
6675 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6676 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6677 ret = voice_extn_compress_voip_open_input_stream(in);
6678 if (ret != 0) {
6679 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6680 __func__, ret);
6681 }
6682 }
6683 }
6684
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006685 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6686 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006687 // Workaround: If routing to an non existing usb device, fail gracefully
6688 // The routing request will otherwise block during 10 second
6689 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006690 struct str_parms *usb_addr =
6691 str_parms_create_str(get_usb_device_address(devices));
6692 if (is_usb_in_device_type(devices) && usb_addr &&
6693 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006694 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6695 ret = -ENOSYS;
6696 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006697 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006698 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006699 if (!in->standby && !in->is_st_session) {
6700 ALOGV("update input routing change");
6701 // inform adm before actual routing to prevent glitches.
6702 if (adev->adm_on_routing_change) {
6703 adev->adm_on_routing_change(adev->adm_data,
6704 in->capture_handle);
6705 ret = select_devices(adev, in->usecase);
6706 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6707 adev->adm_routing_changed = true;
6708 }
6709 }
6710 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006711 if (usb_addr)
6712 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006713 }
6714 pthread_mutex_unlock(&adev->lock);
6715 pthread_mutex_unlock(&in->lock);
6716
6717 ALOGD("%s: exit: status(%d)", __func__, ret);
6718 return ret;
6719}
6720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6722{
6723 struct stream_in *in = (struct stream_in *)stream;
6724 struct audio_device *adev = in->dev;
6725 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006726 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006727 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306729 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006730 parms = str_parms_create_str(kvpairs);
6731
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306732 if (!parms)
6733 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006734 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006735 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006736
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006737 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6738 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306739 strlcpy(in->profile, value, sizeof(in->profile));
6740 ALOGV("updating stream profile with value '%s'", in->profile);
6741 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6742 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006743 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306744 in->sample_rate, in->bit_width,
6745 in->profile, &in->app_type_cfg);
6746 }
6747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006748 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006749 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006750
6751 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306752error:
Eric Laurent994a6932013-07-17 11:51:42 -07006753 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006754 return ret;
6755}
6756
6757static char* in_get_parameters(const struct audio_stream *stream,
6758 const char *keys)
6759{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006760 struct stream_in *in = (struct stream_in *)stream;
6761 struct str_parms *query = str_parms_create_str(keys);
6762 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006763 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006764
6765 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006766 if (reply) {
6767 str_parms_destroy(reply);
6768 }
6769 if (query) {
6770 str_parms_destroy(query);
6771 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006772 ALOGE("in_get_parameters: failed to create query or reply");
6773 return NULL;
6774 }
6775
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006776 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006777
6778 voice_extn_in_get_parameters(in, query, reply);
6779
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006780 stream_get_parameter_channels(query, reply,
6781 &in->supported_channel_masks[0]);
6782 stream_get_parameter_formats(query, reply,
6783 &in->supported_formats[0]);
6784 stream_get_parameter_rates(query, reply,
6785 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006786 str = str_parms_to_str(reply);
6787 str_parms_destroy(query);
6788 str_parms_destroy(reply);
6789
6790 ALOGV("%s: exit: returns - %s", __func__, str);
6791 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006792}
6793
Aalique Grahame22e49102018-12-18 14:23:57 -08006794static int in_set_gain(struct audio_stream_in *stream,
6795 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796{
Aalique Grahame22e49102018-12-18 14:23:57 -08006797 struct stream_in *in = (struct stream_in *)stream;
6798 char mixer_ctl_name[128];
6799 struct mixer_ctl *ctl;
6800 int ctl_value;
6801
6802 ALOGV("%s: gain %f", __func__, gain);
6803
6804 if (stream == NULL)
6805 return -EINVAL;
6806
6807 /* in_set_gain() only used to silence MMAP capture for now */
6808 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6809 return -ENOSYS;
6810
6811 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6812
6813 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6814 if (!ctl) {
6815 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6816 __func__, mixer_ctl_name);
6817 return -ENOSYS;
6818 }
6819
6820 if (gain < RECORD_GAIN_MIN)
6821 gain = RECORD_GAIN_MIN;
6822 else if (gain > RECORD_GAIN_MAX)
6823 gain = RECORD_GAIN_MAX;
6824 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6825
6826 mixer_ctl_set_value(ctl, 0, ctl_value);
6827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006828 return 0;
6829}
6830
6831static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6832 size_t bytes)
6833{
6834 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306835
6836 if (in == NULL) {
6837 ALOGE("%s: stream_in ptr is NULL", __func__);
6838 return -EINVAL;
6839 }
6840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006841 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306842 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306843 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006845 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306846
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006847 if (in->is_st_session) {
6848 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6849 /* Read from sound trigger HAL */
6850 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006851 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006852 if (adev->num_va_sessions < UINT_MAX)
6853 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006854 in->standby = 0;
6855 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006856 pthread_mutex_unlock(&in->lock);
6857 return bytes;
6858 }
6859
Haynes Mathew George16081042017-05-31 17:16:49 -07006860 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6861 ret = -ENOSYS;
6862 goto exit;
6863 }
6864
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006865 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6866 !in->standby && adev->adm_routing_changed) {
6867 ret = -ENOSYS;
6868 goto exit;
6869 }
6870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006871 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006872 pthread_mutex_lock(&adev->lock);
6873 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6874 ret = voice_extn_compress_voip_start_input_stream(in);
6875 else
6876 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006877 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6878 if (adev->num_va_sessions < UINT_MAX)
6879 adev->num_va_sessions++;
6880 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006881 pthread_mutex_unlock(&adev->lock);
6882 if (ret != 0) {
6883 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006884 }
6885 in->standby = 0;
6886 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006887
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306888 /* Avoid read if capture_stopped is set */
6889 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6890 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6891 ret = -EINVAL;
6892 goto exit;
6893 }
6894
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006895 // what's the duration requested by the client?
6896 long ns = 0;
6897
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306898 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006899 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6900 in->config.rate;
6901
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006902 ret = request_in_focus(in, ns);
6903 if (ret != 0)
6904 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006905 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006906
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306907 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306908 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6909 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306910 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006911 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306912 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006913 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006914 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006915 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006916 } else if (audio_extn_ffv_get_stream() == in) {
6917 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306918 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006919 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306920 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6921 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6922 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6923 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306924 ret = -EINVAL;
6925 goto exit;
6926 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306927 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306928 ret = -errno;
6929 }
6930 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306931 /* bytes read is always set to bytes for non compress usecases */
6932 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006933 }
6934
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006935 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006937 /*
Quinn Malef6050362019-01-30 15:55:40 -08006938 * Instead of writing zeroes here, we could trust the hardware to always
6939 * provide zeroes when muted. This is also muted with voice recognition
6940 * usecases so that other clients do not have access to voice recognition
6941 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006942 */
Quinn Malef6050362019-01-30 15:55:40 -08006943 if ((ret == 0 && voice_get_mic_mute(adev) &&
6944 !voice_is_in_call_rec_stream(in) &&
6945 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6946 (adev->num_va_sessions &&
6947 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6948 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6949 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006950 memset(buffer, 0, bytes);
6951
6952exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306953 frame_size = audio_stream_in_frame_size(stream);
6954 if (frame_size > 0)
6955 in->frames_read += bytes_read/frame_size;
6956
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006957 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306958 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006959 pthread_mutex_unlock(&in->lock);
6960
6961 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306962 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306963 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306964 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306965 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306966 in->standby = true;
6967 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306968 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05306969 bytes_read = bytes;
6970 memset(buffer, 0, bytes);
6971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006972 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006973 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6974 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006975 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306976 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306977 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006978 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306979 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980}
6981
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006982static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006983{
6984 return 0;
6985}
6986
Aalique Grahame22e49102018-12-18 14:23:57 -08006987static int in_get_capture_position(const struct audio_stream_in *stream,
6988 int64_t *frames, int64_t *time)
6989{
6990 if (stream == NULL || frames == NULL || time == NULL) {
6991 return -EINVAL;
6992 }
6993 struct stream_in *in = (struct stream_in *)stream;
6994 int ret = -ENOSYS;
6995
6996 lock_input_stream(in);
6997 // note: ST sessions do not close the alsa pcm driver synchronously
6998 // on standby. Therefore, we may return an error even though the
6999 // pcm stream is still opened.
7000 if (in->standby) {
7001 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7002 "%s stream in standby but pcm not NULL for non ST session", __func__);
7003 goto exit;
7004 }
7005 if (in->pcm) {
7006 struct timespec timestamp;
7007 unsigned int avail;
7008 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7009 *frames = in->frames_read + avail;
7010 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7011 ret = 0;
7012 }
7013 }
7014exit:
7015 pthread_mutex_unlock(&in->lock);
7016 return ret;
7017}
7018
Carter Hsu2e429db2019-05-14 18:50:52 +08007019static int in_update_effect_list(bool add, effect_handle_t effect,
7020 struct listnode *head)
7021{
7022 struct listnode *node;
7023 struct in_effect_list *elist = NULL;
7024 struct in_effect_list *target = NULL;
7025 int ret = 0;
7026
7027 if (!head)
7028 return ret;
7029
7030 list_for_each(node, head) {
7031 elist = node_to_item(node, struct in_effect_list, list);
7032 if (elist->handle == effect) {
7033 target = elist;
7034 break;
7035 }
7036 }
7037
7038 if (add) {
7039 if (target) {
7040 ALOGD("effect %p already exist", effect);
7041 return ret;
7042 }
7043
7044 target = (struct in_effect_list *)
7045 calloc(1, sizeof(struct in_effect_list));
7046
7047 if (!target) {
7048 ALOGE("%s:fail to allocate memory", __func__);
7049 return -ENOMEM;
7050 }
7051
7052 target->handle = effect;
7053 list_add_tail(head, &target->list);
7054 } else {
7055 if (target) {
7056 list_remove(&target->list);
7057 free(target);
7058 }
7059 }
7060
7061 return ret;
7062}
7063
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007064static int add_remove_audio_effect(const struct audio_stream *stream,
7065 effect_handle_t effect,
7066 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007067{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007068 struct stream_in *in = (struct stream_in *)stream;
7069 int status = 0;
7070 effect_descriptor_t desc;
7071
7072 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007073 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7074
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007075 if (status != 0)
7076 return status;
7077
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007078 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007079 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007080 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007081 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7082 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007083 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007084
7085 in_update_effect_list(enable, effect, &in->aec_list);
7086 enable = !list_empty(&in->aec_list);
7087 if (enable == in->enable_aec)
7088 goto exit;
7089
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007090 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007091 ALOGD("AEC enable %d", enable);
7092
Aalique Grahame22e49102018-12-18 14:23:57 -08007093 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7094 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7095 in->dev->enable_voicerx = enable;
7096 struct audio_usecase *usecase;
7097 struct listnode *node;
7098 list_for_each(node, &in->dev->usecase_list) {
7099 usecase = node_to_item(node, struct audio_usecase, list);
7100 if (usecase->type == PCM_PLAYBACK)
7101 select_devices(in->dev, usecase->id);
7102 }
7103 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007104 if (!in->standby) {
7105 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7106 select_devices(in->dev, in->usecase);
7107 }
7108
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007109 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007110 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7111
7112 in_update_effect_list(enable, effect, &in->ns_list);
7113 enable = !list_empty(&in->ns_list);
7114 if (enable == in->enable_ns)
7115 goto exit;
7116
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007117 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007118 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007119 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007120 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7121 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007122 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7123 select_devices(in->dev, in->usecase);
7124 } else
7125 select_devices(in->dev, in->usecase);
7126 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007127 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007128exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007129 pthread_mutex_unlock(&in->dev->lock);
7130 pthread_mutex_unlock(&in->lock);
7131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007132 return 0;
7133}
7134
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007135static int in_add_audio_effect(const struct audio_stream *stream,
7136 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007137{
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, true);
7140}
7141
7142static int in_remove_audio_effect(const struct audio_stream *stream,
7143 effect_handle_t effect)
7144{
Eric Laurent994a6932013-07-17 11:51:42 -07007145 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007146 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147}
7148
Derek Chenf939fb72018-11-13 13:34:41 -08007149streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7150 audio_io_handle_t input)
7151{
7152 struct listnode *node;
7153
7154 list_for_each(node, &dev->active_inputs_list) {
7155 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7156 streams_input_ctxt_t,
7157 list);
7158 if (in_ctxt->input->capture_handle == input) {
7159 return in_ctxt;
7160 }
7161 }
7162 return NULL;
7163}
7164
7165streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7166 audio_io_handle_t output)
7167{
7168 struct listnode *node;
7169
7170 list_for_each(node, &dev->active_outputs_list) {
7171 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7172 streams_output_ctxt_t,
7173 list);
7174 if (out_ctxt->output->handle == output) {
7175 return out_ctxt;
7176 }
7177 }
7178 return NULL;
7179}
7180
Haynes Mathew George16081042017-05-31 17:16:49 -07007181static int in_stop(const struct audio_stream_in* stream)
7182{
7183 struct stream_in *in = (struct stream_in *)stream;
7184 struct audio_device *adev = in->dev;
7185
7186 int ret = -ENOSYS;
7187 ALOGV("%s", __func__);
7188 pthread_mutex_lock(&adev->lock);
7189 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7190 in->capture_started && in->pcm != NULL) {
7191 pcm_stop(in->pcm);
7192 ret = stop_input_stream(in);
7193 in->capture_started = false;
7194 }
7195 pthread_mutex_unlock(&adev->lock);
7196 return ret;
7197}
7198
7199static int in_start(const struct audio_stream_in* stream)
7200{
7201 struct stream_in *in = (struct stream_in *)stream;
7202 struct audio_device *adev = in->dev;
7203 int ret = -ENOSYS;
7204
7205 ALOGV("%s in %p", __func__, in);
7206 pthread_mutex_lock(&adev->lock);
7207 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7208 !in->capture_started && in->pcm != NULL) {
7209 if (!in->capture_started) {
7210 ret = start_input_stream(in);
7211 if (ret == 0) {
7212 in->capture_started = true;
7213 }
7214 }
7215 }
7216 pthread_mutex_unlock(&adev->lock);
7217 return ret;
7218}
7219
Phil Burke0a86d12019-02-16 22:28:11 -08007220// Read offset for the positional timestamp from a persistent vendor property.
7221// This is to workaround apparent inaccuracies in the timing information that
7222// is used by the AAudio timing model. The inaccuracies can cause glitches.
7223static int64_t in_get_mmap_time_offset() {
7224 const int32_t kDefaultOffsetMicros = 0;
7225 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007226 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007227 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7228 return mmap_time_offset_micros * (int64_t)1000;
7229}
7230
Haynes Mathew George16081042017-05-31 17:16:49 -07007231static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7232 int32_t min_size_frames,
7233 struct audio_mmap_buffer_info *info)
7234{
7235 struct stream_in *in = (struct stream_in *)stream;
7236 struct audio_device *adev = in->dev;
7237 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007238 unsigned int offset1 = 0;
7239 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007240 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007241 uint32_t mmap_size = 0;
7242 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007243
7244 pthread_mutex_lock(&adev->lock);
7245 ALOGV("%s in %p", __func__, in);
7246
Sharad Sanglec6f32552018-05-04 16:15:38 +05307247 if (CARD_STATUS_OFFLINE == in->card_status||
7248 CARD_STATUS_OFFLINE == adev->card_status) {
7249 ALOGW("in->card_status or adev->card_status offline, try again");
7250 ret = -EIO;
7251 goto exit;
7252 }
7253
Haynes Mathew George16081042017-05-31 17:16:49 -07007254 if (info == NULL || min_size_frames == 0) {
7255 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7256 ret = -EINVAL;
7257 goto exit;
7258 }
7259 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7260 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7261 ALOGV("%s in %p", __func__, in);
7262 ret = -ENOSYS;
7263 goto exit;
7264 }
7265 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7266 if (in->pcm_device_id < 0) {
7267 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7268 __func__, in->pcm_device_id, in->usecase);
7269 ret = -EINVAL;
7270 goto exit;
7271 }
7272
7273 adjust_mmap_period_count(&in->config, min_size_frames);
7274
7275 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7276 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7277 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7278 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307279 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307280 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7281 in->card_status = CARD_STATUS_OFFLINE;
7282 adev->card_status = CARD_STATUS_OFFLINE;
7283 ret = -EIO;
7284 goto exit;
7285 }
7286
Haynes Mathew George16081042017-05-31 17:16:49 -07007287 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7288 step = "open";
7289 ret = -ENODEV;
7290 goto exit;
7291 }
7292
7293 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7294 if (ret < 0) {
7295 step = "begin";
7296 goto exit;
7297 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007298
Arun Mirpuri5d170872019-03-26 13:21:31 -07007299 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7300 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7301 info->burst_size_frames = in->config.period_size;
7302 ret = platform_get_mmap_data_fd(adev->platform,
7303 in->pcm_device_id, 1 /*capture*/,
7304 &info->shared_memory_fd,
7305 &mmap_size);
7306 if (ret < 0) {
7307 // Fall back to non exclusive mode
7308 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7309 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007310 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7311 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7312
Arun Mirpuri5d170872019-03-26 13:21:31 -07007313 if (mmap_size < buffer_size) {
7314 step = "mmap";
7315 goto exit;
7316 }
7317 // FIXME: indicate exclusive mode support by returning a negative buffer size
7318 info->buffer_size_frames *= -1;
7319 }
7320
7321 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007322
7323 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7324 if (ret < 0) {
7325 step = "commit";
7326 goto exit;
7327 }
7328
Phil Burke0a86d12019-02-16 22:28:11 -08007329 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7330
Haynes Mathew George16081042017-05-31 17:16:49 -07007331 in->standby = false;
7332 ret = 0;
7333
7334 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7335 __func__, info->shared_memory_address, info->buffer_size_frames);
7336
7337exit:
7338 if (ret != 0) {
7339 if (in->pcm == NULL) {
7340 ALOGE("%s: %s - %d", __func__, step, ret);
7341 } else {
7342 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7343 pcm_close(in->pcm);
7344 in->pcm = NULL;
7345 }
7346 }
7347 pthread_mutex_unlock(&adev->lock);
7348 return ret;
7349}
7350
7351static int in_get_mmap_position(const struct audio_stream_in *stream,
7352 struct audio_mmap_position *position)
7353{
7354 struct stream_in *in = (struct stream_in *)stream;
7355 ALOGVV("%s", __func__);
7356 if (position == NULL) {
7357 return -EINVAL;
7358 }
7359 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7360 return -ENOSYS;
7361 }
7362 if (in->pcm == NULL) {
7363 return -ENOSYS;
7364 }
7365 struct timespec ts = { 0, 0 };
7366 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7367 if (ret < 0) {
7368 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7369 return ret;
7370 }
Phil Burke0a86d12019-02-16 22:28:11 -08007371 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7372 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007373 return 0;
7374}
7375
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307376static int in_get_active_microphones(const struct audio_stream_in *stream,
7377 struct audio_microphone_characteristic_t *mic_array,
7378 size_t *mic_count) {
7379 struct stream_in *in = (struct stream_in *)stream;
7380 struct audio_device *adev = in->dev;
7381 ALOGVV("%s", __func__);
7382
7383 lock_input_stream(in);
7384 pthread_mutex_lock(&adev->lock);
7385 int ret = platform_get_active_microphones(adev->platform,
7386 audio_channel_count_from_in_mask(in->channel_mask),
7387 in->usecase, mic_array, mic_count);
7388 pthread_mutex_unlock(&adev->lock);
7389 pthread_mutex_unlock(&in->lock);
7390
7391 return ret;
7392}
7393
7394static int adev_get_microphones(const struct audio_hw_device *dev,
7395 struct audio_microphone_characteristic_t *mic_array,
7396 size_t *mic_count) {
7397 struct audio_device *adev = (struct audio_device *)dev;
7398 ALOGVV("%s", __func__);
7399
7400 pthread_mutex_lock(&adev->lock);
7401 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7402 pthread_mutex_unlock(&adev->lock);
7403
7404 return ret;
7405}
juyuchendb308c22019-01-21 11:57:17 -07007406
7407static void in_update_sink_metadata(struct audio_stream_in *stream,
7408 const struct sink_metadata *sink_metadata) {
7409
7410 if (stream == NULL
7411 || sink_metadata == NULL
7412 || sink_metadata->tracks == NULL) {
7413 return;
7414 }
7415
7416 int error = 0;
7417 struct stream_in *in = (struct stream_in *)stream;
7418 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007419 struct listnode devices;
7420
7421 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007422
7423 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007424 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007425
7426 lock_input_stream(in);
7427 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007428 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007429
7430 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007431 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007432 && adev->voice_tx_output != NULL) {
7433 /* Use the rx device from afe-proxy record to route voice call because
7434 there is no routing if tx device is on primary hal and rx device
7435 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007436 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007437
7438 if (!voice_is_call_state_active(adev)) {
7439 if (adev->mode == AUDIO_MODE_IN_CALL) {
7440 adev->current_call_output = adev->voice_tx_output;
7441 error = voice_start_call(adev);
7442 if (error != 0)
7443 ALOGE("%s: start voice call failed %d", __func__, error);
7444 }
7445 } else {
7446 adev->current_call_output = adev->voice_tx_output;
7447 voice_update_devices_for_all_voice_usecases(adev);
7448 }
7449 }
7450
7451 pthread_mutex_unlock(&adev->lock);
7452 pthread_mutex_unlock(&in->lock);
7453}
7454
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307455int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007456 audio_io_handle_t handle,
7457 audio_devices_t devices,
7458 audio_output_flags_t flags,
7459 struct audio_config *config,
7460 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007461 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007462{
7463 struct audio_device *adev = (struct audio_device *)dev;
7464 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307465 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007466 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007467 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307468 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007469 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7470 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7471 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7472 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007473 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007474 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7475 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007476 bool force_haptic_path =
7477 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007478 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007479
kunleizdff872d2018-08-20 14:40:33 +08007480 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007481 is_usb_dev = false;
7482 devices = AUDIO_DEVICE_OUT_SPEAKER;
7483 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7484 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007485 if (config->format == AUDIO_FORMAT_DEFAULT)
7486 config->format = AUDIO_FORMAT_PCM_16_BIT;
7487 if (config->sample_rate == 0)
7488 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7489 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7490 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007491 }
7492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007493 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307494
Rahul Sharma99770982019-03-06 17:05:26 +05307495 pthread_mutex_lock(&adev->lock);
7496 if (out_get_stream(adev, handle) != NULL) {
7497 ALOGW("%s, output stream already opened", __func__);
7498 ret = -EEXIST;
7499 }
7500 pthread_mutex_unlock(&adev->lock);
7501 if (ret)
7502 return ret;
7503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007504 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7505
Mingming Yin3a941d42016-02-17 18:08:05 -08007506 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007507 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7508 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307509
7510
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007511 if (!out) {
7512 return -ENOMEM;
7513 }
7514
Haynes Mathew George204045b2015-02-25 20:32:03 -08007515 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007516 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307517 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007518 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007519 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007521 if (devices == AUDIO_DEVICE_NONE)
7522 devices = AUDIO_DEVICE_OUT_SPEAKER;
7523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007524 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007525 list_init(&out->device_list);
7526 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007527 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007528 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007529 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307530 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307531 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7532 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7533 else
7534 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007535 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007536 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007537 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307538 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307539 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307540 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007541 out->hal_output_suspend_supported = 0;
7542 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307543 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307544 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307545 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007546 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007547
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307548 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307549 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007550 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7551
Aalique Grahame22e49102018-12-18 14:23:57 -08007552 if (direct_dev &&
7553 (audio_is_linear_pcm(out->format) ||
7554 config->format == AUDIO_FORMAT_DEFAULT) &&
7555 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7556 audio_format_t req_format = config->format;
7557 audio_channel_mask_t req_channel_mask = config->channel_mask;
7558 uint32_t req_sample_rate = config->sample_rate;
7559
7560 pthread_mutex_lock(&adev->lock);
7561 if (is_hdmi) {
7562 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7563 ret = read_hdmi_sink_caps(out);
7564 if (config->sample_rate == 0)
7565 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7566 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7567 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7568 if (config->format == AUDIO_FORMAT_DEFAULT)
7569 config->format = AUDIO_FORMAT_PCM_16_BIT;
7570 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007571 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7572 &config->format,
7573 &out->supported_formats[0],
7574 MAX_SUPPORTED_FORMATS,
7575 &config->channel_mask,
7576 &out->supported_channel_masks[0],
7577 MAX_SUPPORTED_CHANNEL_MASKS,
7578 &config->sample_rate,
7579 &out->supported_sample_rates[0],
7580 MAX_SUPPORTED_SAMPLE_RATES);
7581 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007582 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007583
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007584 pthread_mutex_unlock(&adev->lock);
7585 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007586 if (ret == -ENOSYS) {
7587 /* ignore and go with default */
7588 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007589 }
7590 // For MMAP NO IRQ, allow conversions in ADSP
7591 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7592 goto error_open;
7593 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007594 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007595 goto error_open;
7596 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007597
7598 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7599 config->sample_rate = req_sample_rate;
7600 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7601 config->channel_mask = req_channel_mask;
7602 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7603 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007604 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007605
7606 out->sample_rate = config->sample_rate;
7607 out->channel_mask = config->channel_mask;
7608 out->format = config->format;
7609 if (is_hdmi) {
7610 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7611 out->config = pcm_config_hdmi_multi;
7612 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7613 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7614 out->config = pcm_config_mmap_playback;
7615 out->stream.start = out_start;
7616 out->stream.stop = out_stop;
7617 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7618 out->stream.get_mmap_position = out_get_mmap_position;
7619 } else {
7620 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7621 out->config = pcm_config_hifi;
7622 }
7623
7624 out->config.rate = out->sample_rate;
7625 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7626 if (is_hdmi) {
7627 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7628 audio_bytes_per_sample(out->format));
7629 }
7630 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007631 }
7632
Derek Chenf6318be2017-06-12 17:16:24 -04007633 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007634 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007635 /* extract car audio stream index */
7636 out->car_audio_stream =
7637 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7638 if (out->car_audio_stream < 0) {
7639 ALOGE("%s: invalid car audio stream %x",
7640 __func__, out->car_audio_stream);
7641 ret = -EINVAL;
7642 goto error_open;
7643 }
Derek Chen5f67a942020-02-24 23:08:13 -08007644 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007645 }
7646
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007647 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007648 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007649 if (!voice_extn_is_compress_voip_supported()) {
7650 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7651 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007652 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7653 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007654 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7655 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007656 out->volume_l = INVALID_OUT_VOLUME;
7657 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007658
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007659 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007660 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007661 uint32_t channel_count =
7662 audio_channel_count_from_out_mask(out->channel_mask);
7663 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7664 out->sample_rate, out->format,
7665 channel_count, false);
7666 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7667 if (frame_size != 0)
7668 out->config.period_size = buffer_size / frame_size;
7669 else
7670 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007671 }
7672 } else {
7673 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7674 voice_extn_compress_voip_is_active(out->dev)) &&
7675 (voice_extn_compress_voip_is_config_supported(config))) {
7676 ret = voice_extn_compress_voip_open_output_stream(out);
7677 if (ret != 0) {
7678 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7679 __func__, ret);
7680 goto error_open;
7681 }
Sujin Panicker19027262019-09-16 18:28:06 +05307682 } else {
7683 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7684 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007685 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007686 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007687 } else if (audio_is_linear_pcm(out->format) &&
7688 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7689 out->channel_mask = config->channel_mask;
7690 out->sample_rate = config->sample_rate;
7691 out->format = config->format;
7692 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7693 // does this change?
7694 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7695 out->config.rate = config->sample_rate;
7696 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7697 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7698 audio_bytes_per_sample(config->format));
7699 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007700 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307701 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307702 pthread_mutex_lock(&adev->lock);
7703 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7704 pthread_mutex_unlock(&adev->lock);
7705
7706 // reject offload during card offline to allow
7707 // fallback to s/w paths
7708 if (offline) {
7709 ret = -ENODEV;
7710 goto error_open;
7711 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007712
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007713 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7714 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7715 ALOGE("%s: Unsupported Offload information", __func__);
7716 ret = -EINVAL;
7717 goto error_open;
7718 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007719
Atul Khare3fa6e542017-08-09 00:56:17 +05307720 if (config->offload_info.format == 0)
7721 config->offload_info.format = config->format;
7722 if (config->offload_info.sample_rate == 0)
7723 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007724
Mingming Yin90310102013-11-13 16:57:00 -08007725 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307726 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007727 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007728 ret = -EINVAL;
7729 goto error_open;
7730 }
7731
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007732 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7733 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7734 (audio_extn_passthru_is_passthrough_stream(out)) &&
7735 !((config->sample_rate == 48000) ||
7736 (config->sample_rate == 96000) ||
7737 (config->sample_rate == 192000))) {
7738 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7739 __func__, config->sample_rate, config->offload_info.format);
7740 ret = -EINVAL;
7741 goto error_open;
7742 }
7743
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007744 out->compr_config.codec = (struct snd_codec *)
7745 calloc(1, sizeof(struct snd_codec));
7746
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007747 if (!out->compr_config.codec) {
7748 ret = -ENOMEM;
7749 goto error_open;
7750 }
7751
Dhananjay Kumarac341582017-02-23 23:42:25 +05307752 out->stream.pause = out_pause;
7753 out->stream.resume = out_resume;
7754 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307755 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307756 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007757 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307758 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007759 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307760 } else {
7761 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7762 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007763 }
vivek mehta446c3962015-09-14 10:57:35 -07007764
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307765 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7766 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007767#ifdef AUDIO_GKI_ENABLED
7768 /* out->compr_config.codec->reserved[1] is for flags */
7769 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7770#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307771 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007772#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307773 }
7774
vivek mehta446c3962015-09-14 10:57:35 -07007775 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007776 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007777 config->format == 0 && config->sample_rate == 0 &&
7778 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007779 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007780 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7781 } else {
7782 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7783 ret = -EEXIST;
7784 goto error_open;
7785 }
vivek mehta446c3962015-09-14 10:57:35 -07007786 }
7787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007788 if (config->offload_info.channel_mask)
7789 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007790 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007791 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007792 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007793 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307794 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007795 ret = -EINVAL;
7796 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007797 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007798
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007799 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007800 out->sample_rate = config->offload_info.sample_rate;
7801
Mingming Yin3ee55c62014-08-04 14:23:35 -07007802 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007803
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307804 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307805 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307806 audio_extn_dolby_send_ddp_endp_params(adev);
7807 audio_extn_dolby_set_dmid(adev);
7808 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007809
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007810 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007811 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007812 out->compr_config.codec->bit_rate =
7813 config->offload_info.bit_rate;
7814 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307815 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007816 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307817 /* Update bit width only for non passthrough usecases.
7818 * For passthrough usecases, the output will always be opened @16 bit
7819 */
7820 if (!audio_extn_passthru_is_passthrough_stream(out))
7821 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307822
7823 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007824#ifdef AUDIO_GKI_ENABLED
7825 /* out->compr_config.codec->reserved[1] is for flags */
7826 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7827 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7828#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307829 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7830 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007831#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307832
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007833 /*TODO: Do we need to change it for passthrough */
7834 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007835
Manish Dewangana6fc5442015-08-24 20:30:31 +05307836 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7837 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307838 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307839 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307840 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7841 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307842
7843 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7844 AUDIO_FORMAT_PCM) {
7845
7846 /*Based on platform support, configure appropriate alsa format for corresponding
7847 *hal input format.
7848 */
7849 out->compr_config.codec->format = hal_format_to_alsa(
7850 config->offload_info.format);
7851
Ashish Jain83a6cc22016-06-28 14:34:17 +05307852 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307853 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307854 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307855
Dhananjay Kumarac341582017-02-23 23:42:25 +05307856 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307857 *hal input format and alsa format might differ based on platform support.
7858 */
7859 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307860 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307861
7862 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7863
Deeraj Soman93155a62019-09-30 19:00:37 +05307864 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7865 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7866 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7867 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7868 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307869
Ashish Jainf1eaa582016-05-23 20:54:24 +05307870 /* Check if alsa session is configured with the same format as HAL input format,
7871 * if not then derive correct fragment size needed to accomodate the
7872 * conversion of HAL input format to alsa format.
7873 */
7874 audio_extn_utils_update_direct_pcm_fragment_size(out);
7875
7876 /*if hal input and output fragment size is different this indicates HAL input format is
7877 *not same as the alsa format
7878 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307879 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307880 /*Allocate a buffer to convert input data to the alsa configured format.
7881 *size of convert buffer is equal to the size required to hold one fragment size
7882 *worth of pcm data, this is because flinger does not write more than fragment_size
7883 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307884 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7885 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307886 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7887 ret = -ENOMEM;
7888 goto error_open;
7889 }
7890 }
7891 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7892 out->compr_config.fragment_size =
7893 audio_extn_passthru_get_buffer_size(&config->offload_info);
7894 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7895 } else {
7896 out->compr_config.fragment_size =
7897 platform_get_compress_offload_buffer_size(&config->offload_info);
7898 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7899 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007900
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307901 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7902 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7903 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007904 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307905 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007906
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307907 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7908 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7909 }
7910
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007911 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7912 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007913
Manish Dewangan69426c82017-01-30 17:35:36 +05307914 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7915 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7916 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7917 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7918 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7919 } else {
7920 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7921 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007922
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307923 memset(&out->channel_map_param, 0,
7924 sizeof(struct audio_out_channel_map_param));
7925
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007926 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307927 out->send_next_track_params = false;
7928 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007929 out->offload_state = OFFLOAD_STATE_IDLE;
7930 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007931 out->writeAt.tv_sec = 0;
7932 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007933
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007934 audio_extn_dts_create_state_notifier_node(out->usecase);
7935
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007936 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7937 __func__, config->offload_info.version,
7938 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307939
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307940 /* Check if DSD audio format is supported in codec
7941 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307942 */
7943
7944 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307945 (!platform_check_codec_dsd_support(adev->platform) ||
7946 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307947 ret = -EINVAL;
7948 goto error_open;
7949 }
7950
Ashish Jain5106d362016-05-11 19:23:33 +05307951 /* Disable gapless if any of the following is true
7952 * passthrough playback
7953 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307954 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307955 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307956 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307957 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007958 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307959 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307960 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307961 check_and_set_gapless_mode(adev, false);
7962 } else
7963 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007964
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307965 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007966 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7967 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307968 if (config->format == AUDIO_FORMAT_DSD) {
7969 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007970#ifdef AUDIO_GKI_ENABLED
7971 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7972 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7973#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307974 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007975#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307976 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007977
7978 create_offload_callback_thread(out);
7979
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007980 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007981 switch (config->sample_rate) {
7982 case 0:
7983 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7984 break;
7985 case 8000:
7986 case 16000:
7987 case 48000:
7988 out->sample_rate = config->sample_rate;
7989 break;
7990 default:
7991 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7992 config->sample_rate);
7993 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7994 ret = -EINVAL;
7995 goto error_open;
7996 }
7997 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7998 switch (config->channel_mask) {
7999 case AUDIO_CHANNEL_NONE:
8000 case AUDIO_CHANNEL_OUT_STEREO:
8001 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8002 break;
8003 default:
8004 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8005 config->channel_mask);
8006 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8007 ret = -EINVAL;
8008 goto error_open;
8009 }
8010 switch (config->format) {
8011 case AUDIO_FORMAT_DEFAULT:
8012 case AUDIO_FORMAT_PCM_16_BIT:
8013 out->format = AUDIO_FORMAT_PCM_16_BIT;
8014 break;
8015 default:
8016 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8017 config->format);
8018 config->format = AUDIO_FORMAT_PCM_16_BIT;
8019 ret = -EINVAL;
8020 goto error_open;
8021 }
8022
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308023 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008024 if (ret != 0) {
8025 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008026 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008027 goto error_open;
8028 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008029 } else if (is_single_device_type_equal(&out->device_list,
8030 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008031 switch (config->sample_rate) {
8032 case 0:
8033 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8034 break;
8035 case 8000:
8036 case 16000:
8037 case 48000:
8038 out->sample_rate = config->sample_rate;
8039 break;
8040 default:
8041 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8042 config->sample_rate);
8043 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8044 ret = -EINVAL;
8045 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008046 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008047 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8048 switch (config->channel_mask) {
8049 case AUDIO_CHANNEL_NONE:
8050 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8051 break;
8052 case AUDIO_CHANNEL_OUT_STEREO:
8053 out->channel_mask = config->channel_mask;
8054 break;
8055 default:
8056 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8057 config->channel_mask);
8058 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8059 ret = -EINVAL;
8060 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008061 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008062 switch (config->format) {
8063 case AUDIO_FORMAT_DEFAULT:
8064 out->format = AUDIO_FORMAT_PCM_16_BIT;
8065 break;
8066 case AUDIO_FORMAT_PCM_16_BIT:
8067 out->format = config->format;
8068 break;
8069 default:
8070 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8071 config->format);
8072 config->format = AUDIO_FORMAT_PCM_16_BIT;
8073 ret = -EINVAL;
8074 break;
8075 }
8076 if (ret != 0)
8077 goto error_open;
8078
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008079 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8080 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008081 out->config.rate = out->sample_rate;
8082 out->config.channels =
8083 audio_channel_count_from_out_mask(out->channel_mask);
8084 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008085 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008086 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308087 unsigned int channels = 0;
8088 /*Update config params to default if not set by the caller*/
8089 if (config->sample_rate == 0)
8090 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8091 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8092 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8093 if (config->format == AUDIO_FORMAT_DEFAULT)
8094 config->format = AUDIO_FORMAT_PCM_16_BIT;
8095
8096 channels = audio_channel_count_from_out_mask(out->channel_mask);
8097
Varun Balaraje49253e2017-07-06 19:48:56 +05308098 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8099 out->usecase = get_interactive_usecase(adev);
8100 out->config = pcm_config_low_latency;
8101 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308102 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008103 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8104 out->flags);
8105 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008106 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8107 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8108 out->config = pcm_config_mmap_playback;
8109 out->stream.start = out_start;
8110 out->stream.stop = out_stop;
8111 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8112 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308113 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8114 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008115 out->hal_output_suspend_supported =
8116 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8117 out->dynamic_pm_qos_config_supported =
8118 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8119 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008120 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8121 } else {
8122 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8123 //the mixer path will be a string similar to "low-latency-playback resume"
8124 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8125 strlcat(out->pm_qos_mixer_path,
8126 " resume", MAX_MIXER_PATH_LEN);
8127 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8128 out->pm_qos_mixer_path);
8129 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308130 out->config = pcm_config_low_latency;
8131 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8132 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8133 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308134 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8135 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8136 if (out->config.period_size <= 0) {
8137 ALOGE("Invalid configuration period size is not valid");
8138 ret = -EINVAL;
8139 goto error_open;
8140 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008141 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8142 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8143 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008144 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8145 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8146 out->config = pcm_config_haptics_audio;
8147 if (force_haptic_path)
8148 adev->haptics_config = pcm_config_haptics_audio;
8149 else
8150 adev->haptics_config = pcm_config_haptics;
8151
Meng Wangd08ce322020-04-02 08:59:20 +08008152 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008153 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8154
8155 if (force_haptic_path) {
8156 out->config.channels = 1;
8157 adev->haptics_config.channels = 1;
8158 } else
8159 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 -08008160 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008161 ret = audio_extn_auto_hal_open_output_stream(out);
8162 if (ret) {
8163 ALOGE("%s: Failed to open output stream for bus device", __func__);
8164 ret = -EINVAL;
8165 goto error_open;
8166 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308167 } else {
8168 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008169 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8170 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308171 }
8172 out->hal_ip_format = format = out->format;
8173 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8174 out->hal_op_format = pcm_format_to_hal(out->config.format);
8175 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8176 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008177 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308178 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308179 if (out->hal_ip_format != out->hal_op_format) {
8180 uint32_t buffer_size = out->config.period_size *
8181 format_to_bitwidth_table[out->hal_op_format] *
8182 out->config.channels;
8183 out->convert_buffer = calloc(1, buffer_size);
8184 if (out->convert_buffer == NULL){
8185 ALOGE("Allocation failed for convert buffer for size %d",
8186 out->compr_config.fragment_size);
8187 ret = -ENOMEM;
8188 goto error_open;
8189 }
8190 ALOGD("Convert buffer allocated of size %d", buffer_size);
8191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008192 }
8193
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008194 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8195 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308196
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008197 /* TODO remove this hardcoding and check why width is zero*/
8198 if (out->bit_width == 0)
8199 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308200 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008201 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008202 &out->device_list, out->flags,
8203 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308204 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308205 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008206 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008207 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8208 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008209 if(adev->primary_output == NULL)
8210 adev->primary_output = out;
8211 else {
8212 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008213 ret = -EEXIST;
8214 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008215 }
8216 }
8217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008218 /* Check if this usecase is already existing */
8219 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008220 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8221 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008222 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008223 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008224 ret = -EEXIST;
8225 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008226 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008228 pthread_mutex_unlock(&adev->lock);
8229
8230 out->stream.common.get_sample_rate = out_get_sample_rate;
8231 out->stream.common.set_sample_rate = out_set_sample_rate;
8232 out->stream.common.get_buffer_size = out_get_buffer_size;
8233 out->stream.common.get_channels = out_get_channels;
8234 out->stream.common.get_format = out_get_format;
8235 out->stream.common.set_format = out_set_format;
8236 out->stream.common.standby = out_standby;
8237 out->stream.common.dump = out_dump;
8238 out->stream.common.set_parameters = out_set_parameters;
8239 out->stream.common.get_parameters = out_get_parameters;
8240 out->stream.common.add_audio_effect = out_add_audio_effect;
8241 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8242 out->stream.get_latency = out_get_latency;
8243 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008244#ifdef NO_AUDIO_OUT
8245 out->stream.write = out_write_for_no_output;
8246#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008247 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008248#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008249 out->stream.get_render_position = out_get_render_position;
8250 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008251 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008252
Haynes Mathew George16081042017-05-31 17:16:49 -07008253 if (out->realtime)
8254 out->af_period_multiplier = af_period_multiplier;
8255 else
8256 out->af_period_multiplier = 1;
8257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008258 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008259 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008260 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008261
8262 config->format = out->stream.common.get_format(&out->stream.common);
8263 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8264 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308265 register_format(out->format, out->supported_formats);
8266 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8267 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008268
Aalique Grahame22e49102018-12-18 14:23:57 -08008269 out->error_log = error_log_create(
8270 ERROR_LOG_ENTRIES,
8271 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8272
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308273 /*
8274 By locking output stream before registering, we allow the callback
8275 to update stream's state only after stream's initial state is set to
8276 adev state.
8277 */
8278 lock_output_stream(out);
8279 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8280 pthread_mutex_lock(&adev->lock);
8281 out->card_status = adev->card_status;
8282 pthread_mutex_unlock(&adev->lock);
8283 pthread_mutex_unlock(&out->lock);
8284
Aalique Grahame22e49102018-12-18 14:23:57 -08008285 stream_app_type_cfg_init(&out->app_type_cfg);
8286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008287 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308288 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008289 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008290
8291 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8292 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8293 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008294 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308295 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008296 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008297 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308298 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8299 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008300 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8301 out->usecase, PCM_PLAYBACK);
8302 hdlr_stream_cfg.flags = out->flags;
8303 hdlr_stream_cfg.type = PCM_PLAYBACK;
8304 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8305 &hdlr_stream_cfg);
8306 if (ret) {
8307 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8308 out->adsp_hdlr_stream_handle = NULL;
8309 }
8310 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308311 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8312 is_direct_passthough, false);
8313 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8314 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008315 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008316 if (ret < 0) {
8317 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8318 out->ip_hdlr_handle = NULL;
8319 }
8320 }
Derek Chenf939fb72018-11-13 13:34:41 -08008321
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008322 ret = io_streams_map_insert(adev, &out->stream.common,
8323 out->handle, AUDIO_PATCH_HANDLE_NONE);
8324 if (ret != 0)
8325 goto error_open;
8326
Derek Chenf939fb72018-11-13 13:34:41 -08008327 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8328 calloc(1, sizeof(streams_output_ctxt_t));
8329 if (out_ctxt == NULL) {
8330 ALOGE("%s fail to allocate output ctxt", __func__);
8331 ret = -ENOMEM;
8332 goto error_open;
8333 }
8334 out_ctxt->output = out;
8335
8336 pthread_mutex_lock(&adev->lock);
8337 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8338 pthread_mutex_unlock(&adev->lock);
8339
Eric Laurent994a6932013-07-17 11:51:42 -07008340 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008341 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008342
8343error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308344 if (out->convert_buffer)
8345 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008346 free(out);
8347 *stream_out = NULL;
8348 ALOGD("%s: exit: ret %d", __func__, ret);
8349 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008350}
8351
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308352void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008353 struct audio_stream_out *stream)
8354{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008355 struct stream_out *out = (struct stream_out *)stream;
8356 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008357 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008358
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008359 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308360
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008361 io_streams_map_remove(adev, out->handle);
8362
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308363 // must deregister from sndmonitor first to prevent races
8364 // between the callback and close_stream
8365 audio_extn_snd_mon_unregister_listener(out);
8366
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008367 /* close adsp hdrl session before standby */
8368 if (out->adsp_hdlr_stream_handle) {
8369 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8370 if (ret)
8371 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8372 out->adsp_hdlr_stream_handle = NULL;
8373 }
8374
Manish Dewangan21a850a2017-08-14 12:03:55 +05308375 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008376 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8377 out->ip_hdlr_handle = NULL;
8378 }
8379
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008380 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308381 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008382 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308383 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308384 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008385 if(ret != 0)
8386 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8387 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008388 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008389 out_standby(&stream->common);
8390
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008391 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008392 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008393 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008394 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008395 if (out->compr_config.codec != NULL)
8396 free(out->compr_config.codec);
8397 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008398
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308399 out->a2dp_compress_mute = false;
8400
Varun Balaraje49253e2017-07-06 19:48:56 +05308401 if (is_interactive_usecase(out->usecase))
8402 free_interactive_usecase(adev, out->usecase);
8403
Ashish Jain83a6cc22016-06-28 14:34:17 +05308404 if (out->convert_buffer != NULL) {
8405 free(out->convert_buffer);
8406 out->convert_buffer = NULL;
8407 }
8408
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008409 if (adev->voice_tx_output == out)
8410 adev->voice_tx_output = NULL;
8411
Aalique Grahame22e49102018-12-18 14:23:57 -08008412 error_log_destroy(out->error_log);
8413 out->error_log = NULL;
8414
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308415 if (adev->primary_output == out)
8416 adev->primary_output = NULL;
8417
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008418 pthread_cond_destroy(&out->cond);
8419 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008420
8421 pthread_mutex_lock(&adev->lock);
8422 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8423 if (out_ctxt != NULL) {
8424 list_remove(&out_ctxt->list);
8425 free(out_ctxt);
8426 } else {
8427 ALOGW("%s, output stream already closed", __func__);
8428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008429 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008430 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008431 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008432}
8433
8434static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8435{
8436 struct audio_device *adev = (struct audio_device *)dev;
8437 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008438 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008439 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008440 int ret;
8441 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008442 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008443 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008444 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008445
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008446 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008447 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008448
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308449 if (!parms)
8450 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308451
Derek Chen6f293672019-04-01 01:40:24 -07008452 /* notify adev and input/output streams on the snd card status */
8453 adev_snd_mon_cb((void *)adev, parms);
8454
8455 list_for_each(node, &adev->active_outputs_list) {
8456 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8457 streams_output_ctxt_t,
8458 list);
8459 out_snd_mon_cb((void *)out_ctxt->output, parms);
8460 }
8461
8462 list_for_each(node, &adev->active_inputs_list) {
8463 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8464 streams_input_ctxt_t,
8465 list);
8466 in_snd_mon_cb((void *)in_ctxt->input, parms);
8467 }
8468
Zhou Songd6d71752019-05-21 18:08:51 +08008469 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308470 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8471 if (ret >= 0) {
8472 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008473 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308474 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008475 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308476 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008477 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008478 }
8479 }
8480
8481 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8482 if (ret>=0) {
8483 if (!strncmp(value, "false", 5) &&
8484 audio_extn_a2dp_source_is_suspended()) {
8485 struct audio_usecase *usecase;
8486 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008487 list_for_each(node, &adev->usecase_list) {
8488 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008489 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008490 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008491 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008492 reassign_device_list(&usecase->stream.in->device_list,
8493 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008494 select_devices(adev, usecase->id);
8495 }
Zhou Songd6d71752019-05-21 18:08:51 +08008496 }
8497 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308498 }
8499
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008500 status = voice_set_parameters(adev, parms);
8501 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008502 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008503
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008504 status = platform_set_parameters(adev->platform, parms);
8505 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008506 goto done;
8507
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008508 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8509 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008510 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008511 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8512 adev->bluetooth_nrec = true;
8513 else
8514 adev->bluetooth_nrec = false;
8515 }
8516
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008517 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8518 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008519 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8520 adev->screen_off = false;
8521 else
8522 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008523 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008524 }
8525
Eric Laurent4b084132018-10-19 17:33:43 -07008526 ret = str_parms_get_int(parms, "rotation", &val);
8527 if (ret >= 0) {
8528 bool reverse_speakers = false;
8529 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8530 switch (val) {
8531 // FIXME: note that the code below assumes that the speakers are in the correct placement
8532 // relative to the user when the device is rotated 90deg from its default rotation. This
8533 // assumption is device-specific, not platform-specific like this code.
8534 case 270:
8535 reverse_speakers = true;
8536 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8537 break;
8538 case 0:
8539 case 180:
8540 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8541 break;
8542 case 90:
8543 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8544 break;
8545 default:
8546 ALOGE("%s: unexpected rotation of %d", __func__, val);
8547 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008548 }
Eric Laurent4b084132018-10-19 17:33:43 -07008549 if (status == 0) {
8550 // check and set swap
8551 // - check if orientation changed and speaker active
8552 // - set rotation and cache the rotation value
8553 adev->camera_orientation =
8554 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8555 if (!audio_extn_is_maxx_audio_enabled())
8556 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8557 }
8558 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008559
Mingming Yin514a8bc2014-07-29 15:22:21 -07008560 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8561 if (ret >= 0) {
8562 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8563 adev->bt_wb_speech_enabled = true;
8564 else
8565 adev->bt_wb_speech_enabled = false;
8566 }
8567
Zhou Song12c29502019-03-16 10:37:18 +08008568 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8569 if (ret >= 0) {
8570 val = atoi(value);
8571 adev->swb_speech_mode = val;
8572 }
8573
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008574 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8575 if (ret >= 0) {
8576 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308577 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008578 if (audio_is_output_device(val) &&
8579 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008580 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008581 platform_get_controller_stream_from_params(parms, &controller, &stream);
8582 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8583 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008584 if (ret < 0) {
8585 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308586 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008587 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008588 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308589 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008590 /*
8591 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8592 * Per AudioPolicyManager, USB device is higher priority than WFD.
8593 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8594 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8595 * starting voice call on USB
8596 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008597 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308598 if (ret >= 0)
8599 audio_extn_usb_add_device(device, atoi(value));
8600
Zhou Song6f862822017-11-06 17:27:57 +08008601 if (!audio_extn_usb_is_tunnel_supported()) {
8602 ALOGV("detected USB connect .. disable proxy");
8603 adev->allow_afe_proxy_usage = false;
8604 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008605 }
8606 }
8607
8608 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8609 if (ret >= 0) {
8610 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308611 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008612 /*
8613 * The HDMI / Displayport disconnect handling has been moved to
8614 * audio extension to ensure that its parameters are not
8615 * invalidated prior to updating sysfs of the disconnect event
8616 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8617 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308618 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008619 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308620 if (ret >= 0)
8621 audio_extn_usb_remove_device(device, atoi(value));
8622
Zhou Song6f862822017-11-06 17:27:57 +08008623 if (!audio_extn_usb_is_tunnel_supported()) {
8624 ALOGV("detected USB disconnect .. enable proxy");
8625 adev->allow_afe_proxy_usage = true;
8626 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008627 }
8628 }
8629
Aalique Grahame22e49102018-12-18 14:23:57 -08008630 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008631 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008632
8633 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008634 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308635 struct audio_usecase *usecase;
8636 struct listnode *node;
8637 list_for_each(node, &adev->usecase_list) {
8638 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308639 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008640 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308641 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008642 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308643 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008644 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308645 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308646 ALOGD("Switching to speaker and muting the stream before select_devices");
8647 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308648 //force device switch to re configure encoder
8649 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308650 ALOGD("Unmuting the stream after select_devices");
8651 usecase->stream.out->a2dp_compress_mute = false;
8652 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 +05308653 audio_extn_a2dp_set_handoff_mode(false);
8654 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308655 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308656 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8657 usecase->stream.out->a2dp_compress_mute) {
8658 pthread_mutex_unlock(&adev->lock);
8659 lock_output_stream(usecase->stream.out);
8660 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008661 reassign_device_list(&usecase->stream.out->device_list,
8662 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308663 check_a2dp_restore_l(adev, usecase->stream.out, true);
8664 pthread_mutex_unlock(&usecase->stream.out->lock);
8665 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308666 }
8667 }
8668 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008669
8670 //handle vr audio setparam
8671 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8672 value, sizeof(value));
8673 if (ret >= 0) {
8674 ALOGI("Setting vr mode to be %s", value);
8675 if (!strncmp(value, "true", 4)) {
8676 adev->vr_audio_mode_enabled = true;
8677 ALOGI("Setting vr mode to true");
8678 } else if (!strncmp(value, "false", 5)) {
8679 adev->vr_audio_mode_enabled = false;
8680 ALOGI("Setting vr mode to false");
8681 } else {
8682 ALOGI("wrong vr mode set");
8683 }
8684 }
8685
Eric Laurent4b084132018-10-19 17:33:43 -07008686 //FIXME: to be replaced by proper video capture properties API
8687 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8688 if (ret >= 0) {
8689 int camera_facing = CAMERA_FACING_BACK;
8690 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8691 camera_facing = CAMERA_FACING_FRONT;
8692 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8693 camera_facing = CAMERA_FACING_BACK;
8694 else {
8695 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8696 goto done;
8697 }
8698 adev->camera_orientation =
8699 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8700 struct audio_usecase *usecase;
8701 struct listnode *node;
8702 list_for_each(node, &adev->usecase_list) {
8703 usecase = node_to_item(node, struct audio_usecase, list);
8704 struct stream_in *in = usecase->stream.in;
8705 if (usecase->type == PCM_CAPTURE && in != NULL &&
8706 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8707 select_devices(adev, in->usecase);
8708 }
8709 }
8710 }
8711
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308712 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008713done:
8714 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008715 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308716error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008717 ALOGV("%s: exit with code(%d)", __func__, status);
8718 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008719}
8720
8721static char* adev_get_parameters(const struct audio_hw_device *dev,
8722 const char *keys)
8723{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308724 ALOGD("%s:%s", __func__, keys);
8725
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008726 struct audio_device *adev = (struct audio_device *)dev;
8727 struct str_parms *reply = str_parms_create();
8728 struct str_parms *query = str_parms_create_str(keys);
8729 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308730 char value[256] = {0};
8731 int ret = 0;
8732
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008733 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008734 if (reply) {
8735 str_parms_destroy(reply);
8736 }
8737 if (query) {
8738 str_parms_destroy(query);
8739 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008740 ALOGE("adev_get_parameters: failed to create query or reply");
8741 return NULL;
8742 }
8743
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008744 //handle vr audio getparam
8745
8746 ret = str_parms_get_str(query,
8747 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8748 value, sizeof(value));
8749
8750 if (ret >= 0) {
8751 bool vr_audio_enabled = false;
8752 pthread_mutex_lock(&adev->lock);
8753 vr_audio_enabled = adev->vr_audio_mode_enabled;
8754 pthread_mutex_unlock(&adev->lock);
8755
8756 ALOGI("getting vr mode to %d", vr_audio_enabled);
8757
8758 if (vr_audio_enabled) {
8759 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8760 "true");
8761 goto exit;
8762 } else {
8763 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8764 "false");
8765 goto exit;
8766 }
8767 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008768
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008769 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008770 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008771 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008772 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008773 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308774 pthread_mutex_unlock(&adev->lock);
8775
Naresh Tannirud7205b62014-06-20 02:54:48 +05308776exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008777 str = str_parms_to_str(reply);
8778 str_parms_destroy(query);
8779 str_parms_destroy(reply);
8780
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308781 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008782 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008783}
8784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008785static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008786{
8787 return 0;
8788}
8789
8790static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8791{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008792 int ret;
8793 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008794
8795 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8796
Haynes Mathew George5191a852013-09-11 14:19:36 -07008797 pthread_mutex_lock(&adev->lock);
8798 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008799 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008800 pthread_mutex_unlock(&adev->lock);
8801 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008802}
8803
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008804static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8805 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008806{
8807 return -ENOSYS;
8808}
8809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008810static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8811 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008812{
8813 return -ENOSYS;
8814}
8815
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008816static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8817 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008818{
8819 return -ENOSYS;
8820}
8821
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008822static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8823 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824{
8825 return -ENOSYS;
8826}
8827
8828static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8829{
8830 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008831 struct listnode *node;
8832 struct audio_usecase *usecase = NULL;
8833 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008835 pthread_mutex_lock(&adev->lock);
8836 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308837 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8838 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008839 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308840 if( mode == AUDIO_MODE_CALL_SCREEN ){
8841 adev->current_call_output = adev->primary_output;
8842 voice_start_call(adev);
8843 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008844 (mode == AUDIO_MODE_NORMAL ||
8845 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008846 list_for_each(node, &adev->usecase_list) {
8847 usecase = node_to_item(node, struct audio_usecase, list);
8848 if (usecase->type == VOICE_CALL)
8849 break;
8850 }
8851 if (usecase &&
8852 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8853 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8854 true);
8855 if (ret != 0) {
8856 /* default service interval was successfully updated,
8857 reopen USB backend with new service interval */
8858 check_usecases_codec_backend(adev,
8859 usecase,
8860 usecase->out_snd_device);
8861 }
8862 }
8863
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008864 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008865 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008866 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008867 // restore device for other active usecases after stop call
8868 list_for_each(node, &adev->usecase_list) {
8869 usecase = node_to_item(node, struct audio_usecase, list);
8870 select_devices(adev, usecase->id);
8871 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008872 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008873 }
8874 pthread_mutex_unlock(&adev->lock);
8875 return 0;
8876}
8877
8878static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8879{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008880 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008881 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008882
8883 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008884 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008885 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008886
Derek Chend2530072014-11-24 12:39:14 -08008887 if (adev->ext_hw_plugin)
8888 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008889
8890 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008891 pthread_mutex_unlock(&adev->lock);
8892
8893 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008894}
8895
8896static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8897{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008898 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008899 return 0;
8900}
8901
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008902static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008903 const struct audio_config *config)
8904{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008905 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008906
Aalique Grahame22e49102018-12-18 14:23:57 -08008907 /* Don't know if USB HIFI in this context so use true to be conservative */
8908 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8909 true /*is_usb_hifi */) != 0)
8910 return 0;
8911
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008912 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8913 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008914}
8915
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008916static bool adev_input_allow_hifi_record(struct audio_device *adev,
8917 audio_devices_t devices,
8918 audio_input_flags_t flags,
8919 audio_source_t source) {
8920 const bool allowed = true;
8921
8922 if (!audio_is_usb_in_device(devices))
8923 return !allowed;
8924
8925 switch (flags) {
8926 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008927 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008928 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8929 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008930 default:
8931 return !allowed;
8932 }
8933
8934 switch (source) {
8935 case AUDIO_SOURCE_DEFAULT:
8936 case AUDIO_SOURCE_MIC:
8937 case AUDIO_SOURCE_UNPROCESSED:
8938 break;
8939 default:
8940 return !allowed;
8941 }
8942
8943 switch (adev->mode) {
8944 case 0:
8945 break;
8946 default:
8947 return !allowed;
8948 }
8949
8950 return allowed;
8951}
8952
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008953static int adev_update_voice_comm_input_stream(struct stream_in *in,
8954 struct audio_config *config)
8955{
8956 bool valid_rate = (config->sample_rate == 8000 ||
8957 config->sample_rate == 16000 ||
8958 config->sample_rate == 32000 ||
8959 config->sample_rate == 48000);
8960 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8961
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008962 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008963 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008964 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8965 in->config = default_pcm_config_voip_copp;
8966 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8967 DEFAULT_VOIP_BUF_DURATION_MS,
8968 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008969 } else {
8970 ALOGW("%s No valid input in voip, use defaults"
8971 "sample rate %u, channel mask 0x%X",
8972 __func__, config->sample_rate, in->channel_mask);
8973 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008974 in->config.rate = config->sample_rate;
8975 in->sample_rate = config->sample_rate;
8976 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008977 //XXX needed for voice_extn_compress_voip_open_input_stream
8978 in->config.rate = config->sample_rate;
8979 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308980 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008981 voice_extn_compress_voip_is_active(in->dev)) &&
8982 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8983 valid_rate && valid_ch) {
8984 voice_extn_compress_voip_open_input_stream(in);
8985 // update rate entries to match config from AF
8986 in->config.rate = config->sample_rate;
8987 in->sample_rate = config->sample_rate;
8988 } else {
8989 ALOGW("%s compress voip not active, use defaults", __func__);
8990 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008991 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008992 return 0;
8993}
8994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008995static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008996 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008997 audio_devices_t devices,
8998 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008999 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309000 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009001 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009002 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009003{
9004 struct audio_device *adev = (struct audio_device *)dev;
9005 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009006 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009007 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009008 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309009 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009010 bool is_usb_dev = audio_is_usb_in_device(devices);
9011 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9012 devices,
9013 flags,
9014 source);
Andy Hung94320602018-10-29 18:31:12 -07009015 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9016 " sample_rate %u, channel_mask %#x, format %#x",
9017 __func__, flags, is_usb_dev, may_use_hifi_record,
9018 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309019
kunleizdff872d2018-08-20 14:40:33 +08009020 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009021 is_usb_dev = false;
9022 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9023 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9024 __func__, devices);
9025 }
9026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009027 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009028
9029 if (!(is_usb_dev && may_use_hifi_record)) {
9030 if (config->sample_rate == 0)
9031 config->sample_rate = 48000;
9032 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9033 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9034 if (config->format == AUDIO_FORMAT_DEFAULT)
9035 config->format = AUDIO_FORMAT_PCM_16_BIT;
9036
9037 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9038
Aalique Grahame22e49102018-12-18 14:23:57 -08009039 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9040 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009041 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309042 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043
Rahul Sharma99770982019-03-06 17:05:26 +05309044 pthread_mutex_lock(&adev->lock);
9045 if (in_get_stream(adev, handle) != NULL) {
9046 ALOGW("%s, input stream already opened", __func__);
9047 ret = -EEXIST;
9048 }
9049 pthread_mutex_unlock(&adev->lock);
9050 if (ret)
9051 return ret;
9052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009053 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009054
9055 if (!in) {
9056 ALOGE("failed to allocate input stream");
9057 return -ENOMEM;
9058 }
9059
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309060 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309061 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9062 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009063 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009064 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009066 in->stream.common.get_sample_rate = in_get_sample_rate;
9067 in->stream.common.set_sample_rate = in_set_sample_rate;
9068 in->stream.common.get_buffer_size = in_get_buffer_size;
9069 in->stream.common.get_channels = in_get_channels;
9070 in->stream.common.get_format = in_get_format;
9071 in->stream.common.set_format = in_set_format;
9072 in->stream.common.standby = in_standby;
9073 in->stream.common.dump = in_dump;
9074 in->stream.common.set_parameters = in_set_parameters;
9075 in->stream.common.get_parameters = in_get_parameters;
9076 in->stream.common.add_audio_effect = in_add_audio_effect;
9077 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9078 in->stream.set_gain = in_set_gain;
9079 in->stream.read = in_read;
9080 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009081 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309082 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009083 in->stream.set_microphone_direction = in_set_microphone_direction;
9084 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009085 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009086
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009087 list_init(&in->device_list);
9088 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009089 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009090 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009091 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009092 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009093 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009094 in->bit_width = 16;
9095 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009096 in->direction = MIC_DIRECTION_UNSPECIFIED;
9097 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009098 list_init(&in->aec_list);
9099 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009100 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009101
Andy Hung94320602018-10-29 18:31:12 -07009102 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009103 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9104 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9105 /* Force channel config requested to mono if incall
9106 record is being requested for only uplink/downlink */
9107 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9108 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9109 ret = -EINVAL;
9110 goto err_open;
9111 }
9112 }
9113
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009114 if (is_usb_dev && may_use_hifi_record) {
9115 /* HiFi record selects an appropriate format, channel, rate combo
9116 depending on sink capabilities*/
9117 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9118 &config->format,
9119 &in->supported_formats[0],
9120 MAX_SUPPORTED_FORMATS,
9121 &config->channel_mask,
9122 &in->supported_channel_masks[0],
9123 MAX_SUPPORTED_CHANNEL_MASKS,
9124 &config->sample_rate,
9125 &in->supported_sample_rates[0],
9126 MAX_SUPPORTED_SAMPLE_RATES);
9127 if (ret != 0) {
9128 ret = -EINVAL;
9129 goto err_open;
9130 }
9131 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009132 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309133 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309134 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9135 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9136 in->config.format = PCM_FORMAT_S32_LE;
9137 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309138 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9139 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9140 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9141 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9142 bool ret_error = false;
9143 in->bit_width = 24;
9144 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9145 from HAL is 24_packed and 8_24
9146 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9147 24_packed return error indicating supported format is 24_packed
9148 *> In case of any other source requesting 24 bit or float return error
9149 indicating format supported is 16 bit only.
9150
9151 on error flinger will retry with supported format passed
9152 */
9153 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9154 (source != AUDIO_SOURCE_CAMCORDER)) {
9155 config->format = AUDIO_FORMAT_PCM_16_BIT;
9156 if (config->sample_rate > 48000)
9157 config->sample_rate = 48000;
9158 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009159 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9160 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309161 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9162 ret_error = true;
9163 }
9164
9165 if (ret_error) {
9166 ret = -EINVAL;
9167 goto err_open;
9168 }
9169 }
9170
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009171 in->channel_mask = config->channel_mask;
9172 in->format = config->format;
9173
9174 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309175
9176 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9177 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9178 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9179 else {
9180 ret = -EINVAL;
9181 goto err_open;
9182 }
9183 }
9184
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009185 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309186 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9187 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009188 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9189 is_low_latency = true;
9190#if LOW_LATENCY_CAPTURE_USE_CASE
9191 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9192#endif
9193 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009194 if (!in->realtime) {
9195 in->config = pcm_config_audio_capture;
9196 frame_size = audio_stream_in_frame_size(&in->stream);
9197 buffer_size = get_input_buffer_size(config->sample_rate,
9198 config->format,
9199 channel_count,
9200 is_low_latency);
9201 in->config.period_size = buffer_size / frame_size;
9202 in->config.rate = config->sample_rate;
9203 in->af_period_multiplier = 1;
9204 } else {
9205 // period size is left untouched for rt mode playback
9206 in->config = pcm_config_audio_capture_rt;
9207 in->af_period_multiplier = af_period_multiplier;
9208 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009209 }
9210
9211 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9212 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9213 in->realtime = 0;
9214 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9215 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009216 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009217 in->stream.start = in_start;
9218 in->stream.stop = in_stop;
9219 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9220 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009221 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009222 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009223 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9224 in->config = pcm_config_audio_capture;
9225 frame_size = audio_stream_in_frame_size(&in->stream);
9226 buffer_size = get_input_buffer_size(config->sample_rate,
9227 config->format,
9228 channel_count,
9229 false /*is_low_latency*/);
9230 in->config.period_size = buffer_size / frame_size;
9231 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009232 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009233 switch (config->format) {
9234 case AUDIO_FORMAT_PCM_32_BIT:
9235 in->bit_width = 32;
9236 break;
9237 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9238 case AUDIO_FORMAT_PCM_8_24_BIT:
9239 in->bit_width = 24;
9240 break;
9241 default:
9242 in->bit_width = 16;
9243 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009244 } else if (is_single_device_type_equal(&in->device_list,
9245 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9246 is_single_device_type_equal(&in->device_list,
9247 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009248 if (config->sample_rate == 0)
9249 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9250 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9251 config->sample_rate != 8000) {
9252 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9253 ret = -EINVAL;
9254 goto err_open;
9255 }
9256 if (config->format == AUDIO_FORMAT_DEFAULT)
9257 config->format = AUDIO_FORMAT_PCM_16_BIT;
9258 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9259 config->format = AUDIO_FORMAT_PCM_16_BIT;
9260 ret = -EINVAL;
9261 goto err_open;
9262 }
9263
9264 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9265 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009266 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009267 in->af_period_multiplier = 1;
9268 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9269 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9270 (config->sample_rate == 8000 ||
9271 config->sample_rate == 16000 ||
9272 config->sample_rate == 32000 ||
9273 config->sample_rate == 48000) &&
9274 channel_count == 1) {
9275 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9276 in->config = pcm_config_audio_capture;
9277 frame_size = audio_stream_in_frame_size(&in->stream);
9278 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9279 config->sample_rate,
9280 config->format,
9281 channel_count, false /*is_low_latency*/);
9282 in->config.period_size = buffer_size / frame_size;
9283 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9284 in->config.rate = config->sample_rate;
9285 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009286 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309287 int ret_val;
9288 pthread_mutex_lock(&adev->lock);
9289 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9290 in, config, &channel_mask_updated);
9291 pthread_mutex_unlock(&adev->lock);
9292
9293 if (!ret_val) {
9294 if (channel_mask_updated == true) {
9295 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9296 __func__, config->channel_mask);
9297 ret = -EINVAL;
9298 goto err_open;
9299 }
9300 ALOGD("%s: created multi-channel session succesfully",__func__);
9301 } else if (audio_extn_compr_cap_enabled() &&
9302 audio_extn_compr_cap_format_supported(config->format) &&
9303 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9304 audio_extn_compr_cap_init(in);
9305 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309306 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309307 if (ret)
9308 goto err_open;
9309 } else {
9310 in->config = pcm_config_audio_capture;
9311 in->config.rate = config->sample_rate;
9312 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309313 in->format = config->format;
9314 frame_size = audio_stream_in_frame_size(&in->stream);
9315 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009316 config->format,
9317 channel_count,
9318 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009319 /* prevent division-by-zero */
9320 if (frame_size == 0) {
9321 ALOGE("%s: Error frame_size==0", __func__);
9322 ret = -EINVAL;
9323 goto err_open;
9324 }
9325
Revathi Uddarajud2634032017-12-07 14:42:34 +05309326 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009327 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009328
Revathi Uddarajud2634032017-12-07 14:42:34 +05309329 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9330 /* optionally use VOIP usecase depending on config(s) */
9331 ret = adev_update_voice_comm_input_stream(in, config);
9332 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009333
Revathi Uddarajud2634032017-12-07 14:42:34 +05309334 if (ret) {
9335 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9336 goto err_open;
9337 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009338 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309339
9340 /* assign concurrent capture usecase if record has to caried out from
9341 * actual hardware input source */
9342 if (audio_extn_is_concurrent_capture_enabled() &&
9343 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309344 /* Acquire lock to avoid two concurrent use cases initialized to
9345 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009346
Samyak Jainc37062f2019-04-25 18:41:06 +05309347 if (in->usecase == USECASE_AUDIO_RECORD) {
9348 pthread_mutex_lock(&adev->lock);
9349 if (!(adev->pcm_record_uc_state)) {
9350 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9351 adev->pcm_record_uc_state = 1;
9352 pthread_mutex_unlock(&adev->lock);
9353 } else {
9354 pthread_mutex_unlock(&adev->lock);
9355 /* Assign compress record use case for second record */
9356 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9357 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9358 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9359 if (audio_extn_cin_applicable_stream(in)) {
9360 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309361 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309362 if (ret)
9363 goto err_open;
9364 }
9365 }
9366 }
kunleiz28c73e72019-03-27 17:24:04 +08009367 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009368 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309369 if (audio_extn_ssr_get_stream() != in)
9370 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009371
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009372 in->sample_rate = in->config.rate;
9373
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309374 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9375 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009376 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009377 in->sample_rate, in->bit_width,
9378 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309379 register_format(in->format, in->supported_formats);
9380 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9381 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309382
Aalique Grahame22e49102018-12-18 14:23:57 -08009383 in->error_log = error_log_create(
9384 ERROR_LOG_ENTRIES,
9385 1000000000 /* aggregate consecutive identical errors within one second */);
9386
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009387 /* This stream could be for sound trigger lab,
9388 get sound trigger pcm if present */
9389 audio_extn_sound_trigger_check_and_get_session(in);
9390
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309391 lock_input_stream(in);
9392 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9393 pthread_mutex_lock(&adev->lock);
9394 in->card_status = adev->card_status;
9395 pthread_mutex_unlock(&adev->lock);
9396 pthread_mutex_unlock(&in->lock);
9397
Aalique Grahame22e49102018-12-18 14:23:57 -08009398 stream_app_type_cfg_init(&in->app_type_cfg);
9399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009400 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009401
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009402 ret = io_streams_map_insert(adev, &in->stream.common,
9403 handle, AUDIO_PATCH_HANDLE_NONE);
9404 if (ret != 0)
9405 goto err_open;
9406
Derek Chenf939fb72018-11-13 13:34:41 -08009407 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9408 calloc(1, sizeof(streams_input_ctxt_t));
9409 if (in_ctxt == NULL) {
9410 ALOGE("%s fail to allocate input ctxt", __func__);
9411 ret = -ENOMEM;
9412 goto err_open;
9413 }
9414 in_ctxt->input = in;
9415
9416 pthread_mutex_lock(&adev->lock);
9417 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9418 pthread_mutex_unlock(&adev->lock);
9419
Eric Laurent994a6932013-07-17 11:51:42 -07009420 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009421 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009422
9423err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309424 if (in->usecase == USECASE_AUDIO_RECORD) {
9425 pthread_mutex_lock(&adev->lock);
9426 adev->pcm_record_uc_state = 0;
9427 pthread_mutex_unlock(&adev->lock);
9428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009429 free(in);
9430 *stream_in = NULL;
9431 return ret;
9432}
9433
9434static void adev_close_input_stream(struct audio_hw_device *dev,
9435 struct audio_stream_in *stream)
9436{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009437 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009438 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009439 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309440
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309441 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009442
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009443 if (in == NULL) {
9444 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9445 return;
9446 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009447 io_streams_map_remove(adev, in->capture_handle);
9448
kunleiz70e57612018-12-28 17:50:23 +08009449 /* must deregister from sndmonitor first to prevent races
9450 * between the callback and close_stream
9451 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309452 audio_extn_snd_mon_unregister_listener(stream);
9453
kunleiz70e57612018-12-28 17:50:23 +08009454 /* Disable echo reference if there are no active input, hfp call
9455 * and sound trigger while closing input stream
9456 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009457 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009458 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009459 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9460 struct listnode out_devices;
9461 list_init(&out_devices);
9462 platform_set_echo_reference(adev, false, &out_devices);
9463 } else
kunleiz70e57612018-12-28 17:50:23 +08009464 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309465
Weiyin Jiang2995f662019-04-17 14:25:12 +08009466 error_log_destroy(in->error_log);
9467 in->error_log = NULL;
9468
Pallavid7c7a272018-01-16 11:22:55 +05309469
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009470 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309471 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009472 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309473 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009474 if (ret != 0)
9475 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9476 __func__, ret);
9477 } else
9478 in_standby(&stream->common);
9479
Revathi Uddarajud2634032017-12-07 14:42:34 +05309480 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309481 if (in->usecase == USECASE_AUDIO_RECORD) {
9482 adev->pcm_record_uc_state = 0;
9483 }
9484
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009485 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9486 adev->enable_voicerx = false;
9487 }
9488
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009489 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009490 audio_extn_ssr_deinit();
9491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009492
Garmond Leunge2433c32017-09-28 21:51:22 -07009493 if (audio_extn_ffv_get_stream() == in) {
9494 audio_extn_ffv_stream_deinit();
9495 }
9496
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309497 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009498 audio_extn_compr_cap_format_supported(in->config.format))
9499 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309500
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309501 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309502 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009503
Mingming Yinfd7607b2016-01-22 12:48:44 -08009504 if (in->is_st_session) {
9505 ALOGV("%s: sound trigger pcm stop lab", __func__);
9506 audio_extn_sound_trigger_stop_lab(in);
9507 }
Derek Chenf939fb72018-11-13 13:34:41 -08009508 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9509 if (in_ctxt != NULL) {
9510 list_remove(&in_ctxt->list);
9511 free(in_ctxt);
9512 } else {
9513 ALOGW("%s, input stream already closed", __func__);
9514 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009515 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309516 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009517 return;
9518}
9519
Aalique Grahame22e49102018-12-18 14:23:57 -08009520/* verifies input and output devices and their capabilities.
9521 *
9522 * This verification is required when enabling extended bit-depth or
9523 * sampling rates, as not all qcom products support it.
9524 *
9525 * Suitable for calling only on initialization such as adev_open().
9526 * It fills the audio_device use_case_table[] array.
9527 *
9528 * Has a side-effect that it needs to configure audio routing / devices
9529 * in order to power up the devices and read the device parameters.
9530 * It does not acquire any hw device lock. Should restore the devices
9531 * back to "normal state" upon completion.
9532 */
9533static int adev_verify_devices(struct audio_device *adev)
9534{
9535 /* enumeration is a bit difficult because one really wants to pull
9536 * the use_case, device id, etc from the hidden pcm_device_table[].
9537 * In this case there are the following use cases and device ids.
9538 *
9539 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9540 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9541 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9542 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9543 * [USECASE_AUDIO_RECORD] = {0, 0},
9544 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9545 * [USECASE_VOICE_CALL] = {2, 2},
9546 *
9547 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9548 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9549 */
9550
9551 /* should be the usecases enabled in adev_open_input_stream() */
9552 static const int test_in_usecases[] = {
9553 USECASE_AUDIO_RECORD,
9554 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9555 };
9556 /* should be the usecases enabled in adev_open_output_stream()*/
9557 static const int test_out_usecases[] = {
9558 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9559 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9560 };
9561 static const usecase_type_t usecase_type_by_dir[] = {
9562 PCM_PLAYBACK,
9563 PCM_CAPTURE,
9564 };
9565 static const unsigned flags_by_dir[] = {
9566 PCM_OUT,
9567 PCM_IN,
9568 };
9569
9570 size_t i;
9571 unsigned dir;
9572 const unsigned card_id = adev->snd_card;
9573
9574 for (dir = 0; dir < 2; ++dir) {
9575 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9576 const unsigned flags_dir = flags_by_dir[dir];
9577 const size_t testsize =
9578 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9579 const int *testcases =
9580 dir ? test_in_usecases : test_out_usecases;
9581 const audio_devices_t audio_device =
9582 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9583
9584 for (i = 0; i < testsize; ++i) {
9585 const audio_usecase_t audio_usecase = testcases[i];
9586 int device_id;
9587 struct pcm_params **pparams;
9588 struct stream_out out;
9589 struct stream_in in;
9590 struct audio_usecase uc_info;
9591 int retval;
9592
9593 pparams = &adev->use_case_table[audio_usecase];
9594 pcm_params_free(*pparams); /* can accept null input */
9595 *pparams = NULL;
9596
9597 /* find the device ID for the use case (signed, for error) */
9598 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9599 if (device_id < 0)
9600 continue;
9601
9602 /* prepare structures for device probing */
9603 memset(&uc_info, 0, sizeof(uc_info));
9604 uc_info.id = audio_usecase;
9605 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009606 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009607 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009608 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009609 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009610 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009611 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9612 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009613 }
9614 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009615 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009616 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009617 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009618 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009619 uc_info.in_snd_device = SND_DEVICE_NONE;
9620 uc_info.out_snd_device = SND_DEVICE_NONE;
9621 list_add_tail(&adev->usecase_list, &uc_info.list);
9622
9623 /* select device - similar to start_(in/out)put_stream() */
9624 retval = select_devices(adev, audio_usecase);
9625 if (retval >= 0) {
9626 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9627#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009628 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009629 if (*pparams) {
9630 ALOGV("%s: (%s) card %d device %d", __func__,
9631 dir ? "input" : "output", card_id, device_id);
9632 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9633 } else {
9634 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9635 }
9636#endif
9637 }
9638
9639 /* deselect device - similar to stop_(in/out)put_stream() */
9640 /* 1. Get and set stream specific mixer controls */
9641 retval = disable_audio_route(adev, &uc_info);
9642 /* 2. Disable the rx device */
9643 retval = disable_snd_device(adev,
9644 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9645 list_remove(&uc_info.list);
9646 }
9647 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009648 return 0;
9649}
9650
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009651int update_patch(unsigned int num_sources,
9652 const struct audio_port_config *sources,
9653 unsigned int num_sinks,
9654 const struct audio_port_config *sinks,
9655 audio_patch_handle_t handle,
9656 struct audio_patch_info *p_info,
9657 patch_type_t patch_type, bool new_patch)
9658{
9659 ALOGD("%s: enter", __func__);
9660
9661 if (p_info == NULL) {
9662 ALOGE("%s: Invalid patch pointer", __func__);
9663 return -EINVAL;
9664 }
9665
9666 if (new_patch) {
9667 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9668 if (p_info->patch == NULL) {
9669 ALOGE("%s: Could not allocate patch", __func__);
9670 return -ENOMEM;
9671 }
9672 }
9673
9674 p_info->patch->id = handle;
9675 p_info->patch->num_sources = num_sources;
9676 p_info->patch->num_sinks = num_sinks;
9677
9678 for (int i = 0; i < num_sources; i++)
9679 p_info->patch->sources[i] = sources[i];
9680 for (int i = 0; i < num_sinks; i++)
9681 p_info->patch->sinks[i] = sinks[i];
9682
9683 p_info->patch_type = patch_type;
9684 return 0;
9685}
9686
9687audio_patch_handle_t generate_patch_handle()
9688{
9689 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9690 if (++patch_handle < 0)
9691 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9692 return patch_handle;
9693}
9694
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309695int adev_create_audio_patch(struct audio_hw_device *dev,
9696 unsigned int num_sources,
9697 const struct audio_port_config *sources,
9698 unsigned int num_sinks,
9699 const struct audio_port_config *sinks,
9700 audio_patch_handle_t *handle)
9701{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009702 int ret = 0;
9703 struct audio_device *adev = (struct audio_device *)dev;
9704 struct audio_patch_info *p_info = NULL;
9705 patch_type_t patch_type = PATCH_NONE;
9706 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9707 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9708 struct audio_stream_info *s_info = NULL;
9709 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009710 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009711 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9712 bool new_patch = false;
9713 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309714
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009715 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9716 num_sources, num_sinks, *handle);
9717
9718 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9719 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9720 ALOGE("%s: Invalid patch arguments", __func__);
9721 ret = -EINVAL;
9722 goto done;
9723 }
9724
9725 if (num_sources > 1) {
9726 ALOGE("%s: Multiple sources are not supported", __func__);
9727 ret = -EINVAL;
9728 goto done;
9729 }
9730
9731 if (sources == NULL || sinks == NULL) {
9732 ALOGE("%s: Invalid sources or sinks port config", __func__);
9733 ret = -EINVAL;
9734 goto done;
9735 }
9736
9737 ALOGV("%s: source role %d, source type %d", __func__,
9738 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009739 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009740
9741 // Populate source/sink information and fetch stream info
9742 switch (sources[0].type) {
9743 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9744 device_type = sources[0].ext.device.type;
9745 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009746 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009747 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9748 patch_type = PATCH_CAPTURE;
9749 io_handle = sinks[0].ext.mix.handle;
9750 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009751 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009752 __func__, device_type, io_handle);
9753 } else {
9754 // Device to device patch is not implemented.
9755 // This space will need changes if audio HAL
9756 // handles device to device patches in the future.
9757 patch_type = PATCH_DEVICE_LOOPBACK;
9758 }
9759 break;
9760 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9761 io_handle = sources[0].ext.mix.handle;
9762 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009763 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009764 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009765 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009766 }
9767 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009768 ALOGD("%s: Playback patch from mix handle %d to device %x",
9769 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009770 break;
9771 case AUDIO_PORT_TYPE_SESSION:
9772 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009773 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9774 ret = -EINVAL;
9775 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009776 }
9777
9778 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009779
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009780 // Generate patch info and update patch
9781 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009782 *handle = generate_patch_handle();
9783 p_info = (struct audio_patch_info *)
9784 calloc(1, sizeof(struct audio_patch_info));
9785 if (p_info == NULL) {
9786 ALOGE("%s: Failed to allocate memory", __func__);
9787 pthread_mutex_unlock(&adev->lock);
9788 ret = -ENOMEM;
9789 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009790 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009791 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009792 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009793 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009794 if (p_info == NULL) {
9795 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9796 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009797 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009798 ret = -EINVAL;
9799 goto done;
9800 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009801 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009802 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009803 *handle, p_info, patch_type, new_patch);
9804
9805 // Fetch stream info of associated mix for playback or capture patches
9806 if (p_info->patch_type == PATCH_PLAYBACK ||
9807 p_info->patch_type == PATCH_CAPTURE) {
9808 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9809 if (s_info == NULL) {
9810 ALOGE("%s: Failed to obtain stream info", __func__);
9811 if (new_patch)
9812 free(p_info);
9813 pthread_mutex_unlock(&adev->lock);
9814 ret = -EINVAL;
9815 goto done;
9816 }
9817 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9818 s_info->patch_handle = *handle;
9819 stream = s_info->stream;
9820 }
9821 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009822
9823 // Update routing for stream
9824 if (stream != NULL) {
9825 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009826 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009827 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009828 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009829 if (ret < 0) {
9830 pthread_mutex_lock(&adev->lock);
9831 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9832 if (new_patch)
9833 free(p_info);
9834 pthread_mutex_unlock(&adev->lock);
9835 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9836 goto done;
9837 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009838 }
9839
9840 // Add new patch to patch map
9841 if (!ret && new_patch) {
9842 pthread_mutex_lock(&adev->lock);
9843 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009844 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009845 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009846 }
9847
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009848done:
9849 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009850 num_sources,
9851 sources,
9852 num_sinks,
9853 sinks,
9854 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009855 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009856 num_sources,
9857 sources,
9858 num_sinks,
9859 sinks,
9860 handle);
9861 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309862}
9863
9864int adev_release_audio_patch(struct audio_hw_device *dev,
9865 audio_patch_handle_t handle)
9866{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009867 struct audio_device *adev = (struct audio_device *) dev;
9868 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009869 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009870 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009871
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009872 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9873 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9874 ret = -EINVAL;
9875 goto done;
9876 }
9877
9878 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009879 pthread_mutex_lock(&adev->lock);
9880 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009881 if (p_info == NULL) {
9882 ALOGE("%s: Patch info not found with 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;
9885 goto done;
9886 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009887 struct audio_patch *patch = p_info->patch;
9888 if (patch == NULL) {
9889 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009890 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009891 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009892 goto done;
9893 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009894 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9895 switch (patch->sources[0].type) {
9896 case AUDIO_PORT_TYPE_MIX:
9897 io_handle = patch->sources[0].ext.mix.handle;
9898 break;
9899 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009900 if (p_info->patch_type == PATCH_CAPTURE)
9901 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009902 break;
9903 case AUDIO_PORT_TYPE_SESSION:
9904 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009905 pthread_mutex_unlock(&adev->lock);
9906 ret = -EINVAL;
9907 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009908 }
9909
9910 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009911 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009912 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009913 if (patch_type == PATCH_PLAYBACK ||
9914 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009915 struct audio_stream_info *s_info =
9916 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9917 if (s_info == NULL) {
9918 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9919 pthread_mutex_unlock(&adev->lock);
9920 goto done;
9921 }
9922 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9923 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009924 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009925 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009926
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009927 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009928 struct listnode devices;
9929 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009930 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009931 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009932 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009933 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009934 }
9935
9936 if (ret < 0)
9937 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9938
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009939done:
9940 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9941 audio_extn_auto_hal_release_audio_patch(dev, handle);
9942
9943 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009944 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309945}
9946
9947int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9948{
Derek Chenf13dd492018-11-13 14:53:51 -08009949 int ret = 0;
9950
9951 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9952 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9953 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309954}
9955
9956int adev_set_audio_port_config(struct audio_hw_device *dev,
9957 const struct audio_port_config *config)
9958{
Derek Chenf13dd492018-11-13 14:53:51 -08009959 int ret = 0;
9960
9961 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9962 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9963 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309964}
9965
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009966static int adev_dump(const audio_hw_device_t *device __unused,
9967 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009968{
9969 return 0;
9970}
9971
9972static int adev_close(hw_device_t *device)
9973{
Aalique Grahame22e49102018-12-18 14:23:57 -08009974 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309975 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009976
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309977 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009978 return 0;
9979
9980 pthread_mutex_lock(&adev_init_lock);
9981
9982 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309983 if (audio_extn_spkr_prot_is_enabled())
9984 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309985 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309986 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009987 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009988 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009989 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009990 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309991 audio_extn_utils_release_streams_cfg_lists(
9992 &adev->streams_output_cfg_list,
9993 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309994 if (audio_extn_qap_is_enabled())
9995 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309996 if (audio_extn_qaf_is_enabled())
9997 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009998 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009999 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010000 free(adev->snd_dev_ref_cnt);
10001 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010002 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10003 pcm_params_free(adev->use_case_table[i]);
10004 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010005 if (adev->adm_deinit)
10006 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010007 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010008 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010009 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010010 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010011 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010012 if (adev->device_cfg_params) {
10013 free(adev->device_cfg_params);
10014 adev->device_cfg_params = NULL;
10015 }
Derek Chend2530072014-11-24 12:39:14 -080010016 if(adev->ext_hw_plugin)
10017 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010018 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010019 free_map(adev->patch_map);
10020 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010021 free(device);
10022 adev = NULL;
10023 }
10024 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010025 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010026 return 0;
10027}
10028
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010029/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10030 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10031 * just that it _might_ work.
10032 */
10033static int period_size_is_plausible_for_low_latency(int period_size)
10034{
10035 switch (period_size) {
10036 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010037 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010038 case 240:
10039 case 320:
10040 case 480:
10041 return 1;
10042 default:
10043 return 0;
10044 }
10045}
10046
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010047static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10048{
10049 bool is_snd_card_status = false;
10050 bool is_ext_device_status = false;
10051 char value[32];
10052 int card = -1;
10053 card_status_t status;
10054
10055 if (cookie != adev || !parms)
10056 return;
10057
10058 if (!parse_snd_card_status(parms, &card, &status)) {
10059 is_snd_card_status = true;
10060 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10061 is_ext_device_status = true;
10062 } else {
10063 // not a valid event
10064 return;
10065 }
10066
10067 pthread_mutex_lock(&adev->lock);
10068 if (card == adev->snd_card || is_ext_device_status) {
10069 if (is_snd_card_status && adev->card_status != status) {
10070 adev->card_status = status;
10071 platform_snd_card_update(adev->platform, status);
10072 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010073 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010074 if (status == CARD_STATUS_OFFLINE)
10075 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010076 } else if (is_ext_device_status) {
10077 platform_set_parameters(adev->platform, parms);
10078 }
10079 }
10080 pthread_mutex_unlock(&adev->lock);
10081 return;
10082}
10083
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010084/* out and adev lock held */
10085static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10086{
10087 struct audio_usecase *uc_info;
10088 float left_p;
10089 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010090 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010091
10092 uc_info = get_usecase_from_list(adev, out->usecase);
10093 if (uc_info == NULL) {
10094 ALOGE("%s: Could not find the usecase (%d) in the list",
10095 __func__, out->usecase);
10096 return -EINVAL;
10097 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010098 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010099
10100 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10101 out->usecase, use_case_table[out->usecase]);
10102
10103 if (restore) {
10104 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010105 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010106 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010107 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10108 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010109 pthread_mutex_lock(&out->compr_mute_lock);
10110 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010111 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010112 out->a2dp_compress_mute = false;
10113 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10114 }
10115 pthread_mutex_unlock(&out->compr_mute_lock);
10116 }
10117 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010118 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10119 // mute compress stream if suspended
10120 pthread_mutex_lock(&out->compr_mute_lock);
10121 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010122 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010123 assign_devices(&devices, &out->device_list);
10124 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010125 left_p = out->volume_l;
10126 right_p = out->volume_r;
10127 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10128 compress_pause(out->compr);
10129 out_set_compr_volume(&out->stream, (float)0, (float)0);
10130 out->a2dp_compress_mute = true;
10131 select_devices(adev, out->usecase);
10132 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10133 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010134 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010135 out->volume_l = left_p;
10136 out->volume_r = right_p;
10137 }
Zhou Songc576a452019-09-09 14:17:40 +080010138 pthread_mutex_unlock(&out->compr_mute_lock);
10139 } else {
10140 // tear down a2dp path for non offloaded streams
10141 if (audio_extn_a2dp_source_is_suspended())
10142 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010143 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010144 }
10145 ALOGV("%s: exit", __func__);
10146 return 0;
10147}
10148
10149int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10150{
10151 int ret = 0;
10152
10153 lock_output_stream(out);
10154 pthread_mutex_lock(&adev->lock);
10155
10156 ret = check_a2dp_restore_l(adev, out, restore);
10157
10158 pthread_mutex_unlock(&adev->lock);
10159 pthread_mutex_unlock(&out->lock);
10160 return ret;
10161}
10162
Haynes Mathew George01156f92018-04-13 15:29:54 -070010163void adev_on_battery_status_changed(bool charging)
10164{
10165 pthread_mutex_lock(&adev->lock);
10166 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10167 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010168 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010169 pthread_mutex_unlock(&adev->lock);
10170}
10171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010172static int adev_open(const hw_module_t *module, const char *name,
10173 hw_device_t **device)
10174{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010175 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010176 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010177 char mixer_ctl_name[128] = {0};
10178 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010179
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010180 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010181 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10182
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010183 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010184 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010185 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010186 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010187 ALOGD("%s: returning existing instance of adev", __func__);
10188 ALOGD("%s: exit", __func__);
10189 pthread_mutex_unlock(&adev_init_lock);
10190 return 0;
10191 }
10192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010193 adev = calloc(1, sizeof(struct audio_device));
10194
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010195 if (!adev) {
10196 pthread_mutex_unlock(&adev_init_lock);
10197 return -ENOMEM;
10198 }
10199
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010200 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10201
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010202 // register audio ext hidl at the earliest
10203 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010204#ifdef DYNAMIC_LOG_ENABLED
10205 register_for_dynamic_logging("hal");
10206#endif
10207
Derek Chenf939fb72018-11-13 13:34:41 -080010208 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010209 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010210 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10211 maj_version = atoi(value);
10212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010213 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010214 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010215 adev->device.common.module = (struct hw_module_t *)module;
10216 adev->device.common.close = adev_close;
10217
10218 adev->device.init_check = adev_init_check;
10219 adev->device.set_voice_volume = adev_set_voice_volume;
10220 adev->device.set_master_volume = adev_set_master_volume;
10221 adev->device.get_master_volume = adev_get_master_volume;
10222 adev->device.set_master_mute = adev_set_master_mute;
10223 adev->device.get_master_mute = adev_get_master_mute;
10224 adev->device.set_mode = adev_set_mode;
10225 adev->device.set_mic_mute = adev_set_mic_mute;
10226 adev->device.get_mic_mute = adev_get_mic_mute;
10227 adev->device.set_parameters = adev_set_parameters;
10228 adev->device.get_parameters = adev_get_parameters;
10229 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10230 adev->device.open_output_stream = adev_open_output_stream;
10231 adev->device.close_output_stream = adev_close_output_stream;
10232 adev->device.open_input_stream = adev_open_input_stream;
10233 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010234 adev->device.create_audio_patch = adev_create_audio_patch;
10235 adev->device.release_audio_patch = adev_release_audio_patch;
10236 adev->device.get_audio_port = adev_get_audio_port;
10237 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010238 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010239 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010240
10241 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010242 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010243 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010244 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010245 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010246 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010247 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010248 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010249 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010250 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010251 /* Init audio and voice feature */
10252 audio_extn_feature_init();
10253 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010254 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010255 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010256 list_init(&adev->active_inputs_list);
10257 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010258 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010259 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10260 audio_extn_utils_hash_eq);
10261 if (!adev->io_streams_map) {
10262 ALOGE("%s: Could not create io streams map", __func__);
10263 ret = -ENOMEM;
10264 goto adev_open_err;
10265 }
10266 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10267 audio_extn_utils_hash_eq);
10268 if (!adev->patch_map) {
10269 ALOGE("%s: Could not create audio patch map", __func__);
10270 ret = -ENOMEM;
10271 goto adev_open_err;
10272 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010273 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010274 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010275 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010276 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010277 adev->perf_lock_opts[0] = 0x101;
10278 adev->perf_lock_opts[1] = 0x20E;
10279 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010280 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010281 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010282 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010283 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010285 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010286 adev->platform = platform_init(adev);
10287 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010288 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010289 ret = -EINVAL;
10290 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010291 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010292
Aalique Grahame22e49102018-12-18 14:23:57 -080010293 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010294 if (audio_extn_qap_is_enabled()) {
10295 ret = audio_extn_qap_init(adev);
10296 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010297 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010298 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010299 }
10300 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10301 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10302 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010303
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010304 if (audio_extn_qaf_is_enabled()) {
10305 ret = audio_extn_qaf_init(adev);
10306 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010307 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010308 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010309 }
10310
10311 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10312 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10313 }
10314
Derek Chenae7b0342019-02-08 15:17:04 -080010315 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010316 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10317
Eric Laurentc4aef752013-09-12 17:45:53 -070010318 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10319 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10320 if (adev->visualizer_lib == NULL) {
10321 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10322 } else {
10323 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10324 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010325 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010326 "visualizer_hal_start_output");
10327 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010328 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010329 "visualizer_hal_stop_output");
10330 }
10331 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010332 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010333 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010334 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010335 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010336 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010337 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010338
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010339 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10340 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10341 if (adev->offload_effects_lib == NULL) {
10342 ALOGE("%s: DLOPEN failed for %s", __func__,
10343 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10344 } else {
10345 ALOGV("%s: DLOPEN successful for %s", __func__,
10346 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10347 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010348 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010349 "offload_effects_bundle_hal_start_output");
10350 adev->offload_effects_stop_output =
10351 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10352 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010353 adev->offload_effects_set_hpx_state =
10354 (int (*)(bool))dlsym(adev->offload_effects_lib,
10355 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010356 adev->offload_effects_get_parameters =
10357 (void (*)(struct str_parms *, struct str_parms *))
10358 dlsym(adev->offload_effects_lib,
10359 "offload_effects_bundle_get_parameters");
10360 adev->offload_effects_set_parameters =
10361 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10362 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010363 }
10364 }
10365
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010366 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10367 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10368 if (adev->adm_lib == NULL) {
10369 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10370 } else {
10371 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10372 adev->adm_init = (adm_init_t)
10373 dlsym(adev->adm_lib, "adm_init");
10374 adev->adm_deinit = (adm_deinit_t)
10375 dlsym(adev->adm_lib, "adm_deinit");
10376 adev->adm_register_input_stream = (adm_register_input_stream_t)
10377 dlsym(adev->adm_lib, "adm_register_input_stream");
10378 adev->adm_register_output_stream = (adm_register_output_stream_t)
10379 dlsym(adev->adm_lib, "adm_register_output_stream");
10380 adev->adm_deregister_stream = (adm_deregister_stream_t)
10381 dlsym(adev->adm_lib, "adm_deregister_stream");
10382 adev->adm_request_focus = (adm_request_focus_t)
10383 dlsym(adev->adm_lib, "adm_request_focus");
10384 adev->adm_abandon_focus = (adm_abandon_focus_t)
10385 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010386 adev->adm_set_config = (adm_set_config_t)
10387 dlsym(adev->adm_lib, "adm_set_config");
10388 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10389 dlsym(adev->adm_lib, "adm_request_focus_v2");
10390 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10391 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10392 adev->adm_on_routing_change = (adm_on_routing_change_t)
10393 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010394 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10395 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010396 }
10397 }
10398
Aalique Grahame22e49102018-12-18 14:23:57 -080010399 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010400 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010401 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010402 //initialize this to false for now,
10403 //this will be set to true through set param
10404 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010405
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010406 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010407 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010408
10409 if (k_enable_extended_precision)
10410 adev_verify_devices(adev);
10411
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010412 adev->dsp_bit_width_enforce_mode =
10413 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010414
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010415 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10416 &adev->streams_output_cfg_list,
10417 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010418
Kiran Kandi910e1862013-10-29 13:29:42 -070010419 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010420
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010421 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010422 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010423 trial = atoi(value);
10424 if (period_size_is_plausible_for_low_latency(trial)) {
10425 pcm_config_low_latency.period_size = trial;
10426 pcm_config_low_latency.start_threshold = trial / 4;
10427 pcm_config_low_latency.avail_min = trial / 4;
10428 configured_low_latency_capture_period_size = trial;
10429 }
10430 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010431 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10432 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010433 trial = atoi(value);
10434 if (period_size_is_plausible_for_low_latency(trial)) {
10435 configured_low_latency_capture_period_size = trial;
10436 }
10437 }
10438
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010439 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10440
Eric Laurent4b084132018-10-19 17:33:43 -070010441 adev->camera_orientation = CAMERA_DEFAULT;
10442
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010443 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010444 af_period_multiplier = atoi(value);
10445 if (af_period_multiplier < 0)
10446 af_period_multiplier = 2;
10447 else if (af_period_multiplier > 4)
10448 af_period_multiplier = 4;
10449
10450 ALOGV("new period_multiplier = %d", af_period_multiplier);
10451 }
10452
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010453 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010454
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010455 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010456 pthread_mutex_unlock(&adev_init_lock);
10457
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010458 if (adev->adm_init)
10459 adev->adm_data = adev->adm_init();
10460
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010461 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010462 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010463 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010464
10465 audio_extn_snd_mon_init();
10466 pthread_mutex_lock(&adev->lock);
10467 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10468 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010469 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10470 /*
10471 * if the battery state callback happens before charging can be queried,
10472 * it will be guarded with the adev->lock held in the cb function and so
10473 * the callback value will reflect the latest state
10474 */
10475 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010476 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010477 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010478 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010479 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010480 /* Allocate memory for Device config params */
10481 adev->device_cfg_params = (struct audio_device_config_param*)
10482 calloc(platform_get_max_codec_backend(),
10483 sizeof(struct audio_device_config_param));
10484 if (adev->device_cfg_params == NULL)
10485 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010486
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010487 /*
10488 * Check if new PSPD matrix mixer control is supported. If not
10489 * supported, then set flag so that old mixer ctrl is sent while
10490 * sending pspd coefficients on older kernel version. Query mixer
10491 * control for default pcm id and channel value one.
10492 */
10493 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10494 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10495
10496 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10497 if (!ctl) {
10498 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10499 __func__, mixer_ctl_name);
10500 adev->use_old_pspd_mix_ctrl = true;
10501 }
10502
Eric Laurent994a6932013-07-17 11:51:42 -070010503 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010504 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010505
10506adev_open_err:
10507 free_map(adev->patch_map);
10508 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010509 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010510 pthread_mutex_destroy(&adev->lock);
10511 free(adev);
10512 adev = NULL;
10513 *device = NULL;
10514 pthread_mutex_unlock(&adev_init_lock);
10515 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010516}
10517
10518static struct hw_module_methods_t hal_module_methods = {
10519 .open = adev_open,
10520};
10521
10522struct audio_module HAL_MODULE_INFO_SYM = {
10523 .common = {
10524 .tag = HARDWARE_MODULE_TAG,
10525 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10526 .hal_api_version = HARDWARE_HAL_API_VERSION,
10527 .id = AUDIO_HARDWARE_MODULE_ID,
10528 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010529 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010530 .methods = &hal_module_methods,
10531 },
10532};