blob: fc75fd176f7e423b503104e33eeb12d63abab650 [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);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306187 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006188 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006189 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306190 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306191 status = compress_pause(out->compr);
6192
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006193 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006194
Mingming Yin21854652016-04-13 11:54:02 -07006195 if (audio_extn_passthru_is_active()) {
6196 ALOGV("offload use case, pause passthru");
6197 audio_extn_passthru_on_pause(out);
6198 }
6199
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306200 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006201 audio_extn_dts_notify_playback_state(out->usecase, 0,
6202 out->sample_rate, popcount(out->channel_mask),
6203 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006204 }
6205 pthread_mutex_unlock(&out->lock);
6206 }
6207 return status;
6208}
6209
6210static int out_resume(struct audio_stream_out* stream)
6211{
6212 struct stream_out *out = (struct stream_out *)stream;
6213 int status = -ENOSYS;
6214 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006215 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006216 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306217 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006218 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006219 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306220 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306221 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006222 }
6223 if (!status) {
6224 out->offload_state = OFFLOAD_STATE_PLAYING;
6225 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306226 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006227 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6228 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006229 }
6230 pthread_mutex_unlock(&out->lock);
6231 }
6232 return status;
6233}
6234
6235static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6236{
6237 struct stream_out *out = (struct stream_out *)stream;
6238 int status = -ENOSYS;
6239 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006240 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006241 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006242 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6243 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6244 else
6245 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6246 pthread_mutex_unlock(&out->lock);
6247 }
6248 return status;
6249}
6250
6251static int out_flush(struct audio_stream_out* stream)
6252{
6253 struct stream_out *out = (struct stream_out *)stream;
6254 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006255 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006256 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006257 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006258 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6259 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006260 } else {
6261 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6262 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006263 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006264 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006265 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006266 return 0;
6267 }
6268 return -ENOSYS;
6269}
6270
Haynes Mathew George16081042017-05-31 17:16:49 -07006271static int out_stop(const struct audio_stream_out* stream)
6272{
6273 struct stream_out *out = (struct stream_out *)stream;
6274 struct audio_device *adev = out->dev;
6275 int ret = -ENOSYS;
6276
6277 ALOGV("%s", __func__);
6278 pthread_mutex_lock(&adev->lock);
6279 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6280 out->playback_started && out->pcm != NULL) {
6281 pcm_stop(out->pcm);
6282 ret = stop_output_stream(out);
6283 out->playback_started = false;
6284 }
6285 pthread_mutex_unlock(&adev->lock);
6286 return ret;
6287}
6288
6289static int out_start(const struct audio_stream_out* stream)
6290{
6291 struct stream_out *out = (struct stream_out *)stream;
6292 struct audio_device *adev = out->dev;
6293 int ret = -ENOSYS;
6294
6295 ALOGV("%s", __func__);
6296 pthread_mutex_lock(&adev->lock);
6297 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6298 !out->playback_started && out->pcm != NULL) {
6299 ret = start_output_stream(out);
6300 if (ret == 0) {
6301 out->playback_started = true;
6302 }
6303 }
6304 pthread_mutex_unlock(&adev->lock);
6305 return ret;
6306}
6307
6308/*
6309 * Modify config->period_count based on min_size_frames
6310 */
6311static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6312{
6313 int periodCountRequested = (min_size_frames + config->period_size - 1)
6314 / config->period_size;
6315 int periodCount = MMAP_PERIOD_COUNT_MIN;
6316
6317 ALOGV("%s original config.period_size = %d config.period_count = %d",
6318 __func__, config->period_size, config->period_count);
6319
6320 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6321 periodCount *= 2;
6322 }
6323 config->period_count = periodCount;
6324
6325 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6326}
6327
Phil Burkfe17efd2019-03-25 10:23:35 -07006328// Read offset for the positional timestamp from a persistent vendor property.
6329// This is to workaround apparent inaccuracies in the timing information that
6330// is used by the AAudio timing model. The inaccuracies can cause glitches.
6331static int64_t get_mmap_out_time_offset() {
6332 const int32_t kDefaultOffsetMicros = 0;
6333 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006334 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006335 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6336 return mmap_time_offset_micros * (int64_t)1000;
6337}
6338
Haynes Mathew George16081042017-05-31 17:16:49 -07006339static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6340 int32_t min_size_frames,
6341 struct audio_mmap_buffer_info *info)
6342{
6343 struct stream_out *out = (struct stream_out *)stream;
6344 struct audio_device *adev = out->dev;
6345 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006346 unsigned int offset1 = 0;
6347 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006348 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006349 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006350 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006351
Arun Mirpuri5d170872019-03-26 13:21:31 -07006352 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306353 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006354 pthread_mutex_lock(&adev->lock);
6355
Sharad Sanglec6f32552018-05-04 16:15:38 +05306356 if (CARD_STATUS_OFFLINE == out->card_status ||
6357 CARD_STATUS_OFFLINE == adev->card_status) {
6358 ALOGW("out->card_status or adev->card_status offline, try again");
6359 ret = -EIO;
6360 goto exit;
6361 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306362 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006363 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6364 ret = -EINVAL;
6365 goto exit;
6366 }
6367 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6368 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6369 ret = -ENOSYS;
6370 goto exit;
6371 }
6372 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6373 if (out->pcm_device_id < 0) {
6374 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6375 __func__, out->pcm_device_id, out->usecase);
6376 ret = -EINVAL;
6377 goto exit;
6378 }
6379
6380 adjust_mmap_period_count(&out->config, min_size_frames);
6381
Arun Mirpuri5d170872019-03-26 13:21:31 -07006382 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006383 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6384 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6385 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306386 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306387 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6388 out->card_status = CARD_STATUS_OFFLINE;
6389 adev->card_status = CARD_STATUS_OFFLINE;
6390 ret = -EIO;
6391 goto exit;
6392 }
6393
Haynes Mathew George16081042017-05-31 17:16:49 -07006394 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6395 step = "open";
6396 ret = -ENODEV;
6397 goto exit;
6398 }
6399 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6400 if (ret < 0) {
6401 step = "begin";
6402 goto exit;
6403 }
juyuchen626833d2019-06-04 16:48:02 +08006404
6405 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006406 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006407 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006408 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006409 ret = platform_get_mmap_data_fd(adev->platform,
6410 out->pcm_device_id, 0 /*playback*/,
6411 &info->shared_memory_fd,
6412 &mmap_size);
6413 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006414 // Fall back to non exclusive mode
6415 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6416 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006417 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6418 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6419
Arun Mirpuri5d170872019-03-26 13:21:31 -07006420 if (mmap_size < buffer_size) {
6421 step = "mmap";
6422 goto exit;
6423 }
juyuchen626833d2019-06-04 16:48:02 +08006424 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006425 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006426 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006427 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006428
6429 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6430 if (ret < 0) {
6431 step = "commit";
6432 goto exit;
6433 }
6434
Phil Burkfe17efd2019-03-25 10:23:35 -07006435 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6436
Haynes Mathew George16081042017-05-31 17:16:49 -07006437 out->standby = false;
6438 ret = 0;
6439
Arun Mirpuri5d170872019-03-26 13:21:31 -07006440 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006441 __func__, info->shared_memory_address, info->buffer_size_frames);
6442
6443exit:
6444 if (ret != 0) {
6445 if (out->pcm == NULL) {
6446 ALOGE("%s: %s - %d", __func__, step, ret);
6447 } else {
6448 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6449 pcm_close(out->pcm);
6450 out->pcm = NULL;
6451 }
6452 }
6453 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306454 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006455 return ret;
6456}
6457
6458static int out_get_mmap_position(const struct audio_stream_out *stream,
6459 struct audio_mmap_position *position)
6460{
6461 struct stream_out *out = (struct stream_out *)stream;
6462 ALOGVV("%s", __func__);
6463 if (position == NULL) {
6464 return -EINVAL;
6465 }
6466 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006467 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006468 return -ENOSYS;
6469 }
6470 if (out->pcm == NULL) {
6471 return -ENOSYS;
6472 }
6473
6474 struct timespec ts = { 0, 0 };
6475 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6476 if (ret < 0) {
6477 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6478 return ret;
6479 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006480 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6481 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006482 return 0;
6483}
6484
6485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006486/** audio_stream_in implementation **/
6487static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6488{
6489 struct stream_in *in = (struct stream_in *)stream;
6490
6491 return in->config.rate;
6492}
6493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006494static int in_set_sample_rate(struct audio_stream *stream __unused,
6495 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006496{
6497 return -ENOSYS;
6498}
6499
6500static size_t in_get_buffer_size(const struct audio_stream *stream)
6501{
6502 struct stream_in *in = (struct stream_in *)stream;
6503
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006504 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6505 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006506 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6507 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306508 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306509 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006510
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006511 return in->config.period_size * in->af_period_multiplier *
6512 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006513}
6514
6515static uint32_t in_get_channels(const struct audio_stream *stream)
6516{
6517 struct stream_in *in = (struct stream_in *)stream;
6518
6519 return in->channel_mask;
6520}
6521
6522static audio_format_t in_get_format(const struct audio_stream *stream)
6523{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006524 struct stream_in *in = (struct stream_in *)stream;
6525
6526 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006527}
6528
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006529static int in_set_format(struct audio_stream *stream __unused,
6530 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006531{
6532 return -ENOSYS;
6533}
6534
6535static int in_standby(struct audio_stream *stream)
6536{
6537 struct stream_in *in = (struct stream_in *)stream;
6538 struct audio_device *adev = in->dev;
6539 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306540 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6541 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006542 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306543
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006544 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006545 if (!in->standby && in->is_st_session) {
6546 ALOGD("%s: sound trigger pcm stop lab", __func__);
6547 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006548 if (adev->num_va_sessions > 0)
6549 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006550 in->standby = 1;
6551 }
6552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006553 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006554 if (adev->adm_deregister_stream)
6555 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6556
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006557 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006558 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006559 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006560 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006561 voice_extn_compress_voip_close_input_stream(stream);
6562 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006563 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6564 do_stop = in->capture_started;
6565 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006566 if (in->mmap_shared_memory_fd >= 0) {
6567 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6568 __func__, in->mmap_shared_memory_fd);
6569 close(in->mmap_shared_memory_fd);
6570 in->mmap_shared_memory_fd = -1;
6571 }
Zhou Songa8895042016-07-05 17:54:22 +08006572 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306573 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306574 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006575 }
6576
Arun Mirpuri5d170872019-03-26 13:21:31 -07006577 if (in->pcm) {
6578 ATRACE_BEGIN("pcm_in_close");
6579 pcm_close(in->pcm);
6580 ATRACE_END();
6581 in->pcm = NULL;
6582 }
6583
Carter Hsu2e429db2019-05-14 18:50:52 +08006584 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006585 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006586
George Gao3018ede2019-10-23 13:23:00 -07006587 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6588 if (adev->num_va_sessions > 0)
6589 adev->num_va_sessions--;
6590 }
Quinn Malef6050362019-01-30 15:55:40 -08006591
Eric Laurent150dbfe2013-02-27 14:31:02 -08006592 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006593 }
6594 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006595 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006596 return status;
6597}
6598
Aalique Grahame22e49102018-12-18 14:23:57 -08006599static int in_dump(const struct audio_stream *stream,
6600 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006601{
Aalique Grahame22e49102018-12-18 14:23:57 -08006602 struct stream_in *in = (struct stream_in *)stream;
6603
6604 // We try to get the lock for consistency,
6605 // but it isn't necessary for these variables.
6606 // If we're not in standby, we may be blocked on a read.
6607 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6608 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6609 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6610 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6611
6612 if (locked) {
6613 pthread_mutex_unlock(&in->lock);
6614 }
6615
6616 // dump error info
6617 (void)error_log_dump(
6618 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006620 return 0;
6621}
6622
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306623static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6624{
6625 if (!stream || !parms)
6626 return;
6627
6628 struct stream_in *in = (struct stream_in *)stream;
6629 struct audio_device *adev = in->dev;
6630
6631 card_status_t status;
6632 int card;
6633 if (parse_snd_card_status(parms, &card, &status) < 0)
6634 return;
6635
6636 pthread_mutex_lock(&adev->lock);
6637 bool valid_cb = (card == adev->snd_card);
6638 pthread_mutex_unlock(&adev->lock);
6639
6640 if (!valid_cb)
6641 return;
6642
6643 lock_input_stream(in);
6644 if (in->card_status != status)
6645 in->card_status = status;
6646 pthread_mutex_unlock(&in->lock);
6647
6648 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6649 use_case_table[in->usecase],
6650 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6651
6652 // a better solution would be to report error back to AF and let
6653 // it put the stream to standby
6654 if (status == CARD_STATUS_OFFLINE)
6655 in_standby(&in->stream.common);
6656
6657 return;
6658}
6659
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006660int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006661 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006662 audio_source_t source)
6663{
6664 struct audio_device *adev = in->dev;
6665 int ret = 0;
6666
6667 lock_input_stream(in);
6668 pthread_mutex_lock(&adev->lock);
6669
6670 /* no audio source uses val == 0 */
6671 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6672 in->source = source;
6673 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6674 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6675 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6676 (in->config.rate == 8000 || in->config.rate == 16000 ||
6677 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6678 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6679 ret = voice_extn_compress_voip_open_input_stream(in);
6680 if (ret != 0) {
6681 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6682 __func__, ret);
6683 }
6684 }
6685 }
6686
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006687 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6688 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006689 // Workaround: If routing to an non existing usb device, fail gracefully
6690 // The routing request will otherwise block during 10 second
6691 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006692 struct str_parms *usb_addr =
6693 str_parms_create_str(get_usb_device_address(devices));
6694 if (is_usb_in_device_type(devices) && usb_addr &&
6695 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006696 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6697 ret = -ENOSYS;
6698 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006699 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006700 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006701 if (!in->standby && !in->is_st_session) {
6702 ALOGV("update input routing change");
6703 // inform adm before actual routing to prevent glitches.
6704 if (adev->adm_on_routing_change) {
6705 adev->adm_on_routing_change(adev->adm_data,
6706 in->capture_handle);
6707 ret = select_devices(adev, in->usecase);
6708 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6709 adev->adm_routing_changed = true;
6710 }
6711 }
6712 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006713 if (usb_addr)
6714 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006715 }
6716 pthread_mutex_unlock(&adev->lock);
6717 pthread_mutex_unlock(&in->lock);
6718
6719 ALOGD("%s: exit: status(%d)", __func__, ret);
6720 return ret;
6721}
6722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6724{
6725 struct stream_in *in = (struct stream_in *)stream;
6726 struct audio_device *adev = in->dev;
6727 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306729 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006730
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306731 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006732 parms = str_parms_create_str(kvpairs);
6733
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306734 if (!parms)
6735 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006736 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006737 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006738
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306739 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6740 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306741 strlcpy(in->profile, value, sizeof(in->profile));
6742 ALOGV("updating stream profile with value '%s'", in->profile);
6743 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6744 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006745 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306746 in->sample_rate, in->bit_width,
6747 in->profile, &in->app_type_cfg);
6748 }
6749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006750 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006751 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006752
6753 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306754error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306755 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006756}
6757
6758static char* in_get_parameters(const struct audio_stream *stream,
6759 const char *keys)
6760{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006761 struct stream_in *in = (struct stream_in *)stream;
6762 struct str_parms *query = str_parms_create_str(keys);
6763 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006764 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006765
6766 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006767 if (reply) {
6768 str_parms_destroy(reply);
6769 }
6770 if (query) {
6771 str_parms_destroy(query);
6772 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006773 ALOGE("in_get_parameters: failed to create query or reply");
6774 return NULL;
6775 }
6776
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006777 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006778
6779 voice_extn_in_get_parameters(in, query, reply);
6780
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006781 stream_get_parameter_channels(query, reply,
6782 &in->supported_channel_masks[0]);
6783 stream_get_parameter_formats(query, reply,
6784 &in->supported_formats[0]);
6785 stream_get_parameter_rates(query, reply,
6786 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006787 str = str_parms_to_str(reply);
6788 str_parms_destroy(query);
6789 str_parms_destroy(reply);
6790
6791 ALOGV("%s: exit: returns - %s", __func__, str);
6792 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006793}
6794
Aalique Grahame22e49102018-12-18 14:23:57 -08006795static int in_set_gain(struct audio_stream_in *stream,
6796 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006797{
Aalique Grahame22e49102018-12-18 14:23:57 -08006798 struct stream_in *in = (struct stream_in *)stream;
6799 char mixer_ctl_name[128];
6800 struct mixer_ctl *ctl;
6801 int ctl_value;
6802
6803 ALOGV("%s: gain %f", __func__, gain);
6804
6805 if (stream == NULL)
6806 return -EINVAL;
6807
6808 /* in_set_gain() only used to silence MMAP capture for now */
6809 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6810 return -ENOSYS;
6811
6812 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6813
6814 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6815 if (!ctl) {
6816 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6817 __func__, mixer_ctl_name);
6818 return -ENOSYS;
6819 }
6820
6821 if (gain < RECORD_GAIN_MIN)
6822 gain = RECORD_GAIN_MIN;
6823 else if (gain > RECORD_GAIN_MAX)
6824 gain = RECORD_GAIN_MAX;
6825 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6826
6827 mixer_ctl_set_value(ctl, 0, ctl_value);
6828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006829 return 0;
6830}
6831
6832static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6833 size_t bytes)
6834{
6835 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306836
6837 if (in == NULL) {
6838 ALOGE("%s: stream_in ptr is NULL", __func__);
6839 return -EINVAL;
6840 }
6841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006842 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306843 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306844 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006845
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006846 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306847
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006848 if (in->is_st_session) {
6849 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6850 /* Read from sound trigger HAL */
6851 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006852 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006853 if (adev->num_va_sessions < UINT_MAX)
6854 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006855 in->standby = 0;
6856 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006857 pthread_mutex_unlock(&in->lock);
6858 return bytes;
6859 }
6860
Haynes Mathew George16081042017-05-31 17:16:49 -07006861 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6862 ret = -ENOSYS;
6863 goto exit;
6864 }
6865
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006866 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6867 !in->standby && adev->adm_routing_changed) {
6868 ret = -ENOSYS;
6869 goto exit;
6870 }
6871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006873 pthread_mutex_lock(&adev->lock);
6874 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6875 ret = voice_extn_compress_voip_start_input_stream(in);
6876 else
6877 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006878 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6879 if (adev->num_va_sessions < UINT_MAX)
6880 adev->num_va_sessions++;
6881 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006882 pthread_mutex_unlock(&adev->lock);
6883 if (ret != 0) {
6884 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006885 }
6886 in->standby = 0;
6887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006888
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306889 /* Avoid read if capture_stopped is set */
6890 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6891 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6892 ret = -EINVAL;
6893 goto exit;
6894 }
6895
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006896 // what's the duration requested by the client?
6897 long ns = 0;
6898
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306899 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006900 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6901 in->config.rate;
6902
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006903 ret = request_in_focus(in, ns);
6904 if (ret != 0)
6905 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006906 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006907
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306908 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306909 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6910 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306911 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006912 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306913 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006914 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006915 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006916 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006917 } else if (audio_extn_ffv_get_stream() == in) {
6918 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306919 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006920 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306921 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6922 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6923 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6924 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306925 ret = -EINVAL;
6926 goto exit;
6927 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306928 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306929 ret = -errno;
6930 }
6931 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306932 /* bytes read is always set to bytes for non compress usecases */
6933 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006934 }
6935
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006936 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006938 /*
Quinn Malef6050362019-01-30 15:55:40 -08006939 * Instead of writing zeroes here, we could trust the hardware to always
6940 * provide zeroes when muted. This is also muted with voice recognition
6941 * usecases so that other clients do not have access to voice recognition
6942 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943 */
Quinn Malef6050362019-01-30 15:55:40 -08006944 if ((ret == 0 && voice_get_mic_mute(adev) &&
6945 !voice_is_in_call_rec_stream(in) &&
6946 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6947 (adev->num_va_sessions &&
6948 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6949 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6950 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951 memset(buffer, 0, bytes);
6952
6953exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306954 frame_size = audio_stream_in_frame_size(stream);
6955 if (frame_size > 0)
6956 in->frames_read += bytes_read/frame_size;
6957
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006958 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306959 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006960 pthread_mutex_unlock(&in->lock);
6961
6962 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306963 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306964 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306965 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306966 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306967 in->standby = true;
6968 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306969 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05306970 bytes_read = bytes;
6971 memset(buffer, 0, bytes);
6972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006974 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6975 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006976 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306977 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306978 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006979 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306980 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006981}
6982
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006983static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006984{
6985 return 0;
6986}
6987
Aalique Grahame22e49102018-12-18 14:23:57 -08006988static int in_get_capture_position(const struct audio_stream_in *stream,
6989 int64_t *frames, int64_t *time)
6990{
6991 if (stream == NULL || frames == NULL || time == NULL) {
6992 return -EINVAL;
6993 }
6994 struct stream_in *in = (struct stream_in *)stream;
6995 int ret = -ENOSYS;
6996
6997 lock_input_stream(in);
6998 // note: ST sessions do not close the alsa pcm driver synchronously
6999 // on standby. Therefore, we may return an error even though the
7000 // pcm stream is still opened.
7001 if (in->standby) {
7002 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7003 "%s stream in standby but pcm not NULL for non ST session", __func__);
7004 goto exit;
7005 }
7006 if (in->pcm) {
7007 struct timespec timestamp;
7008 unsigned int avail;
7009 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7010 *frames = in->frames_read + avail;
7011 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7012 ret = 0;
7013 }
7014 }
7015exit:
7016 pthread_mutex_unlock(&in->lock);
7017 return ret;
7018}
7019
Carter Hsu2e429db2019-05-14 18:50:52 +08007020static int in_update_effect_list(bool add, effect_handle_t effect,
7021 struct listnode *head)
7022{
7023 struct listnode *node;
7024 struct in_effect_list *elist = NULL;
7025 struct in_effect_list *target = NULL;
7026 int ret = 0;
7027
7028 if (!head)
7029 return ret;
7030
7031 list_for_each(node, head) {
7032 elist = node_to_item(node, struct in_effect_list, list);
7033 if (elist->handle == effect) {
7034 target = elist;
7035 break;
7036 }
7037 }
7038
7039 if (add) {
7040 if (target) {
7041 ALOGD("effect %p already exist", effect);
7042 return ret;
7043 }
7044
7045 target = (struct in_effect_list *)
7046 calloc(1, sizeof(struct in_effect_list));
7047
7048 if (!target) {
7049 ALOGE("%s:fail to allocate memory", __func__);
7050 return -ENOMEM;
7051 }
7052
7053 target->handle = effect;
7054 list_add_tail(head, &target->list);
7055 } else {
7056 if (target) {
7057 list_remove(&target->list);
7058 free(target);
7059 }
7060 }
7061
7062 return ret;
7063}
7064
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007065static int add_remove_audio_effect(const struct audio_stream *stream,
7066 effect_handle_t effect,
7067 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007068{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007069 struct stream_in *in = (struct stream_in *)stream;
7070 int status = 0;
7071 effect_descriptor_t desc;
7072
7073 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007074 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7075
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007076 if (status != 0)
7077 return status;
7078
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007079 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007080 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007081 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007082 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7083 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007084 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007085
7086 in_update_effect_list(enable, effect, &in->aec_list);
7087 enable = !list_empty(&in->aec_list);
7088 if (enable == in->enable_aec)
7089 goto exit;
7090
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007091 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007092 ALOGD("AEC enable %d", enable);
7093
Aalique Grahame22e49102018-12-18 14:23:57 -08007094 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7095 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7096 in->dev->enable_voicerx = enable;
7097 struct audio_usecase *usecase;
7098 struct listnode *node;
7099 list_for_each(node, &in->dev->usecase_list) {
7100 usecase = node_to_item(node, struct audio_usecase, list);
7101 if (usecase->type == PCM_PLAYBACK)
7102 select_devices(in->dev, usecase->id);
7103 }
7104 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007105 if (!in->standby) {
7106 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7107 select_devices(in->dev, in->usecase);
7108 }
7109
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007110 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007111 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7112
7113 in_update_effect_list(enable, effect, &in->ns_list);
7114 enable = !list_empty(&in->ns_list);
7115 if (enable == in->enable_ns)
7116 goto exit;
7117
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007118 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007119 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007120 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007121 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7122 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007123 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7124 select_devices(in->dev, in->usecase);
7125 } else
7126 select_devices(in->dev, in->usecase);
7127 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007128 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007129exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007130 pthread_mutex_unlock(&in->dev->lock);
7131 pthread_mutex_unlock(&in->lock);
7132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133 return 0;
7134}
7135
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007136static int in_add_audio_effect(const struct audio_stream *stream,
7137 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138{
Eric Laurent994a6932013-07-17 11:51:42 -07007139 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007140 return add_remove_audio_effect(stream, effect, true);
7141}
7142
7143static int in_remove_audio_effect(const struct audio_stream *stream,
7144 effect_handle_t effect)
7145{
Eric Laurent994a6932013-07-17 11:51:42 -07007146 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007147 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007148}
7149
Derek Chenf939fb72018-11-13 13:34:41 -08007150streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7151 audio_io_handle_t input)
7152{
7153 struct listnode *node;
7154
7155 list_for_each(node, &dev->active_inputs_list) {
7156 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7157 streams_input_ctxt_t,
7158 list);
7159 if (in_ctxt->input->capture_handle == input) {
7160 return in_ctxt;
7161 }
7162 }
7163 return NULL;
7164}
7165
7166streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7167 audio_io_handle_t output)
7168{
7169 struct listnode *node;
7170
7171 list_for_each(node, &dev->active_outputs_list) {
7172 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7173 streams_output_ctxt_t,
7174 list);
7175 if (out_ctxt->output->handle == output) {
7176 return out_ctxt;
7177 }
7178 }
7179 return NULL;
7180}
7181
Haynes Mathew George16081042017-05-31 17:16:49 -07007182static int in_stop(const struct audio_stream_in* stream)
7183{
7184 struct stream_in *in = (struct stream_in *)stream;
7185 struct audio_device *adev = in->dev;
7186
7187 int ret = -ENOSYS;
7188 ALOGV("%s", __func__);
7189 pthread_mutex_lock(&adev->lock);
7190 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7191 in->capture_started && in->pcm != NULL) {
7192 pcm_stop(in->pcm);
7193 ret = stop_input_stream(in);
7194 in->capture_started = false;
7195 }
7196 pthread_mutex_unlock(&adev->lock);
7197 return ret;
7198}
7199
7200static int in_start(const struct audio_stream_in* stream)
7201{
7202 struct stream_in *in = (struct stream_in *)stream;
7203 struct audio_device *adev = in->dev;
7204 int ret = -ENOSYS;
7205
7206 ALOGV("%s in %p", __func__, in);
7207 pthread_mutex_lock(&adev->lock);
7208 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7209 !in->capture_started && in->pcm != NULL) {
7210 if (!in->capture_started) {
7211 ret = start_input_stream(in);
7212 if (ret == 0) {
7213 in->capture_started = true;
7214 }
7215 }
7216 }
7217 pthread_mutex_unlock(&adev->lock);
7218 return ret;
7219}
7220
Phil Burke0a86d12019-02-16 22:28:11 -08007221// Read offset for the positional timestamp from a persistent vendor property.
7222// This is to workaround apparent inaccuracies in the timing information that
7223// is used by the AAudio timing model. The inaccuracies can cause glitches.
7224static int64_t in_get_mmap_time_offset() {
7225 const int32_t kDefaultOffsetMicros = 0;
7226 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007227 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007228 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7229 return mmap_time_offset_micros * (int64_t)1000;
7230}
7231
Haynes Mathew George16081042017-05-31 17:16:49 -07007232static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7233 int32_t min_size_frames,
7234 struct audio_mmap_buffer_info *info)
7235{
7236 struct stream_in *in = (struct stream_in *)stream;
7237 struct audio_device *adev = in->dev;
7238 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007239 unsigned int offset1 = 0;
7240 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007241 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007242 uint32_t mmap_size = 0;
7243 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007244
7245 pthread_mutex_lock(&adev->lock);
7246 ALOGV("%s in %p", __func__, in);
7247
Sharad Sanglec6f32552018-05-04 16:15:38 +05307248 if (CARD_STATUS_OFFLINE == in->card_status||
7249 CARD_STATUS_OFFLINE == adev->card_status) {
7250 ALOGW("in->card_status or adev->card_status offline, try again");
7251 ret = -EIO;
7252 goto exit;
7253 }
7254
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307255 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007256 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7257 ret = -EINVAL;
7258 goto exit;
7259 }
7260 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7261 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7262 ALOGV("%s in %p", __func__, in);
7263 ret = -ENOSYS;
7264 goto exit;
7265 }
7266 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7267 if (in->pcm_device_id < 0) {
7268 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7269 __func__, in->pcm_device_id, in->usecase);
7270 ret = -EINVAL;
7271 goto exit;
7272 }
7273
7274 adjust_mmap_period_count(&in->config, min_size_frames);
7275
7276 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7277 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7278 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7279 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307280 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307281 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7282 in->card_status = CARD_STATUS_OFFLINE;
7283 adev->card_status = CARD_STATUS_OFFLINE;
7284 ret = -EIO;
7285 goto exit;
7286 }
7287
Haynes Mathew George16081042017-05-31 17:16:49 -07007288 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7289 step = "open";
7290 ret = -ENODEV;
7291 goto exit;
7292 }
7293
7294 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7295 if (ret < 0) {
7296 step = "begin";
7297 goto exit;
7298 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007299
juyuchen626833d2019-06-04 16:48:02 +08007300 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007301 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7302 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7303 info->burst_size_frames = in->config.period_size;
7304 ret = platform_get_mmap_data_fd(adev->platform,
7305 in->pcm_device_id, 1 /*capture*/,
7306 &info->shared_memory_fd,
7307 &mmap_size);
7308 if (ret < 0) {
7309 // Fall back to non exclusive mode
7310 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7311 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007312 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7313 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7314
Arun Mirpuri5d170872019-03-26 13:21:31 -07007315 if (mmap_size < buffer_size) {
7316 step = "mmap";
7317 goto exit;
7318 }
juyuchen626833d2019-06-04 16:48:02 +08007319 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007320 }
7321
7322 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007323
7324 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7325 if (ret < 0) {
7326 step = "commit";
7327 goto exit;
7328 }
7329
Phil Burke0a86d12019-02-16 22:28:11 -08007330 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7331
Haynes Mathew George16081042017-05-31 17:16:49 -07007332 in->standby = false;
7333 ret = 0;
7334
7335 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7336 __func__, info->shared_memory_address, info->buffer_size_frames);
7337
7338exit:
7339 if (ret != 0) {
7340 if (in->pcm == NULL) {
7341 ALOGE("%s: %s - %d", __func__, step, ret);
7342 } else {
7343 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7344 pcm_close(in->pcm);
7345 in->pcm = NULL;
7346 }
7347 }
7348 pthread_mutex_unlock(&adev->lock);
7349 return ret;
7350}
7351
7352static int in_get_mmap_position(const struct audio_stream_in *stream,
7353 struct audio_mmap_position *position)
7354{
7355 struct stream_in *in = (struct stream_in *)stream;
7356 ALOGVV("%s", __func__);
7357 if (position == NULL) {
7358 return -EINVAL;
7359 }
7360 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7361 return -ENOSYS;
7362 }
7363 if (in->pcm == NULL) {
7364 return -ENOSYS;
7365 }
7366 struct timespec ts = { 0, 0 };
7367 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7368 if (ret < 0) {
7369 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7370 return ret;
7371 }
Phil Burke0a86d12019-02-16 22:28:11 -08007372 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7373 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007374 return 0;
7375}
7376
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307377static int in_get_active_microphones(const struct audio_stream_in *stream,
7378 struct audio_microphone_characteristic_t *mic_array,
7379 size_t *mic_count) {
7380 struct stream_in *in = (struct stream_in *)stream;
7381 struct audio_device *adev = in->dev;
7382 ALOGVV("%s", __func__);
7383
7384 lock_input_stream(in);
7385 pthread_mutex_lock(&adev->lock);
7386 int ret = platform_get_active_microphones(adev->platform,
7387 audio_channel_count_from_in_mask(in->channel_mask),
7388 in->usecase, mic_array, mic_count);
7389 pthread_mutex_unlock(&adev->lock);
7390 pthread_mutex_unlock(&in->lock);
7391
7392 return ret;
7393}
7394
7395static int adev_get_microphones(const struct audio_hw_device *dev,
7396 struct audio_microphone_characteristic_t *mic_array,
7397 size_t *mic_count) {
7398 struct audio_device *adev = (struct audio_device *)dev;
7399 ALOGVV("%s", __func__);
7400
7401 pthread_mutex_lock(&adev->lock);
7402 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7403 pthread_mutex_unlock(&adev->lock);
7404
7405 return ret;
7406}
juyuchendb308c22019-01-21 11:57:17 -07007407
7408static void in_update_sink_metadata(struct audio_stream_in *stream,
7409 const struct sink_metadata *sink_metadata) {
7410
7411 if (stream == NULL
7412 || sink_metadata == NULL
7413 || sink_metadata->tracks == NULL) {
7414 return;
7415 }
7416
7417 int error = 0;
7418 struct stream_in *in = (struct stream_in *)stream;
7419 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007420 struct listnode devices;
7421
7422 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007423
7424 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007425 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007426
7427 lock_input_stream(in);
7428 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007429 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007430
7431 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007432 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007433 && adev->voice_tx_output != NULL) {
7434 /* Use the rx device from afe-proxy record to route voice call because
7435 there is no routing if tx device is on primary hal and rx device
7436 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007437 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007438
7439 if (!voice_is_call_state_active(adev)) {
7440 if (adev->mode == AUDIO_MODE_IN_CALL) {
7441 adev->current_call_output = adev->voice_tx_output;
7442 error = voice_start_call(adev);
7443 if (error != 0)
7444 ALOGE("%s: start voice call failed %d", __func__, error);
7445 }
7446 } else {
7447 adev->current_call_output = adev->voice_tx_output;
7448 voice_update_devices_for_all_voice_usecases(adev);
7449 }
7450 }
7451
7452 pthread_mutex_unlock(&adev->lock);
7453 pthread_mutex_unlock(&in->lock);
7454}
7455
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307456int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007457 audio_io_handle_t handle,
7458 audio_devices_t devices,
7459 audio_output_flags_t flags,
7460 struct audio_config *config,
7461 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007462 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007463{
7464 struct audio_device *adev = (struct audio_device *)dev;
7465 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307466 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007467 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007468 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307469 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007470 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7471 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7472 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7473 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007474 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007475 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7476 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007477 bool force_haptic_path =
7478 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007479 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007480
kunleizdff872d2018-08-20 14:40:33 +08007481 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007482 is_usb_dev = false;
7483 devices = AUDIO_DEVICE_OUT_SPEAKER;
7484 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7485 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007486 if (config->format == AUDIO_FORMAT_DEFAULT)
7487 config->format = AUDIO_FORMAT_PCM_16_BIT;
7488 if (config->sample_rate == 0)
7489 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7490 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7491 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007492 }
7493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307495
Rahul Sharma99770982019-03-06 17:05:26 +05307496 pthread_mutex_lock(&adev->lock);
7497 if (out_get_stream(adev, handle) != NULL) {
7498 ALOGW("%s, output stream already opened", __func__);
7499 ret = -EEXIST;
7500 }
7501 pthread_mutex_unlock(&adev->lock);
7502 if (ret)
7503 return ret;
7504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007505 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7506
Mingming Yin3a941d42016-02-17 18:08:05 -08007507 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007508 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7509 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307510
7511
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007512 if (!out) {
7513 return -ENOMEM;
7514 }
7515
Haynes Mathew George204045b2015-02-25 20:32:03 -08007516 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007517 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307518 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007519 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007520 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007522 if (devices == AUDIO_DEVICE_NONE)
7523 devices = AUDIO_DEVICE_OUT_SPEAKER;
7524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007525 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007526 list_init(&out->device_list);
7527 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007528 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007529 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007530 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307531 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307532 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7533 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7534 else
7535 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007536 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007537 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007538 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307539 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307540 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307541 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007542 out->hal_output_suspend_supported = 0;
7543 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307544 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307545 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307546 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007547 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007548
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307549 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307550 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007551 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7552
Aalique Grahame22e49102018-12-18 14:23:57 -08007553 if (direct_dev &&
7554 (audio_is_linear_pcm(out->format) ||
7555 config->format == AUDIO_FORMAT_DEFAULT) &&
7556 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7557 audio_format_t req_format = config->format;
7558 audio_channel_mask_t req_channel_mask = config->channel_mask;
7559 uint32_t req_sample_rate = config->sample_rate;
7560
7561 pthread_mutex_lock(&adev->lock);
7562 if (is_hdmi) {
7563 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7564 ret = read_hdmi_sink_caps(out);
7565 if (config->sample_rate == 0)
7566 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7567 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7568 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7569 if (config->format == AUDIO_FORMAT_DEFAULT)
7570 config->format = AUDIO_FORMAT_PCM_16_BIT;
7571 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007572 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7573 &config->format,
7574 &out->supported_formats[0],
7575 MAX_SUPPORTED_FORMATS,
7576 &config->channel_mask,
7577 &out->supported_channel_masks[0],
7578 MAX_SUPPORTED_CHANNEL_MASKS,
7579 &config->sample_rate,
7580 &out->supported_sample_rates[0],
7581 MAX_SUPPORTED_SAMPLE_RATES);
7582 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007583 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007584
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007585 pthread_mutex_unlock(&adev->lock);
7586 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007587 if (ret == -ENOSYS) {
7588 /* ignore and go with default */
7589 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007590 }
7591 // For MMAP NO IRQ, allow conversions in ADSP
7592 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7593 goto error_open;
7594 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007595 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007596 goto error_open;
7597 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007598
7599 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7600 config->sample_rate = req_sample_rate;
7601 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7602 config->channel_mask = req_channel_mask;
7603 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7604 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007605 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007606
7607 out->sample_rate = config->sample_rate;
7608 out->channel_mask = config->channel_mask;
7609 out->format = config->format;
7610 if (is_hdmi) {
7611 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7612 out->config = pcm_config_hdmi_multi;
7613 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7614 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7615 out->config = pcm_config_mmap_playback;
7616 out->stream.start = out_start;
7617 out->stream.stop = out_stop;
7618 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7619 out->stream.get_mmap_position = out_get_mmap_position;
7620 } else {
7621 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7622 out->config = pcm_config_hifi;
7623 }
7624
7625 out->config.rate = out->sample_rate;
7626 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7627 if (is_hdmi) {
7628 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7629 audio_bytes_per_sample(out->format));
7630 }
7631 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007632 }
7633
Derek Chenf6318be2017-06-12 17:16:24 -04007634 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007635 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007636 /* extract car audio stream index */
7637 out->car_audio_stream =
7638 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7639 if (out->car_audio_stream < 0) {
7640 ALOGE("%s: invalid car audio stream %x",
7641 __func__, out->car_audio_stream);
7642 ret = -EINVAL;
7643 goto error_open;
7644 }
Derek Chen5f67a942020-02-24 23:08:13 -08007645 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007646 }
7647
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007648 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007649 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007650 if (!voice_extn_is_compress_voip_supported()) {
7651 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7652 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007653 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7654 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007655 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7656 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007657 out->volume_l = INVALID_OUT_VOLUME;
7658 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007659
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007660 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007661 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007662 uint32_t channel_count =
7663 audio_channel_count_from_out_mask(out->channel_mask);
7664 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7665 out->sample_rate, out->format,
7666 channel_count, false);
7667 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7668 if (frame_size != 0)
7669 out->config.period_size = buffer_size / frame_size;
7670 else
7671 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007672 }
7673 } else {
7674 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7675 voice_extn_compress_voip_is_active(out->dev)) &&
7676 (voice_extn_compress_voip_is_config_supported(config))) {
7677 ret = voice_extn_compress_voip_open_output_stream(out);
7678 if (ret != 0) {
7679 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7680 __func__, ret);
7681 goto error_open;
7682 }
Sujin Panicker19027262019-09-16 18:28:06 +05307683 } else {
7684 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7685 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007686 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007687 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007688 } else if (audio_is_linear_pcm(out->format) &&
7689 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7690 out->channel_mask = config->channel_mask;
7691 out->sample_rate = config->sample_rate;
7692 out->format = config->format;
7693 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7694 // does this change?
7695 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7696 out->config.rate = config->sample_rate;
7697 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7698 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7699 audio_bytes_per_sample(config->format));
7700 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007701 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307702 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307703 pthread_mutex_lock(&adev->lock);
7704 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7705 pthread_mutex_unlock(&adev->lock);
7706
7707 // reject offload during card offline to allow
7708 // fallback to s/w paths
7709 if (offline) {
7710 ret = -ENODEV;
7711 goto error_open;
7712 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007714 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7715 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7716 ALOGE("%s: Unsupported Offload information", __func__);
7717 ret = -EINVAL;
7718 goto error_open;
7719 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007720
Atul Khare3fa6e542017-08-09 00:56:17 +05307721 if (config->offload_info.format == 0)
7722 config->offload_info.format = config->format;
7723 if (config->offload_info.sample_rate == 0)
7724 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007725
Mingming Yin90310102013-11-13 16:57:00 -08007726 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307727 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007728 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007729 ret = -EINVAL;
7730 goto error_open;
7731 }
7732
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007733 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7734 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7735 (audio_extn_passthru_is_passthrough_stream(out)) &&
7736 !((config->sample_rate == 48000) ||
7737 (config->sample_rate == 96000) ||
7738 (config->sample_rate == 192000))) {
7739 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7740 __func__, config->sample_rate, config->offload_info.format);
7741 ret = -EINVAL;
7742 goto error_open;
7743 }
7744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007745 out->compr_config.codec = (struct snd_codec *)
7746 calloc(1, sizeof(struct snd_codec));
7747
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007748 if (!out->compr_config.codec) {
7749 ret = -ENOMEM;
7750 goto error_open;
7751 }
7752
Dhananjay Kumarac341582017-02-23 23:42:25 +05307753 out->stream.pause = out_pause;
7754 out->stream.resume = out_resume;
7755 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307756 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307757 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007758 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307759 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007760 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307761 } else {
7762 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7763 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007764 }
vivek mehta446c3962015-09-14 10:57:35 -07007765
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307766 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7767 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007768#ifdef AUDIO_GKI_ENABLED
7769 /* out->compr_config.codec->reserved[1] is for flags */
7770 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7771#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307772 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007773#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307774 }
7775
vivek mehta446c3962015-09-14 10:57:35 -07007776 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007777 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007778 config->format == 0 && config->sample_rate == 0 &&
7779 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007780 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007781 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7782 } else {
7783 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7784 ret = -EEXIST;
7785 goto error_open;
7786 }
vivek mehta446c3962015-09-14 10:57:35 -07007787 }
7788
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007789 if (config->offload_info.channel_mask)
7790 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007791 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007792 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007793 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007794 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307795 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007796 ret = -EINVAL;
7797 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007798 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007799
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007800 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007801 out->sample_rate = config->offload_info.sample_rate;
7802
Mingming Yin3ee55c62014-08-04 14:23:35 -07007803 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007804
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307805 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307806 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307807 audio_extn_dolby_send_ddp_endp_params(adev);
7808 audio_extn_dolby_set_dmid(adev);
7809 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007810
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007811 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007812 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007813 out->compr_config.codec->bit_rate =
7814 config->offload_info.bit_rate;
7815 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307816 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007817 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307818 /* Update bit width only for non passthrough usecases.
7819 * For passthrough usecases, the output will always be opened @16 bit
7820 */
7821 if (!audio_extn_passthru_is_passthrough_stream(out))
7822 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307823
7824 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007825#ifdef AUDIO_GKI_ENABLED
7826 /* out->compr_config.codec->reserved[1] is for flags */
7827 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7828 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7829#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307830 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7831 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007832#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307833
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007834 /*TODO: Do we need to change it for passthrough */
7835 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007836
Manish Dewangana6fc5442015-08-24 20:30:31 +05307837 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7838 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307839 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307840 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307841 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7842 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307843
7844 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7845 AUDIO_FORMAT_PCM) {
7846
7847 /*Based on platform support, configure appropriate alsa format for corresponding
7848 *hal input format.
7849 */
7850 out->compr_config.codec->format = hal_format_to_alsa(
7851 config->offload_info.format);
7852
Ashish Jain83a6cc22016-06-28 14:34:17 +05307853 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307854 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307855 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307856
Dhananjay Kumarac341582017-02-23 23:42:25 +05307857 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307858 *hal input format and alsa format might differ based on platform support.
7859 */
7860 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307861 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307862
7863 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7864
Deeraj Soman93155a62019-09-30 19:00:37 +05307865 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7866 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7867 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7868 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7869 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307870
Ashish Jainf1eaa582016-05-23 20:54:24 +05307871 /* Check if alsa session is configured with the same format as HAL input format,
7872 * if not then derive correct fragment size needed to accomodate the
7873 * conversion of HAL input format to alsa format.
7874 */
7875 audio_extn_utils_update_direct_pcm_fragment_size(out);
7876
7877 /*if hal input and output fragment size is different this indicates HAL input format is
7878 *not same as the alsa format
7879 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307880 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307881 /*Allocate a buffer to convert input data to the alsa configured format.
7882 *size of convert buffer is equal to the size required to hold one fragment size
7883 *worth of pcm data, this is because flinger does not write more than fragment_size
7884 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307885 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7886 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307887 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7888 ret = -ENOMEM;
7889 goto error_open;
7890 }
7891 }
7892 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7893 out->compr_config.fragment_size =
7894 audio_extn_passthru_get_buffer_size(&config->offload_info);
7895 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7896 } else {
7897 out->compr_config.fragment_size =
7898 platform_get_compress_offload_buffer_size(&config->offload_info);
7899 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7900 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007901
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307902 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7903 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7904 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007905 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307906 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007907
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307908 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7909 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7910 }
7911
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007912 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7913 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007914
Manish Dewangan69426c82017-01-30 17:35:36 +05307915 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7916 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7917 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7918 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7919 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7920 } else {
7921 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7922 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007923
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307924 memset(&out->channel_map_param, 0,
7925 sizeof(struct audio_out_channel_map_param));
7926
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007927 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307928 out->send_next_track_params = false;
7929 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007930 out->offload_state = OFFLOAD_STATE_IDLE;
7931 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007932 out->writeAt.tv_sec = 0;
7933 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007934
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007935 audio_extn_dts_create_state_notifier_node(out->usecase);
7936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007937 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7938 __func__, config->offload_info.version,
7939 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307940
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307941 /* Check if DSD audio format is supported in codec
7942 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307943 */
7944
7945 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307946 (!platform_check_codec_dsd_support(adev->platform) ||
7947 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307948 ret = -EINVAL;
7949 goto error_open;
7950 }
7951
Ashish Jain5106d362016-05-11 19:23:33 +05307952 /* Disable gapless if any of the following is true
7953 * passthrough playback
7954 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307955 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307956 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307957 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307958 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007959 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307960 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307961 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307962 check_and_set_gapless_mode(adev, false);
7963 } else
7964 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007965
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307966 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007967 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7968 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307969 if (config->format == AUDIO_FORMAT_DSD) {
7970 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007971#ifdef AUDIO_GKI_ENABLED
7972 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7973 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7974#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307975 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007976#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307977 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007978
7979 create_offload_callback_thread(out);
7980
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007981 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007982 switch (config->sample_rate) {
7983 case 0:
7984 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7985 break;
7986 case 8000:
7987 case 16000:
7988 case 48000:
7989 out->sample_rate = config->sample_rate;
7990 break;
7991 default:
7992 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7993 config->sample_rate);
7994 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7995 ret = -EINVAL;
7996 goto error_open;
7997 }
7998 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7999 switch (config->channel_mask) {
8000 case AUDIO_CHANNEL_NONE:
8001 case AUDIO_CHANNEL_OUT_STEREO:
8002 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8003 break;
8004 default:
8005 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8006 config->channel_mask);
8007 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8008 ret = -EINVAL;
8009 goto error_open;
8010 }
8011 switch (config->format) {
8012 case AUDIO_FORMAT_DEFAULT:
8013 case AUDIO_FORMAT_PCM_16_BIT:
8014 out->format = AUDIO_FORMAT_PCM_16_BIT;
8015 break;
8016 default:
8017 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8018 config->format);
8019 config->format = AUDIO_FORMAT_PCM_16_BIT;
8020 ret = -EINVAL;
8021 goto error_open;
8022 }
8023
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308024 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008025 if (ret != 0) {
8026 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008027 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008028 goto error_open;
8029 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008030 } else if (is_single_device_type_equal(&out->device_list,
8031 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008032 switch (config->sample_rate) {
8033 case 0:
8034 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8035 break;
8036 case 8000:
8037 case 16000:
8038 case 48000:
8039 out->sample_rate = config->sample_rate;
8040 break;
8041 default:
8042 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8043 config->sample_rate);
8044 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8045 ret = -EINVAL;
8046 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008047 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008048 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8049 switch (config->channel_mask) {
8050 case AUDIO_CHANNEL_NONE:
8051 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8052 break;
8053 case AUDIO_CHANNEL_OUT_STEREO:
8054 out->channel_mask = config->channel_mask;
8055 break;
8056 default:
8057 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8058 config->channel_mask);
8059 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8060 ret = -EINVAL;
8061 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008062 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008063 switch (config->format) {
8064 case AUDIO_FORMAT_DEFAULT:
8065 out->format = AUDIO_FORMAT_PCM_16_BIT;
8066 break;
8067 case AUDIO_FORMAT_PCM_16_BIT:
8068 out->format = config->format;
8069 break;
8070 default:
8071 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8072 config->format);
8073 config->format = AUDIO_FORMAT_PCM_16_BIT;
8074 ret = -EINVAL;
8075 break;
8076 }
8077 if (ret != 0)
8078 goto error_open;
8079
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008080 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8081 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008082 out->config.rate = out->sample_rate;
8083 out->config.channels =
8084 audio_channel_count_from_out_mask(out->channel_mask);
8085 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008086 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008087 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308088 unsigned int channels = 0;
8089 /*Update config params to default if not set by the caller*/
8090 if (config->sample_rate == 0)
8091 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8092 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8093 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8094 if (config->format == AUDIO_FORMAT_DEFAULT)
8095 config->format = AUDIO_FORMAT_PCM_16_BIT;
8096
8097 channels = audio_channel_count_from_out_mask(out->channel_mask);
8098
Varun Balaraje49253e2017-07-06 19:48:56 +05308099 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8100 out->usecase = get_interactive_usecase(adev);
8101 out->config = pcm_config_low_latency;
8102 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308103 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008104 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8105 out->flags);
8106 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008107 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8108 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8109 out->config = pcm_config_mmap_playback;
8110 out->stream.start = out_start;
8111 out->stream.stop = out_stop;
8112 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8113 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308114 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8115 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008116 out->hal_output_suspend_supported =
8117 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8118 out->dynamic_pm_qos_config_supported =
8119 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8120 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008121 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8122 } else {
8123 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8124 //the mixer path will be a string similar to "low-latency-playback resume"
8125 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8126 strlcat(out->pm_qos_mixer_path,
8127 " resume", MAX_MIXER_PATH_LEN);
8128 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8129 out->pm_qos_mixer_path);
8130 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308131 out->config = pcm_config_low_latency;
8132 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8133 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8134 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308135 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8136 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8137 if (out->config.period_size <= 0) {
8138 ALOGE("Invalid configuration period size is not valid");
8139 ret = -EINVAL;
8140 goto error_open;
8141 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008142 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8143 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8144 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008145 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8146 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8147 out->config = pcm_config_haptics_audio;
8148 if (force_haptic_path)
8149 adev->haptics_config = pcm_config_haptics_audio;
8150 else
8151 adev->haptics_config = pcm_config_haptics;
8152
Meng Wangd08ce322020-04-02 08:59:20 +08008153 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008154 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8155
8156 if (force_haptic_path) {
8157 out->config.channels = 1;
8158 adev->haptics_config.channels = 1;
8159 } else
8160 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 -08008161 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008162 ret = audio_extn_auto_hal_open_output_stream(out);
8163 if (ret) {
8164 ALOGE("%s: Failed to open output stream for bus device", __func__);
8165 ret = -EINVAL;
8166 goto error_open;
8167 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308168 } else {
8169 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008170 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8171 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308172 }
8173 out->hal_ip_format = format = out->format;
8174 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8175 out->hal_op_format = pcm_format_to_hal(out->config.format);
8176 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8177 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008178 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308179 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308180 if (out->hal_ip_format != out->hal_op_format) {
8181 uint32_t buffer_size = out->config.period_size *
8182 format_to_bitwidth_table[out->hal_op_format] *
8183 out->config.channels;
8184 out->convert_buffer = calloc(1, buffer_size);
8185 if (out->convert_buffer == NULL){
8186 ALOGE("Allocation failed for convert buffer for size %d",
8187 out->compr_config.fragment_size);
8188 ret = -ENOMEM;
8189 goto error_open;
8190 }
8191 ALOGD("Convert buffer allocated of size %d", buffer_size);
8192 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008193 }
8194
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008195 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8196 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308197
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008198 /* TODO remove this hardcoding and check why width is zero*/
8199 if (out->bit_width == 0)
8200 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308201 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008202 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008203 &out->device_list, out->flags,
8204 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308205 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308206 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008207 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008208 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8209 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008210 if(adev->primary_output == NULL)
8211 adev->primary_output = out;
8212 else {
8213 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008214 ret = -EEXIST;
8215 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008216 }
8217 }
8218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008219 /* Check if this usecase is already existing */
8220 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008221 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8222 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008223 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008224 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008225 ret = -EEXIST;
8226 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008227 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008229 pthread_mutex_unlock(&adev->lock);
8230
8231 out->stream.common.get_sample_rate = out_get_sample_rate;
8232 out->stream.common.set_sample_rate = out_set_sample_rate;
8233 out->stream.common.get_buffer_size = out_get_buffer_size;
8234 out->stream.common.get_channels = out_get_channels;
8235 out->stream.common.get_format = out_get_format;
8236 out->stream.common.set_format = out_set_format;
8237 out->stream.common.standby = out_standby;
8238 out->stream.common.dump = out_dump;
8239 out->stream.common.set_parameters = out_set_parameters;
8240 out->stream.common.get_parameters = out_get_parameters;
8241 out->stream.common.add_audio_effect = out_add_audio_effect;
8242 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8243 out->stream.get_latency = out_get_latency;
8244 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008245#ifdef NO_AUDIO_OUT
8246 out->stream.write = out_write_for_no_output;
8247#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008248 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008249#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008250 out->stream.get_render_position = out_get_render_position;
8251 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008252 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008253
Haynes Mathew George16081042017-05-31 17:16:49 -07008254 if (out->realtime)
8255 out->af_period_multiplier = af_period_multiplier;
8256 else
8257 out->af_period_multiplier = 1;
8258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008259 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008260 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008261 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008262
8263 config->format = out->stream.common.get_format(&out->stream.common);
8264 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8265 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308266 register_format(out->format, out->supported_formats);
8267 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8268 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008269
Aalique Grahame22e49102018-12-18 14:23:57 -08008270 out->error_log = error_log_create(
8271 ERROR_LOG_ENTRIES,
8272 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8273
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308274 /*
8275 By locking output stream before registering, we allow the callback
8276 to update stream's state only after stream's initial state is set to
8277 adev state.
8278 */
8279 lock_output_stream(out);
8280 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8281 pthread_mutex_lock(&adev->lock);
8282 out->card_status = adev->card_status;
8283 pthread_mutex_unlock(&adev->lock);
8284 pthread_mutex_unlock(&out->lock);
8285
Aalique Grahame22e49102018-12-18 14:23:57 -08008286 stream_app_type_cfg_init(&out->app_type_cfg);
8287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008288 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308289 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008290 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008291
8292 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8293 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8294 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008295 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308296 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008297 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008298 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308299 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8300 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008301 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8302 out->usecase, PCM_PLAYBACK);
8303 hdlr_stream_cfg.flags = out->flags;
8304 hdlr_stream_cfg.type = PCM_PLAYBACK;
8305 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8306 &hdlr_stream_cfg);
8307 if (ret) {
8308 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8309 out->adsp_hdlr_stream_handle = NULL;
8310 }
8311 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308312 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8313 is_direct_passthough, false);
8314 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8315 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008316 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008317 if (ret < 0) {
8318 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8319 out->ip_hdlr_handle = NULL;
8320 }
8321 }
Derek Chenf939fb72018-11-13 13:34:41 -08008322
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008323 ret = io_streams_map_insert(adev, &out->stream.common,
8324 out->handle, AUDIO_PATCH_HANDLE_NONE);
8325 if (ret != 0)
8326 goto error_open;
8327
Derek Chenf939fb72018-11-13 13:34:41 -08008328 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8329 calloc(1, sizeof(streams_output_ctxt_t));
8330 if (out_ctxt == NULL) {
8331 ALOGE("%s fail to allocate output ctxt", __func__);
8332 ret = -ENOMEM;
8333 goto error_open;
8334 }
8335 out_ctxt->output = out;
8336
8337 pthread_mutex_lock(&adev->lock);
8338 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8339 pthread_mutex_unlock(&adev->lock);
8340
Eric Laurent994a6932013-07-17 11:51:42 -07008341 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008342 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008343
8344error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308345 if (out->convert_buffer)
8346 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008347 free(out);
8348 *stream_out = NULL;
8349 ALOGD("%s: exit: ret %d", __func__, ret);
8350 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008351}
8352
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308353void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008354 struct audio_stream_out *stream)
8355{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008356 struct stream_out *out = (struct stream_out *)stream;
8357 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008358 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008359
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008360 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308361
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008362 io_streams_map_remove(adev, out->handle);
8363
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308364 // must deregister from sndmonitor first to prevent races
8365 // between the callback and close_stream
8366 audio_extn_snd_mon_unregister_listener(out);
8367
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008368 /* close adsp hdrl session before standby */
8369 if (out->adsp_hdlr_stream_handle) {
8370 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8371 if (ret)
8372 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8373 out->adsp_hdlr_stream_handle = NULL;
8374 }
8375
Manish Dewangan21a850a2017-08-14 12:03:55 +05308376 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008377 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8378 out->ip_hdlr_handle = NULL;
8379 }
8380
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008381 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308382 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008383 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308384 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308385 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008386 if(ret != 0)
8387 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8388 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008389 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008390 out_standby(&stream->common);
8391
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008392 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008393 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008394 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008395 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008396 if (out->compr_config.codec != NULL)
8397 free(out->compr_config.codec);
8398 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008399
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308400 out->a2dp_compress_mute = false;
8401
Varun Balaraje49253e2017-07-06 19:48:56 +05308402 if (is_interactive_usecase(out->usecase))
8403 free_interactive_usecase(adev, out->usecase);
8404
Ashish Jain83a6cc22016-06-28 14:34:17 +05308405 if (out->convert_buffer != NULL) {
8406 free(out->convert_buffer);
8407 out->convert_buffer = NULL;
8408 }
8409
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008410 if (adev->voice_tx_output == out)
8411 adev->voice_tx_output = NULL;
8412
Aalique Grahame22e49102018-12-18 14:23:57 -08008413 error_log_destroy(out->error_log);
8414 out->error_log = NULL;
8415
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308416 if (adev->primary_output == out)
8417 adev->primary_output = NULL;
8418
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008419 pthread_cond_destroy(&out->cond);
8420 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008421
8422 pthread_mutex_lock(&adev->lock);
8423 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8424 if (out_ctxt != NULL) {
8425 list_remove(&out_ctxt->list);
8426 free(out_ctxt);
8427 } else {
8428 ALOGW("%s, output stream already closed", __func__);
8429 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008430 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008431 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008432 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008433}
8434
8435static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8436{
8437 struct audio_device *adev = (struct audio_device *)dev;
8438 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008439 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008440 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008441 int ret;
8442 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008443 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008444 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008445 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008446
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008447 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008448 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008449
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308450 if (!parms)
8451 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308452
Derek Chen6f293672019-04-01 01:40:24 -07008453 /* notify adev and input/output streams on the snd card status */
8454 adev_snd_mon_cb((void *)adev, parms);
8455
8456 list_for_each(node, &adev->active_outputs_list) {
8457 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8458 streams_output_ctxt_t,
8459 list);
8460 out_snd_mon_cb((void *)out_ctxt->output, parms);
8461 }
8462
8463 list_for_each(node, &adev->active_inputs_list) {
8464 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8465 streams_input_ctxt_t,
8466 list);
8467 in_snd_mon_cb((void *)in_ctxt->input, parms);
8468 }
8469
Zhou Songd6d71752019-05-21 18:08:51 +08008470 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308471 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8472 if (ret >= 0) {
8473 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008474 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308475 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008476 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308477 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008478 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008479 }
8480 }
8481
8482 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8483 if (ret>=0) {
8484 if (!strncmp(value, "false", 5) &&
8485 audio_extn_a2dp_source_is_suspended()) {
8486 struct audio_usecase *usecase;
8487 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008488 list_for_each(node, &adev->usecase_list) {
8489 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008490 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008491 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008492 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008493 reassign_device_list(&usecase->stream.in->device_list,
8494 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008495 select_devices(adev, usecase->id);
8496 }
Zhou Songd6d71752019-05-21 18:08:51 +08008497 }
8498 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308499 }
8500
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008501 status = voice_set_parameters(adev, parms);
8502 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008503 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008504
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008505 status = platform_set_parameters(adev->platform, parms);
8506 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008507 goto done;
8508
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008509 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8510 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008511 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008512 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8513 adev->bluetooth_nrec = true;
8514 else
8515 adev->bluetooth_nrec = false;
8516 }
8517
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008518 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8519 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008520 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8521 adev->screen_off = false;
8522 else
8523 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008524 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008525 }
8526
Eric Laurent4b084132018-10-19 17:33:43 -07008527 ret = str_parms_get_int(parms, "rotation", &val);
8528 if (ret >= 0) {
8529 bool reverse_speakers = false;
8530 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8531 switch (val) {
8532 // FIXME: note that the code below assumes that the speakers are in the correct placement
8533 // relative to the user when the device is rotated 90deg from its default rotation. This
8534 // assumption is device-specific, not platform-specific like this code.
8535 case 270:
8536 reverse_speakers = true;
8537 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8538 break;
8539 case 0:
8540 case 180:
8541 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8542 break;
8543 case 90:
8544 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8545 break;
8546 default:
8547 ALOGE("%s: unexpected rotation of %d", __func__, val);
8548 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008549 }
Eric Laurent4b084132018-10-19 17:33:43 -07008550 if (status == 0) {
8551 // check and set swap
8552 // - check if orientation changed and speaker active
8553 // - set rotation and cache the rotation value
8554 adev->camera_orientation =
8555 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8556 if (!audio_extn_is_maxx_audio_enabled())
8557 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8558 }
8559 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008560
Mingming Yin514a8bc2014-07-29 15:22:21 -07008561 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8562 if (ret >= 0) {
8563 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8564 adev->bt_wb_speech_enabled = true;
8565 else
8566 adev->bt_wb_speech_enabled = false;
8567 }
8568
Zhou Song12c29502019-03-16 10:37:18 +08008569 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8570 if (ret >= 0) {
8571 val = atoi(value);
8572 adev->swb_speech_mode = val;
8573 }
8574
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8576 if (ret >= 0) {
8577 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308578 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008579 if (audio_is_output_device(val) &&
8580 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008581 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008582 platform_get_controller_stream_from_params(parms, &controller, &stream);
8583 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8584 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008585 if (ret < 0) {
8586 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308587 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008588 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008589 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308590 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008591 /*
8592 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8593 * Per AudioPolicyManager, USB device is higher priority than WFD.
8594 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8595 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8596 * starting voice call on USB
8597 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008598 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308599 if (ret >= 0)
8600 audio_extn_usb_add_device(device, atoi(value));
8601
Zhou Song6f862822017-11-06 17:27:57 +08008602 if (!audio_extn_usb_is_tunnel_supported()) {
8603 ALOGV("detected USB connect .. disable proxy");
8604 adev->allow_afe_proxy_usage = false;
8605 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008606 }
8607 }
8608
8609 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8610 if (ret >= 0) {
8611 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308612 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008613 /*
8614 * The HDMI / Displayport disconnect handling has been moved to
8615 * audio extension to ensure that its parameters are not
8616 * invalidated prior to updating sysfs of the disconnect event
8617 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8618 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308619 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008620 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308621 if (ret >= 0)
8622 audio_extn_usb_remove_device(device, atoi(value));
8623
Zhou Song6f862822017-11-06 17:27:57 +08008624 if (!audio_extn_usb_is_tunnel_supported()) {
8625 ALOGV("detected USB disconnect .. enable proxy");
8626 adev->allow_afe_proxy_usage = true;
8627 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008628 }
8629 }
8630
Aalique Grahame22e49102018-12-18 14:23:57 -08008631 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008632 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008633
8634 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008635 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308636 struct audio_usecase *usecase;
8637 struct listnode *node;
8638 list_for_each(node, &adev->usecase_list) {
8639 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308640 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008641 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308642 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008643 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308644 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008645 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308646 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308647 ALOGD("Switching to speaker and muting the stream before select_devices");
8648 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308649 //force device switch to re configure encoder
8650 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308651 ALOGD("Unmuting the stream after select_devices");
8652 usecase->stream.out->a2dp_compress_mute = false;
8653 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 +05308654 audio_extn_a2dp_set_handoff_mode(false);
8655 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308656 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308657 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8658 usecase->stream.out->a2dp_compress_mute) {
8659 pthread_mutex_unlock(&adev->lock);
8660 lock_output_stream(usecase->stream.out);
8661 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008662 reassign_device_list(&usecase->stream.out->device_list,
8663 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308664 check_a2dp_restore_l(adev, usecase->stream.out, true);
8665 pthread_mutex_unlock(&usecase->stream.out->lock);
8666 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308667 }
8668 }
8669 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008670
8671 //handle vr audio setparam
8672 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8673 value, sizeof(value));
8674 if (ret >= 0) {
8675 ALOGI("Setting vr mode to be %s", value);
8676 if (!strncmp(value, "true", 4)) {
8677 adev->vr_audio_mode_enabled = true;
8678 ALOGI("Setting vr mode to true");
8679 } else if (!strncmp(value, "false", 5)) {
8680 adev->vr_audio_mode_enabled = false;
8681 ALOGI("Setting vr mode to false");
8682 } else {
8683 ALOGI("wrong vr mode set");
8684 }
8685 }
8686
Eric Laurent4b084132018-10-19 17:33:43 -07008687 //FIXME: to be replaced by proper video capture properties API
8688 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8689 if (ret >= 0) {
8690 int camera_facing = CAMERA_FACING_BACK;
8691 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8692 camera_facing = CAMERA_FACING_FRONT;
8693 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8694 camera_facing = CAMERA_FACING_BACK;
8695 else {
8696 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8697 goto done;
8698 }
8699 adev->camera_orientation =
8700 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8701 struct audio_usecase *usecase;
8702 struct listnode *node;
8703 list_for_each(node, &adev->usecase_list) {
8704 usecase = node_to_item(node, struct audio_usecase, list);
8705 struct stream_in *in = usecase->stream.in;
8706 if (usecase->type == PCM_CAPTURE && in != NULL &&
8707 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8708 select_devices(adev, in->usecase);
8709 }
8710 }
8711 }
8712
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308713 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008714done:
8715 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008716 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308717error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008718 ALOGV("%s: exit with code(%d)", __func__, status);
8719 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008720}
8721
8722static char* adev_get_parameters(const struct audio_hw_device *dev,
8723 const char *keys)
8724{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308725 ALOGD("%s:%s", __func__, keys);
8726
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008727 struct audio_device *adev = (struct audio_device *)dev;
8728 struct str_parms *reply = str_parms_create();
8729 struct str_parms *query = str_parms_create_str(keys);
8730 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308731 char value[256] = {0};
8732 int ret = 0;
8733
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008734 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008735 if (reply) {
8736 str_parms_destroy(reply);
8737 }
8738 if (query) {
8739 str_parms_destroy(query);
8740 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008741 ALOGE("adev_get_parameters: failed to create query or reply");
8742 return NULL;
8743 }
8744
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008745 //handle vr audio getparam
8746
8747 ret = str_parms_get_str(query,
8748 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8749 value, sizeof(value));
8750
8751 if (ret >= 0) {
8752 bool vr_audio_enabled = false;
8753 pthread_mutex_lock(&adev->lock);
8754 vr_audio_enabled = adev->vr_audio_mode_enabled;
8755 pthread_mutex_unlock(&adev->lock);
8756
8757 ALOGI("getting vr mode to %d", vr_audio_enabled);
8758
8759 if (vr_audio_enabled) {
8760 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8761 "true");
8762 goto exit;
8763 } else {
8764 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8765 "false");
8766 goto exit;
8767 }
8768 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008769
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008770 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008771 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008772 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008773 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008774 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308775 pthread_mutex_unlock(&adev->lock);
8776
Naresh Tannirud7205b62014-06-20 02:54:48 +05308777exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008778 str = str_parms_to_str(reply);
8779 str_parms_destroy(query);
8780 str_parms_destroy(reply);
8781
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308782 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008783 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008784}
8785
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008786static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008787{
8788 return 0;
8789}
8790
8791static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8792{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008793 int ret;
8794 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008795
8796 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8797
Haynes Mathew George5191a852013-09-11 14:19:36 -07008798 pthread_mutex_lock(&adev->lock);
8799 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008800 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008801 pthread_mutex_unlock(&adev->lock);
8802 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008803}
8804
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008805static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8806 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008807{
8808 return -ENOSYS;
8809}
8810
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008811static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8812 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008813{
8814 return -ENOSYS;
8815}
8816
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008817static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8818 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008819{
8820 return -ENOSYS;
8821}
8822
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008823static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8824 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008825{
8826 return -ENOSYS;
8827}
8828
8829static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8830{
8831 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008832 struct listnode *node;
8833 struct audio_usecase *usecase = NULL;
8834 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008836 pthread_mutex_lock(&adev->lock);
8837 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308838 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8839 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008840 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308841 if( mode == AUDIO_MODE_CALL_SCREEN ){
8842 adev->current_call_output = adev->primary_output;
8843 voice_start_call(adev);
8844 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008845 (mode == AUDIO_MODE_NORMAL ||
8846 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008847 list_for_each(node, &adev->usecase_list) {
8848 usecase = node_to_item(node, struct audio_usecase, list);
8849 if (usecase->type == VOICE_CALL)
8850 break;
8851 }
8852 if (usecase &&
8853 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8854 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8855 true);
8856 if (ret != 0) {
8857 /* default service interval was successfully updated,
8858 reopen USB backend with new service interval */
8859 check_usecases_codec_backend(adev,
8860 usecase,
8861 usecase->out_snd_device);
8862 }
8863 }
8864
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008865 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008866 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008867 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008868 // restore device for other active usecases after stop call
8869 list_for_each(node, &adev->usecase_list) {
8870 usecase = node_to_item(node, struct audio_usecase, list);
8871 select_devices(adev, usecase->id);
8872 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008874 }
8875 pthread_mutex_unlock(&adev->lock);
8876 return 0;
8877}
8878
8879static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8880{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008881 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008882 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008883
8884 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008885 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008886 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008887
Derek Chend2530072014-11-24 12:39:14 -08008888 if (adev->ext_hw_plugin)
8889 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008890
8891 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008892 pthread_mutex_unlock(&adev->lock);
8893
8894 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008895}
8896
8897static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8898{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008899 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008900 return 0;
8901}
8902
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008903static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008904 const struct audio_config *config)
8905{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008906 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008907
Aalique Grahame22e49102018-12-18 14:23:57 -08008908 /* Don't know if USB HIFI in this context so use true to be conservative */
8909 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8910 true /*is_usb_hifi */) != 0)
8911 return 0;
8912
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008913 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8914 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008915}
8916
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008917static bool adev_input_allow_hifi_record(struct audio_device *adev,
8918 audio_devices_t devices,
8919 audio_input_flags_t flags,
8920 audio_source_t source) {
8921 const bool allowed = true;
8922
8923 if (!audio_is_usb_in_device(devices))
8924 return !allowed;
8925
8926 switch (flags) {
8927 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008928 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008929 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8930 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008931 default:
8932 return !allowed;
8933 }
8934
8935 switch (source) {
8936 case AUDIO_SOURCE_DEFAULT:
8937 case AUDIO_SOURCE_MIC:
8938 case AUDIO_SOURCE_UNPROCESSED:
8939 break;
8940 default:
8941 return !allowed;
8942 }
8943
8944 switch (adev->mode) {
8945 case 0:
8946 break;
8947 default:
8948 return !allowed;
8949 }
8950
8951 return allowed;
8952}
8953
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008954static int adev_update_voice_comm_input_stream(struct stream_in *in,
8955 struct audio_config *config)
8956{
8957 bool valid_rate = (config->sample_rate == 8000 ||
8958 config->sample_rate == 16000 ||
8959 config->sample_rate == 32000 ||
8960 config->sample_rate == 48000);
8961 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8962
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008963 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008964 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008965 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8966 in->config = default_pcm_config_voip_copp;
8967 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8968 DEFAULT_VOIP_BUF_DURATION_MS,
8969 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008970 } else {
8971 ALOGW("%s No valid input in voip, use defaults"
8972 "sample rate %u, channel mask 0x%X",
8973 __func__, config->sample_rate, in->channel_mask);
8974 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008975 in->config.rate = config->sample_rate;
8976 in->sample_rate = config->sample_rate;
8977 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008978 //XXX needed for voice_extn_compress_voip_open_input_stream
8979 in->config.rate = config->sample_rate;
8980 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308981 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008982 voice_extn_compress_voip_is_active(in->dev)) &&
8983 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8984 valid_rate && valid_ch) {
8985 voice_extn_compress_voip_open_input_stream(in);
8986 // update rate entries to match config from AF
8987 in->config.rate = config->sample_rate;
8988 in->sample_rate = config->sample_rate;
8989 } else {
8990 ALOGW("%s compress voip not active, use defaults", __func__);
8991 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008992 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008993 return 0;
8994}
8995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008997 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008998 audio_devices_t devices,
8999 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009000 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309001 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009002 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009003 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009004{
9005 struct audio_device *adev = (struct audio_device *)dev;
9006 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009007 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009008 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009009 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309010 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009011 bool is_usb_dev = audio_is_usb_in_device(devices);
9012 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9013 devices,
9014 flags,
9015 source);
Andy Hung94320602018-10-29 18:31:12 -07009016 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9017 " sample_rate %u, channel_mask %#x, format %#x",
9018 __func__, flags, is_usb_dev, may_use_hifi_record,
9019 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309020
kunleizdff872d2018-08-20 14:40:33 +08009021 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009022 is_usb_dev = false;
9023 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9024 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9025 __func__, devices);
9026 }
9027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009028 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009029
9030 if (!(is_usb_dev && may_use_hifi_record)) {
9031 if (config->sample_rate == 0)
9032 config->sample_rate = 48000;
9033 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9034 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9035 if (config->format == AUDIO_FORMAT_DEFAULT)
9036 config->format = AUDIO_FORMAT_PCM_16_BIT;
9037
9038 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9039
Aalique Grahame22e49102018-12-18 14:23:57 -08009040 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9041 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009042 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309043 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009044
Rahul Sharma99770982019-03-06 17:05:26 +05309045 pthread_mutex_lock(&adev->lock);
9046 if (in_get_stream(adev, handle) != NULL) {
9047 ALOGW("%s, input stream already opened", __func__);
9048 ret = -EEXIST;
9049 }
9050 pthread_mutex_unlock(&adev->lock);
9051 if (ret)
9052 return ret;
9053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009054 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009055
9056 if (!in) {
9057 ALOGE("failed to allocate input stream");
9058 return -ENOMEM;
9059 }
9060
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309061 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309062 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9063 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009064 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009065 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009067 in->stream.common.get_sample_rate = in_get_sample_rate;
9068 in->stream.common.set_sample_rate = in_set_sample_rate;
9069 in->stream.common.get_buffer_size = in_get_buffer_size;
9070 in->stream.common.get_channels = in_get_channels;
9071 in->stream.common.get_format = in_get_format;
9072 in->stream.common.set_format = in_set_format;
9073 in->stream.common.standby = in_standby;
9074 in->stream.common.dump = in_dump;
9075 in->stream.common.set_parameters = in_set_parameters;
9076 in->stream.common.get_parameters = in_get_parameters;
9077 in->stream.common.add_audio_effect = in_add_audio_effect;
9078 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9079 in->stream.set_gain = in_set_gain;
9080 in->stream.read = in_read;
9081 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009082 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309083 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009084 in->stream.set_microphone_direction = in_set_microphone_direction;
9085 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009086 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009087
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009088 list_init(&in->device_list);
9089 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009090 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009091 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009092 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009093 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009094 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009095 in->bit_width = 16;
9096 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009097 in->direction = MIC_DIRECTION_UNSPECIFIED;
9098 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009099 list_init(&in->aec_list);
9100 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009101 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009102
Andy Hung94320602018-10-29 18:31:12 -07009103 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009104 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9105 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9106 /* Force channel config requested to mono if incall
9107 record is being requested for only uplink/downlink */
9108 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9109 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9110 ret = -EINVAL;
9111 goto err_open;
9112 }
9113 }
9114
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009115 if (is_usb_dev && may_use_hifi_record) {
9116 /* HiFi record selects an appropriate format, channel, rate combo
9117 depending on sink capabilities*/
9118 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9119 &config->format,
9120 &in->supported_formats[0],
9121 MAX_SUPPORTED_FORMATS,
9122 &config->channel_mask,
9123 &in->supported_channel_masks[0],
9124 MAX_SUPPORTED_CHANNEL_MASKS,
9125 &config->sample_rate,
9126 &in->supported_sample_rates[0],
9127 MAX_SUPPORTED_SAMPLE_RATES);
9128 if (ret != 0) {
9129 ret = -EINVAL;
9130 goto err_open;
9131 }
9132 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009133 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309134 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309135 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9136 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9137 in->config.format = PCM_FORMAT_S32_LE;
9138 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309139 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9140 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9141 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9142 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9143 bool ret_error = false;
9144 in->bit_width = 24;
9145 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9146 from HAL is 24_packed and 8_24
9147 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9148 24_packed return error indicating supported format is 24_packed
9149 *> In case of any other source requesting 24 bit or float return error
9150 indicating format supported is 16 bit only.
9151
9152 on error flinger will retry with supported format passed
9153 */
9154 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9155 (source != AUDIO_SOURCE_CAMCORDER)) {
9156 config->format = AUDIO_FORMAT_PCM_16_BIT;
9157 if (config->sample_rate > 48000)
9158 config->sample_rate = 48000;
9159 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009160 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9161 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309162 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9163 ret_error = true;
9164 }
9165
9166 if (ret_error) {
9167 ret = -EINVAL;
9168 goto err_open;
9169 }
9170 }
9171
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009172 in->channel_mask = config->channel_mask;
9173 in->format = config->format;
9174
9175 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309176
9177 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9178 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9179 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9180 else {
9181 ret = -EINVAL;
9182 goto err_open;
9183 }
9184 }
9185
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009186 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309187 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9188 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009189 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9190 is_low_latency = true;
9191#if LOW_LATENCY_CAPTURE_USE_CASE
9192 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9193#endif
9194 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009195 if (!in->realtime) {
9196 in->config = pcm_config_audio_capture;
9197 frame_size = audio_stream_in_frame_size(&in->stream);
9198 buffer_size = get_input_buffer_size(config->sample_rate,
9199 config->format,
9200 channel_count,
9201 is_low_latency);
9202 in->config.period_size = buffer_size / frame_size;
9203 in->config.rate = config->sample_rate;
9204 in->af_period_multiplier = 1;
9205 } else {
9206 // period size is left untouched for rt mode playback
9207 in->config = pcm_config_audio_capture_rt;
9208 in->af_period_multiplier = af_period_multiplier;
9209 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009210 }
9211
9212 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9213 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9214 in->realtime = 0;
9215 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9216 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009217 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009218 in->stream.start = in_start;
9219 in->stream.stop = in_stop;
9220 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9221 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009222 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009223 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009224 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9225 in->config = pcm_config_audio_capture;
9226 frame_size = audio_stream_in_frame_size(&in->stream);
9227 buffer_size = get_input_buffer_size(config->sample_rate,
9228 config->format,
9229 channel_count,
9230 false /*is_low_latency*/);
9231 in->config.period_size = buffer_size / frame_size;
9232 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009233 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009234 switch (config->format) {
9235 case AUDIO_FORMAT_PCM_32_BIT:
9236 in->bit_width = 32;
9237 break;
9238 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9239 case AUDIO_FORMAT_PCM_8_24_BIT:
9240 in->bit_width = 24;
9241 break;
9242 default:
9243 in->bit_width = 16;
9244 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009245 } else if (is_single_device_type_equal(&in->device_list,
9246 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9247 is_single_device_type_equal(&in->device_list,
9248 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009249 if (config->sample_rate == 0)
9250 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9251 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9252 config->sample_rate != 8000) {
9253 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9254 ret = -EINVAL;
9255 goto err_open;
9256 }
9257 if (config->format == AUDIO_FORMAT_DEFAULT)
9258 config->format = AUDIO_FORMAT_PCM_16_BIT;
9259 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9260 config->format = AUDIO_FORMAT_PCM_16_BIT;
9261 ret = -EINVAL;
9262 goto err_open;
9263 }
9264
9265 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9266 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009267 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009268 in->af_period_multiplier = 1;
9269 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9270 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9271 (config->sample_rate == 8000 ||
9272 config->sample_rate == 16000 ||
9273 config->sample_rate == 32000 ||
9274 config->sample_rate == 48000) &&
9275 channel_count == 1) {
9276 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9277 in->config = pcm_config_audio_capture;
9278 frame_size = audio_stream_in_frame_size(&in->stream);
9279 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9280 config->sample_rate,
9281 config->format,
9282 channel_count, false /*is_low_latency*/);
9283 in->config.period_size = buffer_size / frame_size;
9284 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9285 in->config.rate = config->sample_rate;
9286 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009287 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309288 int ret_val;
9289 pthread_mutex_lock(&adev->lock);
9290 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9291 in, config, &channel_mask_updated);
9292 pthread_mutex_unlock(&adev->lock);
9293
9294 if (!ret_val) {
9295 if (channel_mask_updated == true) {
9296 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9297 __func__, config->channel_mask);
9298 ret = -EINVAL;
9299 goto err_open;
9300 }
9301 ALOGD("%s: created multi-channel session succesfully",__func__);
9302 } else if (audio_extn_compr_cap_enabled() &&
9303 audio_extn_compr_cap_format_supported(config->format) &&
9304 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9305 audio_extn_compr_cap_init(in);
9306 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309307 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309308 if (ret)
9309 goto err_open;
9310 } else {
9311 in->config = pcm_config_audio_capture;
9312 in->config.rate = config->sample_rate;
9313 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309314 in->format = config->format;
9315 frame_size = audio_stream_in_frame_size(&in->stream);
9316 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009317 config->format,
9318 channel_count,
9319 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009320 /* prevent division-by-zero */
9321 if (frame_size == 0) {
9322 ALOGE("%s: Error frame_size==0", __func__);
9323 ret = -EINVAL;
9324 goto err_open;
9325 }
9326
Revathi Uddarajud2634032017-12-07 14:42:34 +05309327 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009328 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009329
Revathi Uddarajud2634032017-12-07 14:42:34 +05309330 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9331 /* optionally use VOIP usecase depending on config(s) */
9332 ret = adev_update_voice_comm_input_stream(in, config);
9333 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009334
Revathi Uddarajud2634032017-12-07 14:42:34 +05309335 if (ret) {
9336 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9337 goto err_open;
9338 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009339 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309340
9341 /* assign concurrent capture usecase if record has to caried out from
9342 * actual hardware input source */
9343 if (audio_extn_is_concurrent_capture_enabled() &&
9344 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309345 /* Acquire lock to avoid two concurrent use cases initialized to
9346 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009347
Samyak Jainc37062f2019-04-25 18:41:06 +05309348 if (in->usecase == USECASE_AUDIO_RECORD) {
9349 pthread_mutex_lock(&adev->lock);
9350 if (!(adev->pcm_record_uc_state)) {
9351 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9352 adev->pcm_record_uc_state = 1;
9353 pthread_mutex_unlock(&adev->lock);
9354 } else {
9355 pthread_mutex_unlock(&adev->lock);
9356 /* Assign compress record use case for second record */
9357 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9358 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9359 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9360 if (audio_extn_cin_applicable_stream(in)) {
9361 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309362 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309363 if (ret)
9364 goto err_open;
9365 }
9366 }
9367 }
kunleiz28c73e72019-03-27 17:24:04 +08009368 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009369 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309370 if (audio_extn_ssr_get_stream() != in)
9371 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009372
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009373 in->sample_rate = in->config.rate;
9374
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309375 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9376 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009377 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009378 in->sample_rate, in->bit_width,
9379 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309380 register_format(in->format, in->supported_formats);
9381 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9382 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309383
Aalique Grahame22e49102018-12-18 14:23:57 -08009384 in->error_log = error_log_create(
9385 ERROR_LOG_ENTRIES,
9386 1000000000 /* aggregate consecutive identical errors within one second */);
9387
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009388 /* This stream could be for sound trigger lab,
9389 get sound trigger pcm if present */
9390 audio_extn_sound_trigger_check_and_get_session(in);
9391
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309392 lock_input_stream(in);
9393 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9394 pthread_mutex_lock(&adev->lock);
9395 in->card_status = adev->card_status;
9396 pthread_mutex_unlock(&adev->lock);
9397 pthread_mutex_unlock(&in->lock);
9398
Aalique Grahame22e49102018-12-18 14:23:57 -08009399 stream_app_type_cfg_init(&in->app_type_cfg);
9400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009401 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009402
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009403 ret = io_streams_map_insert(adev, &in->stream.common,
9404 handle, AUDIO_PATCH_HANDLE_NONE);
9405 if (ret != 0)
9406 goto err_open;
9407
Derek Chenf939fb72018-11-13 13:34:41 -08009408 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9409 calloc(1, sizeof(streams_input_ctxt_t));
9410 if (in_ctxt == NULL) {
9411 ALOGE("%s fail to allocate input ctxt", __func__);
9412 ret = -ENOMEM;
9413 goto err_open;
9414 }
9415 in_ctxt->input = in;
9416
9417 pthread_mutex_lock(&adev->lock);
9418 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9419 pthread_mutex_unlock(&adev->lock);
9420
Eric Laurent994a6932013-07-17 11:51:42 -07009421 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009422 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009423
9424err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309425 if (in->usecase == USECASE_AUDIO_RECORD) {
9426 pthread_mutex_lock(&adev->lock);
9427 adev->pcm_record_uc_state = 0;
9428 pthread_mutex_unlock(&adev->lock);
9429 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009430 free(in);
9431 *stream_in = NULL;
9432 return ret;
9433}
9434
9435static void adev_close_input_stream(struct audio_hw_device *dev,
9436 struct audio_stream_in *stream)
9437{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009438 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009439 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009440 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309441
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309442 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009443
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009444 if (in == NULL) {
9445 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9446 return;
9447 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009448 io_streams_map_remove(adev, in->capture_handle);
9449
kunleiz70e57612018-12-28 17:50:23 +08009450 /* must deregister from sndmonitor first to prevent races
9451 * between the callback and close_stream
9452 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309453 audio_extn_snd_mon_unregister_listener(stream);
9454
kunleiz70e57612018-12-28 17:50:23 +08009455 /* Disable echo reference if there are no active input, hfp call
9456 * and sound trigger while closing input stream
9457 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009458 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009459 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009460 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9461 struct listnode out_devices;
9462 list_init(&out_devices);
9463 platform_set_echo_reference(adev, false, &out_devices);
9464 } else
kunleiz70e57612018-12-28 17:50:23 +08009465 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309466
Weiyin Jiang2995f662019-04-17 14:25:12 +08009467 error_log_destroy(in->error_log);
9468 in->error_log = NULL;
9469
Pallavid7c7a272018-01-16 11:22:55 +05309470
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009471 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309472 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009473 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309474 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009475 if (ret != 0)
9476 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9477 __func__, ret);
9478 } else
9479 in_standby(&stream->common);
9480
Revathi Uddarajud2634032017-12-07 14:42:34 +05309481 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309482 if (in->usecase == USECASE_AUDIO_RECORD) {
9483 adev->pcm_record_uc_state = 0;
9484 }
9485
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009486 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9487 adev->enable_voicerx = false;
9488 }
9489
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009490 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009491 audio_extn_ssr_deinit();
9492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009493
Garmond Leunge2433c32017-09-28 21:51:22 -07009494 if (audio_extn_ffv_get_stream() == in) {
9495 audio_extn_ffv_stream_deinit();
9496 }
9497
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309498 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009499 audio_extn_compr_cap_format_supported(in->config.format))
9500 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309501
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309502 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309503 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009504
Mingming Yinfd7607b2016-01-22 12:48:44 -08009505 if (in->is_st_session) {
9506 ALOGV("%s: sound trigger pcm stop lab", __func__);
9507 audio_extn_sound_trigger_stop_lab(in);
9508 }
Derek Chenf939fb72018-11-13 13:34:41 -08009509 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9510 if (in_ctxt != NULL) {
9511 list_remove(&in_ctxt->list);
9512 free(in_ctxt);
9513 } else {
9514 ALOGW("%s, input stream already closed", __func__);
9515 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009516 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309517 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009518 return;
9519}
9520
Aalique Grahame22e49102018-12-18 14:23:57 -08009521/* verifies input and output devices and their capabilities.
9522 *
9523 * This verification is required when enabling extended bit-depth or
9524 * sampling rates, as not all qcom products support it.
9525 *
9526 * Suitable for calling only on initialization such as adev_open().
9527 * It fills the audio_device use_case_table[] array.
9528 *
9529 * Has a side-effect that it needs to configure audio routing / devices
9530 * in order to power up the devices and read the device parameters.
9531 * It does not acquire any hw device lock. Should restore the devices
9532 * back to "normal state" upon completion.
9533 */
9534static int adev_verify_devices(struct audio_device *adev)
9535{
9536 /* enumeration is a bit difficult because one really wants to pull
9537 * the use_case, device id, etc from the hidden pcm_device_table[].
9538 * In this case there are the following use cases and device ids.
9539 *
9540 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9541 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9542 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9543 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9544 * [USECASE_AUDIO_RECORD] = {0, 0},
9545 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9546 * [USECASE_VOICE_CALL] = {2, 2},
9547 *
9548 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9549 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9550 */
9551
9552 /* should be the usecases enabled in adev_open_input_stream() */
9553 static const int test_in_usecases[] = {
9554 USECASE_AUDIO_RECORD,
9555 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9556 };
9557 /* should be the usecases enabled in adev_open_output_stream()*/
9558 static const int test_out_usecases[] = {
9559 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9560 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9561 };
9562 static const usecase_type_t usecase_type_by_dir[] = {
9563 PCM_PLAYBACK,
9564 PCM_CAPTURE,
9565 };
9566 static const unsigned flags_by_dir[] = {
9567 PCM_OUT,
9568 PCM_IN,
9569 };
9570
9571 size_t i;
9572 unsigned dir;
9573 const unsigned card_id = adev->snd_card;
9574
9575 for (dir = 0; dir < 2; ++dir) {
9576 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9577 const unsigned flags_dir = flags_by_dir[dir];
9578 const size_t testsize =
9579 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9580 const int *testcases =
9581 dir ? test_in_usecases : test_out_usecases;
9582 const audio_devices_t audio_device =
9583 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9584
9585 for (i = 0; i < testsize; ++i) {
9586 const audio_usecase_t audio_usecase = testcases[i];
9587 int device_id;
9588 struct pcm_params **pparams;
9589 struct stream_out out;
9590 struct stream_in in;
9591 struct audio_usecase uc_info;
9592 int retval;
9593
9594 pparams = &adev->use_case_table[audio_usecase];
9595 pcm_params_free(*pparams); /* can accept null input */
9596 *pparams = NULL;
9597
9598 /* find the device ID for the use case (signed, for error) */
9599 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9600 if (device_id < 0)
9601 continue;
9602
9603 /* prepare structures for device probing */
9604 memset(&uc_info, 0, sizeof(uc_info));
9605 uc_info.id = audio_usecase;
9606 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009607 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009608 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009609 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009610 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009611 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009612 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9613 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009614 }
9615 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009616 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009617 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009618 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009619 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009620 uc_info.in_snd_device = SND_DEVICE_NONE;
9621 uc_info.out_snd_device = SND_DEVICE_NONE;
9622 list_add_tail(&adev->usecase_list, &uc_info.list);
9623
9624 /* select device - similar to start_(in/out)put_stream() */
9625 retval = select_devices(adev, audio_usecase);
9626 if (retval >= 0) {
9627 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9628#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009629 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009630 if (*pparams) {
9631 ALOGV("%s: (%s) card %d device %d", __func__,
9632 dir ? "input" : "output", card_id, device_id);
9633 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9634 } else {
9635 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9636 }
9637#endif
9638 }
9639
9640 /* deselect device - similar to stop_(in/out)put_stream() */
9641 /* 1. Get and set stream specific mixer controls */
9642 retval = disable_audio_route(adev, &uc_info);
9643 /* 2. Disable the rx device */
9644 retval = disable_snd_device(adev,
9645 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9646 list_remove(&uc_info.list);
9647 }
9648 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009649 return 0;
9650}
9651
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009652int update_patch(unsigned int num_sources,
9653 const struct audio_port_config *sources,
9654 unsigned int num_sinks,
9655 const struct audio_port_config *sinks,
9656 audio_patch_handle_t handle,
9657 struct audio_patch_info *p_info,
9658 patch_type_t patch_type, bool new_patch)
9659{
9660 ALOGD("%s: enter", __func__);
9661
9662 if (p_info == NULL) {
9663 ALOGE("%s: Invalid patch pointer", __func__);
9664 return -EINVAL;
9665 }
9666
9667 if (new_patch) {
9668 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9669 if (p_info->patch == NULL) {
9670 ALOGE("%s: Could not allocate patch", __func__);
9671 return -ENOMEM;
9672 }
9673 }
9674
9675 p_info->patch->id = handle;
9676 p_info->patch->num_sources = num_sources;
9677 p_info->patch->num_sinks = num_sinks;
9678
9679 for (int i = 0; i < num_sources; i++)
9680 p_info->patch->sources[i] = sources[i];
9681 for (int i = 0; i < num_sinks; i++)
9682 p_info->patch->sinks[i] = sinks[i];
9683
9684 p_info->patch_type = patch_type;
9685 return 0;
9686}
9687
9688audio_patch_handle_t generate_patch_handle()
9689{
9690 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9691 if (++patch_handle < 0)
9692 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9693 return patch_handle;
9694}
9695
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309696int adev_create_audio_patch(struct audio_hw_device *dev,
9697 unsigned int num_sources,
9698 const struct audio_port_config *sources,
9699 unsigned int num_sinks,
9700 const struct audio_port_config *sinks,
9701 audio_patch_handle_t *handle)
9702{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009703 int ret = 0;
9704 struct audio_device *adev = (struct audio_device *)dev;
9705 struct audio_patch_info *p_info = NULL;
9706 patch_type_t patch_type = PATCH_NONE;
9707 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9708 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9709 struct audio_stream_info *s_info = NULL;
9710 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009711 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009712 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9713 bool new_patch = false;
9714 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309715
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009716 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9717 num_sources, num_sinks, *handle);
9718
9719 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9720 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9721 ALOGE("%s: Invalid patch arguments", __func__);
9722 ret = -EINVAL;
9723 goto done;
9724 }
9725
9726 if (num_sources > 1) {
9727 ALOGE("%s: Multiple sources are not supported", __func__);
9728 ret = -EINVAL;
9729 goto done;
9730 }
9731
9732 if (sources == NULL || sinks == NULL) {
9733 ALOGE("%s: Invalid sources or sinks port config", __func__);
9734 ret = -EINVAL;
9735 goto done;
9736 }
9737
9738 ALOGV("%s: source role %d, source type %d", __func__,
9739 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009740 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009741
9742 // Populate source/sink information and fetch stream info
9743 switch (sources[0].type) {
9744 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9745 device_type = sources[0].ext.device.type;
9746 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009747 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009748 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9749 patch_type = PATCH_CAPTURE;
9750 io_handle = sinks[0].ext.mix.handle;
9751 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009752 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009753 __func__, device_type, io_handle);
9754 } else {
9755 // Device to device patch is not implemented.
9756 // This space will need changes if audio HAL
9757 // handles device to device patches in the future.
9758 patch_type = PATCH_DEVICE_LOOPBACK;
9759 }
9760 break;
9761 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9762 io_handle = sources[0].ext.mix.handle;
9763 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009764 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009765 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009766 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009767 }
9768 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009769 ALOGD("%s: Playback patch from mix handle %d to device %x",
9770 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009771 break;
9772 case AUDIO_PORT_TYPE_SESSION:
9773 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009774 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9775 ret = -EINVAL;
9776 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009777 }
9778
9779 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009780
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009781 // Generate patch info and update patch
9782 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009783 *handle = generate_patch_handle();
9784 p_info = (struct audio_patch_info *)
9785 calloc(1, sizeof(struct audio_patch_info));
9786 if (p_info == NULL) {
9787 ALOGE("%s: Failed to allocate memory", __func__);
9788 pthread_mutex_unlock(&adev->lock);
9789 ret = -ENOMEM;
9790 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009791 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009792 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009793 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009794 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009795 if (p_info == NULL) {
9796 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9797 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009798 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009799 ret = -EINVAL;
9800 goto done;
9801 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009802 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009803 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009804 *handle, p_info, patch_type, new_patch);
9805
9806 // Fetch stream info of associated mix for playback or capture patches
9807 if (p_info->patch_type == PATCH_PLAYBACK ||
9808 p_info->patch_type == PATCH_CAPTURE) {
9809 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9810 if (s_info == NULL) {
9811 ALOGE("%s: Failed to obtain stream info", __func__);
9812 if (new_patch)
9813 free(p_info);
9814 pthread_mutex_unlock(&adev->lock);
9815 ret = -EINVAL;
9816 goto done;
9817 }
9818 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9819 s_info->patch_handle = *handle;
9820 stream = s_info->stream;
9821 }
9822 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009823
9824 // Update routing for stream
9825 if (stream != NULL) {
9826 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009827 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009828 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009829 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009830 if (ret < 0) {
9831 pthread_mutex_lock(&adev->lock);
9832 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9833 if (new_patch)
9834 free(p_info);
9835 pthread_mutex_unlock(&adev->lock);
9836 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9837 goto done;
9838 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009839 }
9840
9841 // Add new patch to patch map
9842 if (!ret && new_patch) {
9843 pthread_mutex_lock(&adev->lock);
9844 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009845 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009846 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009847 }
9848
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009849done:
9850 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009851 num_sources,
9852 sources,
9853 num_sinks,
9854 sinks,
9855 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009856 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009857 num_sources,
9858 sources,
9859 num_sinks,
9860 sinks,
9861 handle);
9862 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309863}
9864
9865int adev_release_audio_patch(struct audio_hw_device *dev,
9866 audio_patch_handle_t handle)
9867{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009868 struct audio_device *adev = (struct audio_device *) dev;
9869 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009870 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009871 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009872
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009873 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9874 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9875 ret = -EINVAL;
9876 goto done;
9877 }
9878
9879 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009880 pthread_mutex_lock(&adev->lock);
9881 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009882 if (p_info == NULL) {
9883 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009884 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009885 ret = -EINVAL;
9886 goto done;
9887 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009888 struct audio_patch *patch = p_info->patch;
9889 if (patch == NULL) {
9890 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009891 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009892 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009893 goto done;
9894 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009895 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9896 switch (patch->sources[0].type) {
9897 case AUDIO_PORT_TYPE_MIX:
9898 io_handle = patch->sources[0].ext.mix.handle;
9899 break;
9900 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009901 if (p_info->patch_type == PATCH_CAPTURE)
9902 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009903 break;
9904 case AUDIO_PORT_TYPE_SESSION:
9905 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009906 pthread_mutex_unlock(&adev->lock);
9907 ret = -EINVAL;
9908 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009909 }
9910
9911 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009912 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009913 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009914 if (patch_type == PATCH_PLAYBACK ||
9915 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009916 struct audio_stream_info *s_info =
9917 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9918 if (s_info == NULL) {
9919 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9920 pthread_mutex_unlock(&adev->lock);
9921 goto done;
9922 }
9923 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9924 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009925 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009926 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009927
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009928 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009929 struct listnode devices;
9930 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009931 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009932 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009933 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009934 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009935 }
9936
9937 if (ret < 0)
9938 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9939
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009940done:
9941 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9942 audio_extn_auto_hal_release_audio_patch(dev, handle);
9943
9944 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009945 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309946}
9947
9948int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9949{
Derek Chenf13dd492018-11-13 14:53:51 -08009950 int ret = 0;
9951
9952 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9953 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9954 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309955}
9956
9957int adev_set_audio_port_config(struct audio_hw_device *dev,
9958 const struct audio_port_config *config)
9959{
Derek Chenf13dd492018-11-13 14:53:51 -08009960 int ret = 0;
9961
9962 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9963 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9964 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309965}
9966
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009967static int adev_dump(const audio_hw_device_t *device __unused,
9968 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009969{
9970 return 0;
9971}
9972
9973static int adev_close(hw_device_t *device)
9974{
Aalique Grahame22e49102018-12-18 14:23:57 -08009975 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309976 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009977
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309978 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009979 return 0;
9980
9981 pthread_mutex_lock(&adev_init_lock);
9982
9983 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309984 if (audio_extn_spkr_prot_is_enabled())
9985 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309986 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309987 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009988 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009989 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009990 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009991 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309992 audio_extn_utils_release_streams_cfg_lists(
9993 &adev->streams_output_cfg_list,
9994 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309995 if (audio_extn_qap_is_enabled())
9996 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309997 if (audio_extn_qaf_is_enabled())
9998 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009999 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010000 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010001 free(adev->snd_dev_ref_cnt);
10002 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010003 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10004 pcm_params_free(adev->use_case_table[i]);
10005 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010006 if (adev->adm_deinit)
10007 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010008 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010009 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010010 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010011 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010012 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010013 if (adev->device_cfg_params) {
10014 free(adev->device_cfg_params);
10015 adev->device_cfg_params = NULL;
10016 }
Derek Chend2530072014-11-24 12:39:14 -080010017 if(adev->ext_hw_plugin)
10018 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010019 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010020 free_map(adev->patch_map);
10021 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010022 free(device);
10023 adev = NULL;
10024 }
10025 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010026 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010027 return 0;
10028}
10029
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010030/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10031 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10032 * just that it _might_ work.
10033 */
10034static int period_size_is_plausible_for_low_latency(int period_size)
10035{
10036 switch (period_size) {
10037 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010038 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010039 case 240:
10040 case 320:
10041 case 480:
10042 return 1;
10043 default:
10044 return 0;
10045 }
10046}
10047
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010048static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10049{
10050 bool is_snd_card_status = false;
10051 bool is_ext_device_status = false;
10052 char value[32];
10053 int card = -1;
10054 card_status_t status;
10055
10056 if (cookie != adev || !parms)
10057 return;
10058
10059 if (!parse_snd_card_status(parms, &card, &status)) {
10060 is_snd_card_status = true;
10061 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10062 is_ext_device_status = true;
10063 } else {
10064 // not a valid event
10065 return;
10066 }
10067
10068 pthread_mutex_lock(&adev->lock);
10069 if (card == adev->snd_card || is_ext_device_status) {
10070 if (is_snd_card_status && adev->card_status != status) {
10071 adev->card_status = status;
10072 platform_snd_card_update(adev->platform, status);
10073 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010074 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010075 if (status == CARD_STATUS_OFFLINE)
10076 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010077 } else if (is_ext_device_status) {
10078 platform_set_parameters(adev->platform, parms);
10079 }
10080 }
10081 pthread_mutex_unlock(&adev->lock);
10082 return;
10083}
10084
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010085/* out and adev lock held */
10086static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10087{
10088 struct audio_usecase *uc_info;
10089 float left_p;
10090 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010091 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010092
10093 uc_info = get_usecase_from_list(adev, out->usecase);
10094 if (uc_info == NULL) {
10095 ALOGE("%s: Could not find the usecase (%d) in the list",
10096 __func__, out->usecase);
10097 return -EINVAL;
10098 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010099 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010100
10101 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10102 out->usecase, use_case_table[out->usecase]);
10103
10104 if (restore) {
10105 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010106 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010107 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010108 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10109 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010110 pthread_mutex_lock(&out->compr_mute_lock);
10111 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010112 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010113 out->a2dp_compress_mute = false;
10114 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10115 }
10116 pthread_mutex_unlock(&out->compr_mute_lock);
10117 }
10118 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010119 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10120 // mute compress stream if suspended
10121 pthread_mutex_lock(&out->compr_mute_lock);
10122 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010123 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010124 assign_devices(&devices, &out->device_list);
10125 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010126 left_p = out->volume_l;
10127 right_p = out->volume_r;
10128 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10129 compress_pause(out->compr);
10130 out_set_compr_volume(&out->stream, (float)0, (float)0);
10131 out->a2dp_compress_mute = true;
10132 select_devices(adev, out->usecase);
10133 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10134 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010135 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010136 out->volume_l = left_p;
10137 out->volume_r = right_p;
10138 }
Zhou Songc576a452019-09-09 14:17:40 +080010139 pthread_mutex_unlock(&out->compr_mute_lock);
10140 } else {
10141 // tear down a2dp path for non offloaded streams
10142 if (audio_extn_a2dp_source_is_suspended())
10143 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010144 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010145 }
10146 ALOGV("%s: exit", __func__);
10147 return 0;
10148}
10149
10150int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10151{
10152 int ret = 0;
10153
10154 lock_output_stream(out);
10155 pthread_mutex_lock(&adev->lock);
10156
10157 ret = check_a2dp_restore_l(adev, out, restore);
10158
10159 pthread_mutex_unlock(&adev->lock);
10160 pthread_mutex_unlock(&out->lock);
10161 return ret;
10162}
10163
Haynes Mathew George01156f92018-04-13 15:29:54 -070010164void adev_on_battery_status_changed(bool charging)
10165{
10166 pthread_mutex_lock(&adev->lock);
10167 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10168 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010169 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010170 pthread_mutex_unlock(&adev->lock);
10171}
10172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010173static int adev_open(const hw_module_t *module, const char *name,
10174 hw_device_t **device)
10175{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010176 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010177 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010178 char mixer_ctl_name[128] = {0};
10179 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010180
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010181 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010182 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10183
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010184 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010185 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010186 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010187 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010188 ALOGD("%s: returning existing instance of adev", __func__);
10189 ALOGD("%s: exit", __func__);
10190 pthread_mutex_unlock(&adev_init_lock);
10191 return 0;
10192 }
10193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010194 adev = calloc(1, sizeof(struct audio_device));
10195
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010196 if (!adev) {
10197 pthread_mutex_unlock(&adev_init_lock);
10198 return -ENOMEM;
10199 }
10200
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010201 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10202
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010203 // register audio ext hidl at the earliest
10204 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010205#ifdef DYNAMIC_LOG_ENABLED
10206 register_for_dynamic_logging("hal");
10207#endif
10208
Derek Chenf939fb72018-11-13 13:34:41 -080010209 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010210 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010211 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10212 maj_version = atoi(value);
10213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010214 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010215 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010216 adev->device.common.module = (struct hw_module_t *)module;
10217 adev->device.common.close = adev_close;
10218
10219 adev->device.init_check = adev_init_check;
10220 adev->device.set_voice_volume = adev_set_voice_volume;
10221 adev->device.set_master_volume = adev_set_master_volume;
10222 adev->device.get_master_volume = adev_get_master_volume;
10223 adev->device.set_master_mute = adev_set_master_mute;
10224 adev->device.get_master_mute = adev_get_master_mute;
10225 adev->device.set_mode = adev_set_mode;
10226 adev->device.set_mic_mute = adev_set_mic_mute;
10227 adev->device.get_mic_mute = adev_get_mic_mute;
10228 adev->device.set_parameters = adev_set_parameters;
10229 adev->device.get_parameters = adev_get_parameters;
10230 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10231 adev->device.open_output_stream = adev_open_output_stream;
10232 adev->device.close_output_stream = adev_close_output_stream;
10233 adev->device.open_input_stream = adev_open_input_stream;
10234 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010235 adev->device.create_audio_patch = adev_create_audio_patch;
10236 adev->device.release_audio_patch = adev_release_audio_patch;
10237 adev->device.get_audio_port = adev_get_audio_port;
10238 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010239 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010240 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010241
10242 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010243 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010244 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010245 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010246 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010247 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010248 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010249 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010250 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010251 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010252 /* Init audio and voice feature */
10253 audio_extn_feature_init();
10254 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010255 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010256 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010257 list_init(&adev->active_inputs_list);
10258 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010259 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010260 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10261 audio_extn_utils_hash_eq);
10262 if (!adev->io_streams_map) {
10263 ALOGE("%s: Could not create io streams map", __func__);
10264 ret = -ENOMEM;
10265 goto adev_open_err;
10266 }
10267 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10268 audio_extn_utils_hash_eq);
10269 if (!adev->patch_map) {
10270 ALOGE("%s: Could not create audio patch map", __func__);
10271 ret = -ENOMEM;
10272 goto adev_open_err;
10273 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010274 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010275 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010276 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010277 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010278 adev->perf_lock_opts[0] = 0x101;
10279 adev->perf_lock_opts[1] = 0x20E;
10280 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010281 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010282 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010283 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010284 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010285
Zhou Song68ebc352019-12-05 17:11:15 +080010286 audio_extn_perf_lock_init();
10287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010288 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010289 adev->platform = platform_init(adev);
10290 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010291 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010292 ret = -EINVAL;
10293 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010294 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010295
Aalique Grahame22e49102018-12-18 14:23:57 -080010296 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010297 if (audio_extn_qap_is_enabled()) {
10298 ret = audio_extn_qap_init(adev);
10299 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010300 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010301 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010302 }
10303 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10304 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10305 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010306
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010307 if (audio_extn_qaf_is_enabled()) {
10308 ret = audio_extn_qaf_init(adev);
10309 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010310 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010311 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010312 }
10313
10314 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10315 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10316 }
10317
Derek Chenae7b0342019-02-08 15:17:04 -080010318 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010319 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10320
Eric Laurentc4aef752013-09-12 17:45:53 -070010321 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10322 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10323 if (adev->visualizer_lib == NULL) {
10324 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10325 } else {
10326 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10327 adev->visualizer_start_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_start_output");
10330 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010331 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010332 "visualizer_hal_stop_output");
10333 }
10334 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010335 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010336 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010337 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010338 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010339 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010340 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010341
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010342 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10343 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10344 if (adev->offload_effects_lib == NULL) {
10345 ALOGE("%s: DLOPEN failed for %s", __func__,
10346 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10347 } else {
10348 ALOGV("%s: DLOPEN successful for %s", __func__,
10349 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10350 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010351 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010352 "offload_effects_bundle_hal_start_output");
10353 adev->offload_effects_stop_output =
10354 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10355 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010356 adev->offload_effects_set_hpx_state =
10357 (int (*)(bool))dlsym(adev->offload_effects_lib,
10358 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010359 adev->offload_effects_get_parameters =
10360 (void (*)(struct str_parms *, struct str_parms *))
10361 dlsym(adev->offload_effects_lib,
10362 "offload_effects_bundle_get_parameters");
10363 adev->offload_effects_set_parameters =
10364 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10365 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010366 }
10367 }
10368
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010369 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10370 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10371 if (adev->adm_lib == NULL) {
10372 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10373 } else {
10374 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10375 adev->adm_init = (adm_init_t)
10376 dlsym(adev->adm_lib, "adm_init");
10377 adev->adm_deinit = (adm_deinit_t)
10378 dlsym(adev->adm_lib, "adm_deinit");
10379 adev->adm_register_input_stream = (adm_register_input_stream_t)
10380 dlsym(adev->adm_lib, "adm_register_input_stream");
10381 adev->adm_register_output_stream = (adm_register_output_stream_t)
10382 dlsym(adev->adm_lib, "adm_register_output_stream");
10383 adev->adm_deregister_stream = (adm_deregister_stream_t)
10384 dlsym(adev->adm_lib, "adm_deregister_stream");
10385 adev->adm_request_focus = (adm_request_focus_t)
10386 dlsym(adev->adm_lib, "adm_request_focus");
10387 adev->adm_abandon_focus = (adm_abandon_focus_t)
10388 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010389 adev->adm_set_config = (adm_set_config_t)
10390 dlsym(adev->adm_lib, "adm_set_config");
10391 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10392 dlsym(adev->adm_lib, "adm_request_focus_v2");
10393 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10394 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10395 adev->adm_on_routing_change = (adm_on_routing_change_t)
10396 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010397 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10398 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010399 }
10400 }
10401
Aalique Grahame22e49102018-12-18 14:23:57 -080010402 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010403 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010404 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010405 //initialize this to false for now,
10406 //this will be set to true through set param
10407 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010408
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010409 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010410 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010411
10412 if (k_enable_extended_precision)
10413 adev_verify_devices(adev);
10414
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010415 adev->dsp_bit_width_enforce_mode =
10416 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010417
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010418 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10419 &adev->streams_output_cfg_list,
10420 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010421
Kiran Kandi910e1862013-10-29 13:29:42 -070010422 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010423
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010424 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010425 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010426 trial = atoi(value);
10427 if (period_size_is_plausible_for_low_latency(trial)) {
10428 pcm_config_low_latency.period_size = trial;
10429 pcm_config_low_latency.start_threshold = trial / 4;
10430 pcm_config_low_latency.avail_min = trial / 4;
10431 configured_low_latency_capture_period_size = trial;
10432 }
10433 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010434 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10435 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010436 trial = atoi(value);
10437 if (period_size_is_plausible_for_low_latency(trial)) {
10438 configured_low_latency_capture_period_size = trial;
10439 }
10440 }
10441
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010442 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10443
Eric Laurent4b084132018-10-19 17:33:43 -070010444 adev->camera_orientation = CAMERA_DEFAULT;
10445
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010446 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010447 af_period_multiplier = atoi(value);
10448 if (af_period_multiplier < 0)
10449 af_period_multiplier = 2;
10450 else if (af_period_multiplier > 4)
10451 af_period_multiplier = 4;
10452
10453 ALOGV("new period_multiplier = %d", af_period_multiplier);
10454 }
10455
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010456 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010457
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010458 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010459 pthread_mutex_unlock(&adev_init_lock);
10460
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010461 if (adev->adm_init)
10462 adev->adm_data = adev->adm_init();
10463
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010464 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010465 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010466
10467 audio_extn_snd_mon_init();
10468 pthread_mutex_lock(&adev->lock);
10469 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10470 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010471 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10472 /*
10473 * if the battery state callback happens before charging can be queried,
10474 * it will be guarded with the adev->lock held in the cb function and so
10475 * the callback value will reflect the latest state
10476 */
10477 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010478 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010479 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010480 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010481 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010482 /* Allocate memory for Device config params */
10483 adev->device_cfg_params = (struct audio_device_config_param*)
10484 calloc(platform_get_max_codec_backend(),
10485 sizeof(struct audio_device_config_param));
10486 if (adev->device_cfg_params == NULL)
10487 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010488
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010489 /*
10490 * Check if new PSPD matrix mixer control is supported. If not
10491 * supported, then set flag so that old mixer ctrl is sent while
10492 * sending pspd coefficients on older kernel version. Query mixer
10493 * control for default pcm id and channel value one.
10494 */
10495 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10496 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10497
10498 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10499 if (!ctl) {
10500 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10501 __func__, mixer_ctl_name);
10502 adev->use_old_pspd_mix_ctrl = true;
10503 }
10504
Eric Laurent994a6932013-07-17 11:51:42 -070010505 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010506 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010507
10508adev_open_err:
10509 free_map(adev->patch_map);
10510 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010511 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010512 pthread_mutex_destroy(&adev->lock);
10513 free(adev);
10514 adev = NULL;
10515 *device = NULL;
10516 pthread_mutex_unlock(&adev_init_lock);
10517 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010518}
10519
10520static struct hw_module_methods_t hal_module_methods = {
10521 .open = adev_open,
10522};
10523
10524struct audio_module HAL_MODULE_INFO_SYM = {
10525 .common = {
10526 .tag = HARDWARE_MODULE_TAG,
10527 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10528 .hal_api_version = HARDWARE_HAL_API_VERSION,
10529 .id = AUDIO_HARDWARE_MODULE_ID,
10530 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010531 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010532 .methods = &hal_module_methods,
10533 },
10534};