blob: 27e2fa3a0d4f2a7e4e7f96398cb6cd9704b82ef4 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, 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
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#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"
Balázs Triszkaa68afd52017-05-11 03:19:29 +020078#include "ultrasound.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
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",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700361 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700362
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700363 [USECASE_VOICE2_CALL] = "voice2-call",
364 [USECASE_VOLTE_CALL] = "volte-call",
365 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800366 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800367 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
368 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800369 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700370 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
371 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
372 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800373 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
374 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
375 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
376
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700377 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
378 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700379 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
380 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700381
382 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
383 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530384 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700385
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530386 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530387 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
388 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700389
390 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
391 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530392 /* For Interactive Audio Streams */
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700401
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800402 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
403
Derek Chenf6318be2017-06-12 17:16:24 -0400404 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
405
406 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
407 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
408 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
409 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530410 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Balázs Triszkaa68afd52017-05-11 03:19:29 +0200411
412 /* For Elliptic Ultrasound proximity sensor */
413 [USECASE_AUDIO_ULTRASOUND_RX] = "ultrasound-rx",
414 [USECASE_AUDIO_ULTRASOUND_TX] = "ultrasound-tx",
Eric Laurentb23d5282013-05-14 15:27:20 -0700415};
416
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700417static const audio_usecase_t offload_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700419 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428
Varun Balaraje49253e2017-07-06 19:48:56 +0530429static const audio_usecase_t interactive_usecases[] = {
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
438};
439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800440#define STRING_TO_ENUM(string) { #string, string }
441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442struct string_to_enum {
443 const char *name;
444 uint32_t value;
445};
446
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700447static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
458 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800467};
468
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700469static const struct string_to_enum formats_name_to_enum_table[] = {
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
472 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700473 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
475 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800477 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
478 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800480};
481
482//list of all supported sample rates by HDMI specification.
483static const int out_hdmi_sample_rates[] = {
484 32000, 44100, 48000, 88200, 96000, 176400, 192000,
485};
486
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700487static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800488 STRING_TO_ENUM(32000),
489 STRING_TO_ENUM(44100),
490 STRING_TO_ENUM(48000),
491 STRING_TO_ENUM(88200),
492 STRING_TO_ENUM(96000),
493 STRING_TO_ENUM(176400),
494 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700495};
496
Carter Hsu2e429db2019-05-14 18:50:52 +0800497struct in_effect_list {
498 struct listnode list;
499 effect_handle_t handle;
500};
501
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700502static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700503static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700504static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700505//cache last MBDRC cal step level
506static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700507
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530508static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
509static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700510static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800511static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530512static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530513
Derek Chen6f293672019-04-01 01:40:24 -0700514static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
515static void in_snd_mon_cb(void * stream, struct str_parms * parms);
516static void out_snd_mon_cb(void * stream, struct str_parms * parms);
517
Vatsal Buchac09ae062018-11-14 13:25:08 +0530518#ifdef AUDIO_FEATURE_ENABLED_GCOV
519extern void __gcov_flush();
520static void enable_gcov()
521{
522 __gcov_flush();
523}
524#else
525static void enable_gcov()
526{
527}
528#endif
529
justinweng20fb6d82019-02-21 18:49:00 -0700530static int in_set_microphone_direction(const struct audio_stream_in *stream,
531 audio_microphone_direction_t dir);
532static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
533
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700534static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
535 int flags __unused)
536{
537 int dir = 0;
538 switch (uc_id) {
539 case USECASE_AUDIO_RECORD_LOW_LATENCY:
540 dir = 1;
541 case USECASE_AUDIO_PLAYBACK_ULL:
542 break;
543 default:
544 return false;
545 }
546
547 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
548 PCM_PLAYBACK : PCM_CAPTURE);
549 if (adev->adm_is_noirq_avail)
550 return adev->adm_is_noirq_avail(adev->adm_data,
551 adev->snd_card, dev_id, dir);
552 return false;
553}
554
555static void register_out_stream(struct stream_out *out)
556{
557 struct audio_device *adev = out->dev;
558 if (is_offload_usecase(out->usecase) ||
559 !adev->adm_register_output_stream)
560 return;
561
562 // register stream first for backward compatibility
563 adev->adm_register_output_stream(adev->adm_data,
564 out->handle,
565 out->flags);
566
567 if (!adev->adm_set_config)
568 return;
569
570 if (out->realtime)
571 adev->adm_set_config(adev->adm_data,
572 out->handle,
573 out->pcm, &out->config);
574}
575
576static void register_in_stream(struct stream_in *in)
577{
578 struct audio_device *adev = in->dev;
579 if (!adev->adm_register_input_stream)
580 return;
581
582 adev->adm_register_input_stream(adev->adm_data,
583 in->capture_handle,
584 in->flags);
585
586 if (!adev->adm_set_config)
587 return;
588
589 if (in->realtime)
590 adev->adm_set_config(adev->adm_data,
591 in->capture_handle,
592 in->pcm,
593 &in->config);
594}
595
596static void request_out_focus(struct stream_out *out, long ns)
597{
598 struct audio_device *adev = out->dev;
599
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700600 if (adev->adm_request_focus_v2)
601 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
602 else if (adev->adm_request_focus)
603 adev->adm_request_focus(adev->adm_data, out->handle);
604}
605
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700606static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607{
608 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700609 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700610
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700611 if (adev->adm_request_focus_v2_1)
612 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
613 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
615 else if (adev->adm_request_focus)
616 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700617
618 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619}
620
621static void release_out_focus(struct stream_out *out)
622{
623 struct audio_device *adev = out->dev;
624
625 if (adev->adm_abandon_focus)
626 adev->adm_abandon_focus(adev->adm_data, out->handle);
627}
628
629static void release_in_focus(struct stream_in *in)
630{
631 struct audio_device *adev = in->dev;
632 if (adev->adm_abandon_focus)
633 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
634}
635
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530636static int parse_snd_card_status(struct str_parms *parms, int *card,
637 card_status_t *status)
638{
639 char value[32]={0};
640 char state[32]={0};
641
642 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
643 if (ret < 0)
644 return -1;
645
646 // sscanf should be okay as value is of max length 32.
647 // same as sizeof state.
648 if (sscanf(value, "%d,%s", card, state) < 2)
649 return -1;
650
651 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
652 CARD_STATUS_OFFLINE;
653 return 0;
654}
655
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700656static inline void adjust_frames_for_device_delay(struct stream_out *out,
657 uint32_t *dsp_frames) {
658 // Adjustment accounts for A2dp encoder latency with offload usecases
659 // Note: Encoder latency is returned in ms.
660 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
661 unsigned long offset =
662 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
663 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
664 }
665}
666
vivek mehtaa76401a2015-04-24 14:12:15 -0700667__attribute__ ((visibility ("default")))
668bool audio_hw_send_gain_dep_calibration(int level) {
669 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700670 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700671
672 pthread_mutex_lock(&adev_init_lock);
673
674 if (adev != NULL && adev->platform != NULL) {
675 pthread_mutex_lock(&adev->lock);
676 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700677
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530678 // cache level info for any of the use case which
679 // was not started.
680 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700681
vivek mehtaa76401a2015-04-24 14:12:15 -0700682 pthread_mutex_unlock(&adev->lock);
683 } else {
684 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
685 }
686
687 pthread_mutex_unlock(&adev_init_lock);
688
689 return ret_val;
690}
691
Ashish Jain5106d362016-05-11 19:23:33 +0530692static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
693{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800694 bool gapless_enabled = false;
695 const char *mixer_ctl_name = "Compress Gapless Playback";
696 struct mixer_ctl *ctl;
697
698 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700699 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530700
701 /*Disable gapless if its AV playback*/
702 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800703
704 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
705 if (!ctl) {
706 ALOGE("%s: Could not get ctl for mixer cmd - %s",
707 __func__, mixer_ctl_name);
708 return -EINVAL;
709 }
710
711 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
712 ALOGE("%s: Could not set gapless mode %d",
713 __func__, gapless_enabled);
714 return -EINVAL;
715 }
716 return 0;
717}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700718
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700719__attribute__ ((visibility ("default")))
720int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
721 int table_size) {
722 int ret_val = 0;
723 ALOGV("%s: enter ... ", __func__);
724
725 pthread_mutex_lock(&adev_init_lock);
726 if (adev == NULL) {
727 ALOGW("%s: adev is NULL .... ", __func__);
728 goto done;
729 }
730
731 pthread_mutex_lock(&adev->lock);
732 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
733 pthread_mutex_unlock(&adev->lock);
734done:
735 pthread_mutex_unlock(&adev_init_lock);
736 ALOGV("%s: exit ... ", __func__);
737 return ret_val;
738}
739
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800740bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800741{
742 bool ret = false;
743 ALOGV("%s: enter ...", __func__);
744
745 pthread_mutex_lock(&adev_init_lock);
746
747 if (adev != NULL && adev->platform != NULL) {
748 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800749 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800750 pthread_mutex_unlock(&adev->lock);
751 }
752
753 pthread_mutex_unlock(&adev_init_lock);
754
755 ALOGV("%s: exit with ret %d", __func__, ret);
756 return ret;
757}
Aalique Grahame22e49102018-12-18 14:23:57 -0800758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700759static bool is_supported_format(audio_format_t format)
760{
Eric Laurent86e17132013-09-12 17:49:30 -0700761 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530762 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530763 format == AUDIO_FORMAT_AAC_LC ||
764 format == AUDIO_FORMAT_AAC_HE_V1 ||
765 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530766 format == AUDIO_FORMAT_AAC_ADTS_LC ||
767 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
768 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530769 format == AUDIO_FORMAT_AAC_LATM_LC ||
770 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
771 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530772 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
773 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530774 format == AUDIO_FORMAT_PCM_FLOAT ||
775 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700776 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530777 format == AUDIO_FORMAT_AC3 ||
778 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700779 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530780 format == AUDIO_FORMAT_DTS ||
781 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800782 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530783 format == AUDIO_FORMAT_ALAC ||
784 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530785 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530786 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800787 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530788 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700789 format == AUDIO_FORMAT_APTX ||
790 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800791 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700792
793 return false;
794}
795
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700796static inline bool is_mmap_usecase(audio_usecase_t uc_id)
797{
798 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
799 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
800}
801
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700802static inline bool is_valid_volume(float left, float right)
803{
804 return ((left >= 0.0f && right >= 0.0f) ? true : false);
805}
806
Avinash Vaish71a8b972014-07-24 15:36:33 +0530807static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
808 struct audio_usecase *uc_info)
809{
810 struct listnode *node;
811 struct audio_usecase *usecase;
812
813 if (uc_info == NULL)
814 return -EINVAL;
815
816 /* Re-route all voice usecases on the shared backend other than the
817 specified usecase to new snd devices */
818 list_for_each(node, &adev->usecase_list) {
819 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800820 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530821 enable_audio_route(adev, usecase);
822 }
823 return 0;
824}
825
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530826static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530827{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530828 ALOGV("%s", __func__);
829 audio_route_apply_and_update_path(adev->audio_route,
830 "asrc-mode");
831 adev->asrc_mode_enabled = true;
832}
833
834static void disable_asrc_mode(struct audio_device *adev)
835{
836 ALOGV("%s", __func__);
837 audio_route_reset_and_update_path(adev->audio_route,
838 "asrc-mode");
839 adev->asrc_mode_enabled = false;
840}
841
842/*
843 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
844 * 44.1 or Native DSD backends are enabled for any of current use case.
845 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
846 * - Disable current mix path use case(Headphone backend) and re-enable it with
847 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
848 * e.g. Naitve DSD or Headphone 44.1 -> + 48
849 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530850static void check_and_set_asrc_mode(struct audio_device *adev,
851 struct audio_usecase *uc_info,
852 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530853{
854 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530855 int i, num_new_devices = 0;
856 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
857 /*
858 *Split snd device for new combo use case
859 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
860 */
861 if (platform_split_snd_device(adev->platform,
862 snd_device,
863 &num_new_devices,
864 split_new_snd_devices) == 0) {
865 for (i = 0; i < num_new_devices; i++)
866 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
867 } else {
868 int new_backend_idx = platform_get_backend_index(snd_device);
869 if (((new_backend_idx == HEADPHONE_BACKEND) ||
870 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
871 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
872 !adev->asrc_mode_enabled) {
873 struct listnode *node = NULL;
874 struct audio_usecase *uc = NULL;
875 struct stream_out *curr_out = NULL;
876 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
877 int i, num_devices, ret = 0;
878 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530879
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530880 list_for_each(node, &adev->usecase_list) {
881 uc = node_to_item(node, struct audio_usecase, list);
882 curr_out = (struct stream_out*) uc->stream.out;
883 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
884 /*
885 *Split snd device for existing combo use case
886 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
887 */
888 ret = platform_split_snd_device(adev->platform,
889 uc->out_snd_device,
890 &num_devices,
891 split_snd_devices);
892 if (ret < 0 || num_devices == 0) {
893 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
894 split_snd_devices[0] = uc->out_snd_device;
895 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800896 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530897 for (i = 0; i < num_devices; i++) {
898 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
899 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
900 if((new_backend_idx == HEADPHONE_BACKEND) &&
901 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
902 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
903 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
904 __func__);
905 enable_asrc_mode(adev);
906 break;
907 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
908 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
909 (usecase_backend_idx == HEADPHONE_BACKEND)) {
910 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
911 __func__);
912 disable_audio_route(adev, uc);
913 disable_snd_device(adev, uc->out_snd_device);
914 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
915 if (new_backend_idx == DSD_NATIVE_BACKEND)
916 audio_route_apply_and_update_path(adev->audio_route,
917 "hph-true-highquality-mode");
918 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
919 (curr_out->bit_width >= 24))
920 audio_route_apply_and_update_path(adev->audio_route,
921 "hph-highquality-mode");
922 enable_asrc_mode(adev);
923 enable_snd_device(adev, uc->out_snd_device);
924 enable_audio_route(adev, uc);
925 break;
926 }
927 }
928 // reset split devices count
929 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800930 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530931 if (adev->asrc_mode_enabled)
932 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530933 }
934 }
935 }
936}
937
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700938static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
939 struct audio_effect_config effect_config,
940 unsigned int param_value)
941{
942 char mixer_ctl_name[] = "Audio Effect";
943 struct mixer_ctl *ctl;
944 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800945 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700946
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700947 if (in == NULL) {
948 ALOGE("%s: active input stream is NULL", __func__);
949 return -EINVAL;
950 }
951
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700952 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
953 if (!ctl) {
954 ALOGE("%s: Could not get mixer ctl - %s",
955 __func__, mixer_ctl_name);
956 return -EINVAL;
957 }
958
959 set_values[0] = 1; //0:Rx 1:Tx
960 set_values[1] = in->app_type_cfg.app_type;
961 set_values[2] = (long)effect_config.module_id;
962 set_values[3] = (long)effect_config.instance_id;
963 set_values[4] = (long)effect_config.param_id;
964 set_values[5] = param_value;
965
966 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
967
968 return 0;
969
970}
971
972static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
973 int effect_type, unsigned int *param_value)
974{
975 int ret = 0;
976 struct audio_effect_config other_effect_config;
977 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800978 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700979
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700980 if (in == NULL) {
981 ALOGE("%s: active input stream is NULL", __func__);
982 return -EINVAL;
983 }
984
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700985 usecase = get_usecase_from_list(adev, in->usecase);
986 if (!usecase)
987 return -EINVAL;
988
989 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
990 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
991 if (ret < 0) {
992 ALOGE("%s Failed to get effect params %d", __func__, ret);
993 return ret;
994 }
995
996 if (module_id == other_effect_config.module_id) {
997 //Same module id for AEC/NS. Values need to be combined
998 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
999 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1000 *param_value |= other_effect_config.param_value;
1001 }
1002 }
1003
1004 return ret;
1005}
1006
1007static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301008{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001009 struct audio_effect_config effect_config;
1010 struct audio_usecase *usecase = NULL;
1011 int ret = 0;
1012 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001013 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001014
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001015 if(!voice_extn_is_dynamic_ecns_enabled())
1016 return ENOSYS;
1017
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001018 if (!in) {
1019 ALOGE("%s: Invalid input stream", __func__);
1020 return -EINVAL;
1021 }
1022
1023 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1024
1025 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001026 if (usecase == NULL) {
1027 ALOGE("%s: Could not find the usecase (%d) in the list",
1028 __func__, in->usecase);
1029 return -EINVAL;
1030 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031
1032 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1033 if (ret < 0) {
1034 ALOGE("%s Failed to get module id %d", __func__, ret);
1035 return ret;
1036 }
1037 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1038 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1039
1040 if(enable)
1041 param_value = effect_config.param_value;
1042
1043 /*Special handling for AEC & NS effects Param values need to be
1044 updated if module ids are same*/
1045
1046 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1047 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1048 if (ret < 0)
1049 return ret;
1050 }
1051
1052 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1053
1054 return ret;
1055}
1056
1057static void check_and_enable_effect(struct audio_device *adev)
1058{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001059 if(!voice_extn_is_dynamic_ecns_enabled())
1060 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001061
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
Eric Laurent637e2d42018-11-15 12:24:31 -08001064 if (in != NULL && !in->standby) {
1065 if (in->enable_aec)
1066 enable_disable_effect(adev, EFFECT_AEC, true);
1067
1068 if (in->enable_ns &&
1069 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1070 enable_disable_effect(adev, EFFECT_NS, true);
1071 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001072 }
1073}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001075int pcm_ioctl(struct pcm *pcm, int request, ...)
1076{
1077 va_list ap;
1078 void * arg;
1079 int pcm_fd = *(int*)pcm;
1080
1081 va_start(ap, request);
1082 arg = va_arg(ap, void *);
1083 va_end(ap);
1084
1085 return ioctl(pcm_fd, request, arg);
1086}
1087
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001088int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001089 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001092 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301093 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301094 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301095 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001096
1097 if (usecase == NULL)
1098 return -EINVAL;
1099
1100 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1101
Carter Hsu2e429db2019-05-14 18:50:52 +08001102 if (usecase->type == PCM_CAPTURE) {
1103 struct stream_in *in = usecase->stream.in;
1104 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001106
1107 if (in) {
1108 if (in->enable_aec || in->enable_ec_port) {
1109 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1110 struct listnode *node;
1111 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1112 USECASE_AUDIO_PLAYBACK_VOIP);
1113 if (voip_usecase) {
1114 out_device = voip_usecase->stream.out->devices;
1115 } else if (adev->primary_output &&
1116 !adev->primary_output->standby) {
1117 out_device = adev->primary_output->devices;
1118 } else {
1119 list_for_each(node, &adev->usecase_list) {
1120 uinfo = node_to_item(node, struct audio_usecase, list);
1121 if (uinfo->type != PCM_CAPTURE) {
1122 out_device = uinfo->stream.out->devices;
1123 break;
1124 }
1125 }
1126 }
1127 platform_set_echo_reference(adev, true, out_device);
1128 in->ec_opened = true;
1129 }
1130 }
1131 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1132 snd_device = usecase->in_snd_device;
1133 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001135 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001136
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001137#ifdef DS1_DOLBY_DAP_ENABLED
1138 audio_extn_dolby_set_dmid(adev);
1139 audio_extn_dolby_set_endpoint(adev);
1140#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001141 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001142 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301143 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001144 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001145 if (audio_extn_is_maxx_audio_enabled())
1146 audio_extn_ma_set_device(usecase);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001147#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1148 if (usecase->id != USECASE_AUDIO_ULTRASOUND_TX)
1149#endif
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301150 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301151 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1152 out = usecase->stream.out;
1153 if (out && out->compr)
1154 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1155 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301156
1157 if (usecase->type == PCM_CAPTURE) {
1158 in = usecase->stream.in;
1159 if (in && is_loopback_input_device(in->device)) {
1160 ALOGD("%s: set custom mtmx params v1", __func__);
1161 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1162 }
1163 } else {
1164 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1165 }
Manish Dewangan58229382017-02-02 15:48:41 +05301166
Andy Hung756ecc12018-10-19 17:47:12 -07001167 // we shouldn't truncate mixer_path
1168 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1169 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1170 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001171 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001172 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301173 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1174 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1175 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1176 if (parms) {
1177 audio_extn_fm_set_parameters(adev, parms);
1178 str_parms_destroy(parms);
1179 }
1180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181 ALOGV("%s: exit", __func__);
1182 return 0;
1183}
1184
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001185int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001186 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001189 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301190 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001191
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301192 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001193 return -EINVAL;
1194
1195 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301196 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197 snd_device = usecase->in_snd_device;
1198 else
1199 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001200 // we shouldn't truncate mixer_path
1201 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1202 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1203 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001204 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001205 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001206 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 if (usecase->type == PCM_CAPTURE) {
1208 struct stream_in *in = usecase->stream.in;
1209 if (in && in->ec_opened) {
1210 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1211 in->ec_opened = false;
1212 }
1213 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001214 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301215 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301216
1217 if (usecase->type == PCM_CAPTURE) {
1218 in = usecase->stream.in;
1219 if (in && is_loopback_input_device(in->device)) {
1220 ALOGD("%s: reset custom mtmx params v1", __func__);
1221 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1222 }
1223 } else {
1224 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1225 }
1226
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001227 if ((usecase->type == PCM_PLAYBACK) &&
1228 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301229 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231 ALOGV("%s: exit", __func__);
1232 return 0;
1233}
1234
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001235int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001236 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301238 int i, num_devices = 0;
1239 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001240 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1241
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001242 if (snd_device < SND_DEVICE_MIN ||
1243 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001244 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001245 return -EINVAL;
1246 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001247
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001248 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001249 ALOGE("%s: Invalid sound device returned", __func__);
1250 return -EINVAL;
1251 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001252
1253 adev->snd_dev_ref_cnt[snd_device]++;
1254
1255 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1256 (platform_split_snd_device(adev->platform,
1257 snd_device,
1258 &num_devices,
1259 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001260 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001261 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262 return 0;
1263 }
1264
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001265 if (audio_extn_spkr_prot_is_enabled())
1266 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001267
Aalique Grahame22e49102018-12-18 14:23:57 -08001268 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1269
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001270 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1271 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001272 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1273 goto err;
1274 }
1275 audio_extn_dev_arbi_acquire(snd_device);
1276 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001277 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001278 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001279 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001280 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001281 } else if (platform_split_snd_device(adev->platform,
1282 snd_device,
1283 &num_devices,
1284 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301285 for (i = 0; i < num_devices; i++) {
1286 enable_snd_device(adev, new_snd_devices[i]);
1287 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001288 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001289 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001290 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301291
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301292
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001293 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1294 (audio_extn_a2dp_start_playback() < 0)) {
1295 ALOGE(" fail to configure A2dp Source control path ");
1296 goto err;
1297 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001298
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001299 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1300 (audio_extn_a2dp_start_capture() < 0)) {
1301 ALOGE(" fail to configure A2dp Sink control path ");
1302 goto err;
1303 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301304
Zhou Song12c29502019-03-16 10:37:18 +08001305 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1306 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1307 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1308 (audio_extn_sco_start_configuration() < 0)) {
1309 ALOGE(" fail to configure sco control path ");
1310 goto err;
1311 }
1312
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001313 /* due to the possibility of calibration overwrite between listen
1314 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001315 audio_extn_sound_trigger_update_device_status(snd_device,
1316 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301317 audio_extn_listen_update_device_status(snd_device,
1318 LISTEN_EVENT_SND_DEVICE_BUSY);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001319#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1320 if (snd_device != SND_DEVICE_OUT_ULTRASOUND_HANDSET &&
1321 snd_device != SND_DEVICE_IN_ULTRASOUND_MIC)
1322#endif
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001323 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001324 audio_extn_sound_trigger_update_device_status(snd_device,
1325 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301326 audio_extn_listen_update_device_status(snd_device,
1327 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001328 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001329 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001330 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001331 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301332
1333 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1334 !adev->native_playback_enabled &&
1335 audio_is_true_native_stream_active(adev)) {
1336 ALOGD("%s: %d: napb: enabling native mode in hardware",
1337 __func__, __LINE__);
1338 audio_route_apply_and_update_path(adev->audio_route,
1339 "true-native-mode");
1340 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301341 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301342 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1343 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001344 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001345 ALOGD("%s: init ec ref loopback", __func__);
1346 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001350err:
1351 adev->snd_dev_ref_cnt[snd_device]--;
1352 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353}
1354
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001355int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001356 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301358 int i, num_devices = 0;
1359 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001360 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1361
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001362 if (snd_device < SND_DEVICE_MIN ||
1363 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001364 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001365 return -EINVAL;
1366 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001367
1368 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1369 ALOGE("%s: Invalid sound device returned", __func__);
1370 return -EINVAL;
1371 }
1372
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1374 ALOGE("%s: device ref cnt is already 0", __func__);
1375 return -EINVAL;
1376 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001377
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001379
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001380
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001381 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001382 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301383
Aalique Grahame22e49102018-12-18 14:23:57 -08001384 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1385
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001386 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1387 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001388 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001389
1390 // when speaker device is disabled, reset swap.
1391 // will be renabled on usecase start
1392 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001393 } else if (platform_split_snd_device(adev->platform,
1394 snd_device,
1395 &num_devices,
1396 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301397 for (i = 0; i < num_devices; i++) {
1398 disable_snd_device(adev, new_snd_devices[i]);
1399 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001400 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001401 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001402 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001403 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001404
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001405 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301406 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001407 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001408 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001409 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001410 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301411 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001412 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301413 adev->native_playback_enabled) {
1414 ALOGD("%s: %d: napb: disabling native mode in hardware",
1415 __func__, __LINE__);
1416 audio_route_reset_and_update_path(adev->audio_route,
1417 "true-native-mode");
1418 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001419 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301420 adev->asrc_mode_enabled) {
1421 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301422 disable_asrc_mode(adev);
1423 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001424 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301425 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001426 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001427 ALOGD("%s: deinit ec ref loopback", __func__);
1428 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1429 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001430
1431 audio_extn_utils_release_snd_device(snd_device);
1432 } else {
1433 if (platform_split_snd_device(adev->platform,
1434 snd_device,
1435 &num_devices,
1436 new_snd_devices) == 0) {
1437 for (i = 0; i < num_devices; i++) {
1438 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1439 }
1440 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 return 0;
1444}
1445
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001446/*
1447 legend:
1448 uc - existing usecase
1449 new_uc - new usecase
1450 d1, d11, d2 - SND_DEVICE enums
1451 a1, a2 - corresponding ANDROID device enums
1452 B1, B2 - backend strings
1453
1454case 1
1455 uc->dev d1 (a1) B1
1456 new_uc->dev d1 (a1), d2 (a2) B1, B2
1457
1458 resolution: disable and enable uc->dev on d1
1459
1460case 2
1461 uc->dev d1 (a1) B1
1462 new_uc->dev d11 (a1) B1
1463
1464 resolution: need to switch uc since d1 and d11 are related
1465 (e.g. speaker and voice-speaker)
1466 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1467
1468case 3
1469 uc->dev d1 (a1) B1
1470 new_uc->dev d2 (a2) B2
1471
1472 resolution: no need to switch uc
1473
1474case 4
1475 uc->dev d1 (a1) B1
1476 new_uc->dev d2 (a2) B1
1477
1478 resolution: disable enable uc-dev on d2 since backends match
1479 we cannot enable two streams on two different devices if they
1480 share the same backend. e.g. if offload is on speaker device using
1481 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1482 using the same backend, offload must also be switched to voice-handset.
1483
1484case 5
1485 uc->dev d1 (a1) B1
1486 new_uc->dev d1 (a1), d2 (a2) B1
1487
1488 resolution: disable enable uc-dev on d2 since backends match
1489 we cannot enable two streams on two different devices if they
1490 share the same backend.
1491
1492case 6
1493 uc->dev d1 (a1) B1
1494 new_uc->dev d2 (a1) B2
1495
1496 resolution: no need to switch
1497
1498case 7
1499 uc->dev d1 (a1), d2 (a2) B1, B2
1500 new_uc->dev d1 (a1) B1
1501
1502 resolution: no need to switch
1503
Zhou Song4ba65882018-07-09 14:48:07 +08001504case 8
1505 uc->dev d1 (a1) B1
1506 new_uc->dev d11 (a1), d2 (a2) B1, B2
1507 resolution: compared to case 1, for this case, d1 and d11 are related
1508 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001509*/
1510static snd_device_t derive_playback_snd_device(void * platform,
1511 struct audio_usecase *uc,
1512 struct audio_usecase *new_uc,
1513 snd_device_t new_snd_device)
1514{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301515 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001516
1517 snd_device_t d1 = uc->out_snd_device;
1518 snd_device_t d2 = new_snd_device;
1519
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301520 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301521 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301522 a1 = uc->stream.inout->out_config.devices;
1523 a2 = new_uc->stream.inout->out_config.devices;
1524 break;
1525 default :
1526 a1 = uc->stream.out->devices;
1527 a2 = new_uc->stream.out->devices;
1528 break;
1529 }
1530
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001531 // Treat as a special case when a1 and a2 are not disjoint
1532 if ((a1 != a2) && (a1 & a2)) {
1533 snd_device_t d3[2];
1534 int num_devices = 0;
1535 int ret = platform_split_snd_device(platform,
1536 popcount(a1) > 1 ? d1 : d2,
1537 &num_devices,
1538 d3);
1539 if (ret < 0) {
1540 if (ret != -ENOSYS) {
1541 ALOGW("%s failed to split snd_device %d",
1542 __func__,
1543 popcount(a1) > 1 ? d1 : d2);
1544 }
1545 goto end;
1546 }
1547
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001548 if (platform_check_backends_match(d3[0], d3[1])) {
1549 return d2; // case 5
1550 } else {
Samyak Jaind826b502019-07-17 16:16:42 +05301551 if (popcount(a1) > 1)
1552 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001553 // check if d1 is related to any of d3's
1554 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001555 return d1; // case 1
1556 else
1557 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001558 }
1559 } else {
1560 if (platform_check_backends_match(d1, d2)) {
1561 return d2; // case 2, 4
1562 } else {
1563 return d1; // case 6, 3
1564 }
1565 }
1566
1567end:
1568 return d2; // return whatever was calculated before.
1569}
1570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301572 struct audio_usecase *uc_info,
1573 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574{
1575 struct listnode *node;
1576 struct audio_usecase *usecase;
1577 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301578 snd_device_t uc_derive_snd_device;
1579 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001580 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1581 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001582 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301583 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584 /*
1585 * This function is to make sure that all the usecases that are active on
1586 * the hardware codec backend are always routed to any one device that is
1587 * handled by the hardware codec.
1588 * For example, if low-latency and deep-buffer usecases are currently active
1589 * on speaker and out_set_parameters(headset) is received on low-latency
1590 * output, then we have to make sure deep-buffer is also switched to headset,
1591 * because of the limitation that both the devices cannot be enabled
1592 * at the same time as they share the same backend.
1593 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001594 /*
1595 * This call is to check if we need to force routing for a particular stream
1596 * If there is a backend configuration change for the device when a
1597 * new stream starts, then ADM needs to be closed and re-opened with the new
1598 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001599 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001600 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001601 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1602 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301603 /* For a2dp device reconfigure all active sessions
1604 * with new AFE encoder format based on a2dp state
1605 */
1606 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1607 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1608 audio_extn_a2dp_is_force_device_switch()) {
1609 force_routing = true;
1610 force_restart_session = true;
1611 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301612 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1613
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001614 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001615 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001616 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001617 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1618 switch_device[i] = false;
1619
1620 list_for_each(node, &adev->usecase_list) {
1621 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001622
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301623 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1624 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301625 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301626 platform_get_snd_device_name(usecase->out_snd_device),
1627 platform_check_backends_match(snd_device, usecase->out_snd_device));
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001628
1629#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1630 if (usecase->id == USECASE_AUDIO_ULTRASOUND_RX)
1631 continue;
1632#endif
1633
Rahul Sharma99770982019-03-06 17:05:26 +05301634 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1635 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301636 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1637 usecase, uc_info, snd_device);
1638 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1639 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1640 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1641 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001642 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301643 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1644 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1645 ((force_restart_session) ||
1646 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301647 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1648 __func__, use_case_table[usecase->id],
1649 platform_get_snd_device_name(usecase->out_snd_device));
1650 disable_audio_route(adev, usecase);
1651 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301652 /* Enable existing usecase on derived playback device */
1653 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301654 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001656 }
1657 }
1658
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301659 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1660 num_uc_to_switch);
1661
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001662 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001663 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301665 /* Make sure the previous devices to be disabled first and then enable the
1666 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667 list_for_each(node, &adev->usecase_list) {
1668 usecase = node_to_item(node, struct audio_usecase, list);
1669 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001670 /* Check if output sound device to be switched can be split and if any
1671 of the split devices match with derived sound device */
1672 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1673 &num_devices, split_snd_devices) == 0) {
1674 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1675 for (i = 0; i < num_devices; i++) {
1676 /* Disable devices that do not match with derived sound device */
1677 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1678 disable_snd_device(adev, split_snd_devices[i]);
1679 }
1680 } else {
1681 disable_snd_device(adev, usecase->out_snd_device);
1682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683 }
1684 }
1685
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001686 list_for_each(node, &adev->usecase_list) {
1687 usecase = node_to_item(node, struct audio_usecase, list);
1688 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001689 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1690 &num_devices, split_snd_devices) == 0) {
1691 /* Enable derived sound device only if it does not match with
1692 one of the split sound devices. This is because the matching
1693 sound device was not disabled */
1694 bool should_enable = true;
1695 for (i = 0; i < num_devices; i++) {
1696 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1697 should_enable = false;
1698 break;
1699 }
1700 }
1701 if (should_enable)
1702 enable_snd_device(adev, derive_snd_device[usecase->id]);
1703 } else {
1704 enable_snd_device(adev, derive_snd_device[usecase->id]);
1705 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001706 }
1707 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 /* Re-route all the usecases on the shared backend other than the
1710 specified usecase to new snd devices */
1711 list_for_each(node, &adev->usecase_list) {
1712 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301713 /* Update the out_snd_device only before enabling the audio route */
1714 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301715 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301716 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301717 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301718 use_case_table[usecase->id],
1719 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001720 /* Update voc calibration before enabling VoIP route */
1721 if (usecase->type == VOIP_CALL)
1722 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001723 usecase->out_snd_device,
1724 platform_get_input_snd_device(
1725 adev->platform, NULL,
1726 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301727 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301728 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001729 out_set_voip_volume(&usecase->stream.out->stream,
1730 usecase->stream.out->volume_l,
1731 usecase->stream.out->volume_r);
1732 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301733 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001734 }
1735 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001736 }
1737}
1738
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301739static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001740 struct audio_usecase *uc_info,
1741 snd_device_t snd_device)
1742{
1743 struct listnode *node;
1744 struct audio_usecase *usecase;
1745 bool switch_device[AUDIO_USECASE_MAX];
1746 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301747 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001748 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001749
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301750 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1751 snd_device);
1752 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301753
1754 /*
1755 * Make sure out devices is checked against out codec backend device and
1756 * also in devices against in codec backend. Checking out device against in
1757 * codec backend or vice versa causes issues.
1758 */
1759 if (uc_info->type == PCM_CAPTURE)
1760 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001761 /*
1762 * This function is to make sure that all the active capture usecases
1763 * are always routed to the same input sound device.
1764 * For example, if audio-record and voice-call usecases are currently
1765 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1766 * is received for voice call then we have to make sure that audio-record
1767 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1768 * because of the limitation that two devices cannot be enabled
1769 * at the same time if they share the same backend.
1770 */
1771 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1772 switch_device[i] = false;
1773
1774 list_for_each(node, &adev->usecase_list) {
1775 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301776 /*
1777 * TODO: Enhance below condition to handle BT sco/USB multi recording
1778 */
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001779
1780#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1781 if (usecase->id == USECASE_AUDIO_ULTRASOUND_TX)
1782 continue;
1783#endif
1784
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001785 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001786 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301787 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301788 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301789 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301790 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001791 ((uc_info->type == VOICE_CALL &&
1792 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1793 platform_check_backends_match(snd_device,\
1794 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001795 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001796 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1797 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001798 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001799 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001800 switch_device[usecase->id] = true;
1801 num_uc_to_switch++;
1802 }
1803 }
1804
1805 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001806 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001807
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301808 /* Make sure the previous devices to be disabled first and then enable the
1809 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001810 list_for_each(node, &adev->usecase_list) {
1811 usecase = node_to_item(node, struct audio_usecase, list);
1812 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001813 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001814 }
1815 }
1816
1817 list_for_each(node, &adev->usecase_list) {
1818 usecase = node_to_item(node, struct audio_usecase, list);
1819 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001820 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001821 }
1822 }
1823
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001824 /* Re-route all the usecases on the shared backend other than the
1825 specified usecase to new snd devices */
1826 list_for_each(node, &adev->usecase_list) {
1827 usecase = node_to_item(node, struct audio_usecase, list);
1828 /* Update the in_snd_device only before enabling the audio route */
1829 if (switch_device[usecase->id] ) {
1830 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001831 if (usecase->type != VOICE_CALL) {
1832 /* Update voc calibration before enabling VoIP route */
1833 if (usecase->type == VOIP_CALL)
1834 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001835 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001836 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301837 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001838 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001839 }
1840 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001841 }
1842}
1843
Mingming Yin3a941d42016-02-17 18:08:05 -08001844static void reset_hdmi_sink_caps(struct stream_out *out) {
1845 int i = 0;
1846
1847 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1848 out->supported_channel_masks[i] = 0;
1849 }
1850 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1851 out->supported_formats[i] = 0;
1852 }
1853 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1854 out->supported_sample_rates[i] = 0;
1855 }
1856}
1857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001859static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860{
Mingming Yin3a941d42016-02-17 18:08:05 -08001861 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001862 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863
Mingming Yin3a941d42016-02-17 18:08:05 -08001864 reset_hdmi_sink_caps(out);
1865
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001866 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001867 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001868 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001869 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001870 }
1871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001874 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001875 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001876 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1877 case 6:
1878 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1879 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1880 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1881 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1882 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1883 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 break;
1885 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001886 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001887 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 break;
1889 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001890
1891 // check channel format caps
1892 i = 0;
1893 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1894 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1895 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1896 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1897 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1898 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1899 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1900 }
1901
Ben Romberger1aaaf862017-04-06 17:49:46 -07001902 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1903 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1904 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1905 }
1906
Mingming Yin3a941d42016-02-17 18:08:05 -08001907 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1908 ALOGV(":%s HDMI supports DTS format", __func__);
1909 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1910 }
1911
1912 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1913 ALOGV(":%s HDMI supports DTS HD format", __func__);
1914 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1915 }
1916
Naresh Tanniru928f0862017-04-07 16:44:23 -07001917 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1918 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1919 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1920 }
1921
Mingming Yin3a941d42016-02-17 18:08:05 -08001922
1923 // check sample rate caps
1924 i = 0;
1925 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1926 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1927 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1928 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1929 }
1930 }
1931
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001932 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933}
1934
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001935static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1936 uint32_t *supported_sample_rates __unused,
1937 uint32_t max_rates __unused)
1938{
1939 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1940 supported_sample_rates,
1941 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301942 ssize_t i = 0;
1943
1944 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001945 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1946 supported_sample_rates[i]);
1947 }
1948 return count;
1949}
1950
1951static inline int read_usb_sup_channel_masks(bool is_playback,
1952 audio_channel_mask_t *supported_channel_masks,
1953 uint32_t max_masks)
1954{
1955 int channels = audio_extn_usb_get_max_channels(is_playback);
1956 int channel_count;
1957 uint32_t num_masks = 0;
1958 if (channels > MAX_HIFI_CHANNEL_COUNT)
1959 channels = MAX_HIFI_CHANNEL_COUNT;
1960
1961 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001962 // start from 2 channels as framework currently doesn't support mono.
1963 if (channels >= FCC_2) {
1964 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1965 }
1966 for (channel_count = FCC_2;
1967 channel_count <= channels && num_masks < max_masks;
1968 ++channel_count) {
1969 supported_channel_masks[num_masks++] =
1970 audio_channel_mask_for_index_assignment_from_count(channel_count);
1971 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001972 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001973 // For capture we report all supported channel masks from 1 channel up.
1974 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001975 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1976 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001977 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1978 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1979 if (channel_count <= FCC_2) {
1980 mask = audio_channel_in_mask_from_count(channel_count);
1981 supported_channel_masks[num_masks++] = mask;
1982 }
1983 const audio_channel_mask_t index_mask =
1984 audio_channel_mask_for_index_assignment_from_count(channel_count);
1985 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1986 supported_channel_masks[num_masks++] = index_mask;
1987 }
1988 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001989 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301990
vincenttewf51c94e2019-05-07 10:28:53 +08001991 for (size_t i = 0; i < num_masks; ++i) {
1992 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1993 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301994 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001995 return num_masks;
1996}
1997
1998static inline int read_usb_sup_formats(bool is_playback __unused,
1999 audio_format_t *supported_formats,
2000 uint32_t max_formats __unused)
2001{
2002 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2003 switch (bitwidth) {
2004 case 24:
2005 // XXX : usb.c returns 24 for s24 and s24_le?
2006 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2007 break;
2008 case 32:
2009 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2010 break;
2011 case 16:
2012 default :
2013 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2014 break;
2015 }
2016 ALOGV("%s: %s supported format %d", __func__,
2017 is_playback ? "P" : "C", bitwidth);
2018 return 1;
2019}
2020
2021static inline int read_usb_sup_params_and_compare(bool is_playback,
2022 audio_format_t *format,
2023 audio_format_t *supported_formats,
2024 uint32_t max_formats,
2025 audio_channel_mask_t *mask,
2026 audio_channel_mask_t *supported_channel_masks,
2027 uint32_t max_masks,
2028 uint32_t *rate,
2029 uint32_t *supported_sample_rates,
2030 uint32_t max_rates) {
2031 int ret = 0;
2032 int num_formats;
2033 int num_masks;
2034 int num_rates;
2035 int i;
2036
2037 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2038 max_formats);
2039 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2040 max_masks);
2041
2042 num_rates = read_usb_sup_sample_rates(is_playback,
2043 supported_sample_rates, max_rates);
2044
2045#define LUT(table, len, what, dflt) \
2046 for (i=0; i<len && (table[i] != what); i++); \
2047 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2048
2049 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2050 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2051 LUT(supported_sample_rates, num_rates, *rate, 0);
2052
2053#undef LUT
2054 return ret < 0 ? -EINVAL : 0; // HACK TBD
2055}
2056
Alexy Josephb1379942016-01-29 15:49:38 -08002057audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002058 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002059{
2060 struct audio_usecase *usecase;
2061 struct listnode *node;
2062
2063 list_for_each(node, &adev->usecase_list) {
2064 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002065 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002066 ALOGV("%s: usecase id %d", __func__, usecase->id);
2067 return usecase->id;
2068 }
2069 }
2070 return USECASE_INVALID;
2071}
2072
Alexy Josephb1379942016-01-29 15:49:38 -08002073struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002074 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075{
2076 struct audio_usecase *usecase;
2077 struct listnode *node;
2078
2079 list_for_each(node, &adev->usecase_list) {
2080 usecase = node_to_item(node, struct audio_usecase, list);
2081 if (usecase->id == uc_id)
2082 return usecase;
2083 }
2084 return NULL;
2085}
2086
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302087/*
2088 * is a true native playback active
2089 */
2090bool audio_is_true_native_stream_active(struct audio_device *adev)
2091{
2092 bool active = false;
2093 int i = 0;
2094 struct listnode *node;
2095
2096 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2097 ALOGV("%s:napb: not in true mode or non hdphones device",
2098 __func__);
2099 active = false;
2100 goto exit;
2101 }
2102
2103 list_for_each(node, &adev->usecase_list) {
2104 struct audio_usecase *uc;
2105 uc = node_to_item(node, struct audio_usecase, list);
2106 struct stream_out *curr_out =
2107 (struct stream_out*) uc->stream.out;
2108
2109 if (curr_out && PCM_PLAYBACK == uc->type) {
2110 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2111 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2112 uc->id, curr_out->sample_rate,
2113 curr_out->bit_width,
2114 platform_get_snd_device_name(uc->out_snd_device));
2115
2116 if (is_offload_usecase(uc->id) &&
2117 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2118 active = true;
2119 ALOGD("%s:napb:native stream detected", __func__);
2120 }
2121 }
2122 }
2123exit:
2124 return active;
2125}
2126
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002127uint32_t adev_get_dsp_bit_width_enforce_mode()
2128{
2129 if (adev == NULL) {
2130 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2131 return 0;
2132 }
2133 return adev->dsp_bit_width_enforce_mode;
2134}
2135
2136static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2137{
2138 char value[PROPERTY_VALUE_MAX];
2139 int trial;
2140 uint32_t dsp_bit_width_enforce_mode = 0;
2141
2142 if (!mixer) {
2143 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2144 __func__);
2145 return 0;
2146 }
2147
2148 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2149 value, NULL) > 0) {
2150 trial = atoi(value);
2151 switch (trial) {
2152 case 16:
2153 dsp_bit_width_enforce_mode = 16;
2154 break;
2155 case 24:
2156 dsp_bit_width_enforce_mode = 24;
2157 break;
2158 case 32:
2159 dsp_bit_width_enforce_mode = 32;
2160 break;
2161 default:
2162 dsp_bit_width_enforce_mode = 0;
2163 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2164 break;
2165 }
2166 }
2167
2168 return dsp_bit_width_enforce_mode;
2169}
2170
2171static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2172 uint32_t enforce_mode,
2173 bool enable)
2174{
2175 struct mixer_ctl *ctl = NULL;
2176 const char *mixer_ctl_name = "ASM Bit Width";
2177 uint32_t asm_bit_width_mode = 0;
2178
2179 if (enforce_mode == 0) {
2180 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2181 return;
2182 }
2183
2184 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2185 if (!ctl) {
2186 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2187 __func__, mixer_ctl_name);
2188 return;
2189 }
2190
2191 if (enable)
2192 asm_bit_width_mode = enforce_mode;
2193 else
2194 asm_bit_width_mode = 0;
2195
2196 ALOGV("%s DSP bit width feature status is %d width=%d",
2197 __func__, enable, asm_bit_width_mode);
2198 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2199 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2200 asm_bit_width_mode);
2201
2202 return;
2203}
2204
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302205/*
2206 * if native DSD playback active
2207 */
2208bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2209{
2210 bool active = false;
2211 struct listnode *node = NULL;
2212 struct audio_usecase *uc = NULL;
2213 struct stream_out *curr_out = NULL;
2214
2215 list_for_each(node, &adev->usecase_list) {
2216 uc = node_to_item(node, struct audio_usecase, list);
2217 curr_out = (struct stream_out*) uc->stream.out;
2218
2219 if (curr_out && PCM_PLAYBACK == uc->type &&
2220 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2221 active = true;
2222 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302223 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302224 }
2225 }
2226 return active;
2227}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302228
2229static bool force_device_switch(struct audio_usecase *usecase)
2230{
2231 bool ret = false;
2232 bool is_it_true_mode = false;
2233
Zhou Song30f2c3e2018-02-08 14:02:15 +08002234 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302235 usecase->type == TRANSCODE_LOOPBACK_RX ||
2236 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002237 return false;
2238 }
2239
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002240 if(usecase->stream.out == NULL) {
2241 ALOGE("%s: stream.out is NULL", __func__);
2242 return false;
2243 }
2244
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302245 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002246 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2247 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2248 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302249 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2250 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2251 (!is_it_true_mode && adev->native_playback_enabled)){
2252 ret = true;
2253 ALOGD("napb: time to toggle native mode");
2254 }
2255 }
2256
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302257 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302258 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2259 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002260 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302261 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302262 ALOGD("Force a2dp device switch to update new encoder config");
2263 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002264 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302265
Florian Pfister1a84f312018-07-19 14:38:18 +02002266 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302267 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2268 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002269 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302270 return ret;
2271}
2272
Aalique Grahame22e49102018-12-18 14:23:57 -08002273static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2274{
2275 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2276}
2277
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302278bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2279{
2280 bool ret=false;
2281 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2282 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2283 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2284 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2285 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2286 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2287 ret = true;
2288
2289 return ret;
2290}
2291
2292bool is_a2dp_device(snd_device_t out_snd_device)
2293{
2294 bool ret=false;
2295 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2296 ret = true;
2297
2298 return ret;
2299}
2300
2301bool is_bt_soc_on(struct audio_device *adev)
2302{
2303 struct mixer_ctl *ctl;
2304 char *mixer_ctl_name = "BT SOC status";
2305 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2306 bool bt_soc_status = true;
2307 if (!ctl) {
2308 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2309 __func__, mixer_ctl_name);
2310 /*This is to ensure we dont break targets which dont have the kernel change*/
2311 return true;
2312 }
2313 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2314 ALOGD("BT SOC status: %d",bt_soc_status);
2315 return bt_soc_status;
2316}
2317
2318int out_standby_l(struct audio_stream *stream);
2319
Eric Laurent637e2d42018-11-15 12:24:31 -08002320struct stream_in *adev_get_active_input(const struct audio_device *adev)
2321{
2322 struct listnode *node;
2323 struct stream_in *last_active_in = NULL;
2324
2325 /* Get last added active input.
2326 * TODO: We may use a priority mechanism to pick highest priority active source */
2327 list_for_each(node, &adev->usecase_list)
2328 {
2329 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2330 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2331 last_active_in = usecase->stream.in;
2332 }
2333
2334 return last_active_in;
2335}
2336
2337struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2338{
2339 struct listnode *node;
2340
2341 /* First check active inputs with voice communication source and then
2342 * any input if audio mode is in communication */
2343 list_for_each(node, &adev->usecase_list)
2344 {
2345 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2346 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2347 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2348 return usecase->stream.in;
2349 }
2350 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2351 return adev_get_active_input(adev);
2352
2353 return NULL;
2354}
2355
Carter Hsu2e429db2019-05-14 18:50:52 +08002356/*
2357 * Aligned with policy.h
2358 */
2359static inline int source_priority(int inputSource)
2360{
2361 switch (inputSource) {
2362 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2363 return 9;
2364 case AUDIO_SOURCE_CAMCORDER:
2365 return 8;
2366 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2367 return 7;
2368 case AUDIO_SOURCE_UNPROCESSED:
2369 return 6;
2370 case AUDIO_SOURCE_MIC:
2371 return 5;
2372 case AUDIO_SOURCE_ECHO_REFERENCE:
2373 return 4;
2374 case AUDIO_SOURCE_FM_TUNER:
2375 return 3;
2376 case AUDIO_SOURCE_VOICE_RECOGNITION:
2377 return 2;
2378 case AUDIO_SOURCE_HOTWORD:
2379 return 1;
2380 default:
2381 break;
2382 }
2383 return 0;
2384}
2385
2386static struct stream_in *get_priority_input(struct audio_device *adev)
2387{
2388 struct listnode *node;
2389 struct audio_usecase *usecase;
2390 int last_priority = 0, priority;
2391 struct stream_in *priority_in = NULL;
2392 struct stream_in *in;
2393
2394 list_for_each(node, &adev->usecase_list) {
2395 usecase = node_to_item(node, struct audio_usecase, list);
2396 if (usecase->type == PCM_CAPTURE) {
2397 in = usecase->stream.in;
2398 if (!in)
2399 continue;
2400 priority = source_priority(in->source);
2401
2402 if (priority > last_priority) {
2403 last_priority = priority;
2404 priority_in = in;
2405 }
2406 }
2407 }
2408 return priority_in;
2409}
2410
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002411int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002413 snd_device_t out_snd_device = SND_DEVICE_NONE;
2414 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002415 struct audio_usecase *usecase = NULL;
2416 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002417 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002418 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302419 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002420 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002421 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302423 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2424
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002425 usecase = get_usecase_from_list(adev, uc_id);
2426 if (usecase == NULL) {
2427 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2428 return -EINVAL;
2429 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002431 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002432 (usecase->type == VOIP_CALL) ||
2433 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302434 if(usecase->stream.out == NULL) {
2435 ALOGE("%s: stream.out is NULL", __func__);
2436 return -EINVAL;
2437 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002438 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002439 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002440 in_snd_device = platform_get_input_snd_device(adev->platform,
2441 NULL,
2442 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002443 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302444 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302445 if (usecase->stream.inout == NULL) {
2446 ALOGE("%s: stream.inout is NULL", __func__);
2447 return -EINVAL;
2448 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302449 stream_out.devices = usecase->stream.inout->out_config.devices;
2450 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2451 stream_out.format = usecase->stream.inout->out_config.format;
2452 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2453 out_snd_device = platform_get_output_snd_device(adev->platform,
2454 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302455 usecase->devices = out_snd_device;
2456 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2457 if (usecase->stream.inout == NULL) {
2458 ALOGE("%s: stream.inout is NULL", __func__);
2459 return -EINVAL;
2460 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002461 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302462 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002463 } else {
2464 /*
2465 * If the voice call is active, use the sound devices of voice call usecase
2466 * so that it would not result any device switch. All the usecases will
2467 * be switched to new device when select_devices() is called for voice call
2468 * usecase. This is to avoid switching devices for voice call when
2469 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002470 * choose voice call device only if the use case device is
2471 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002472 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002473 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002474 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002475 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002476 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2477 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302478 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2479 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002480 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2481 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002482 in_snd_device = vc_usecase->in_snd_device;
2483 out_snd_device = vc_usecase->out_snd_device;
2484 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002485 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002486 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002487 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002488 if ((voip_usecase != NULL) &&
2489 (usecase->type == PCM_PLAYBACK) &&
2490 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002491 out_snd_device_backend_match = platform_check_backends_match(
2492 voip_usecase->out_snd_device,
2493 platform_get_output_snd_device(
2494 adev->platform,
2495 usecase->stream.out));
2496 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002497 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002498 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2499 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002500 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002501 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002502 in_snd_device = voip_usecase->in_snd_device;
2503 out_snd_device = voip_usecase->out_snd_device;
2504 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002505 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002506 hfp_ucid = audio_extn_hfp_get_usecase();
2507 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002508 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002509 in_snd_device = hfp_usecase->in_snd_device;
2510 out_snd_device = hfp_usecase->out_snd_device;
2511 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002512 }
2513 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302514 if (usecase->stream.out == NULL) {
2515 ALOGE("%s: stream.out is NULL", __func__);
2516 return -EINVAL;
2517 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002518 usecase->devices = usecase->stream.out->devices;
2519 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002520 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002521 struct stream_out *voip_out = adev->primary_output;
2522 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002523 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002524 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002525 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002526
Eric Laurent637e2d42018-11-15 12:24:31 -08002527 if (voip_usecase)
2528 voip_out = voip_usecase->stream.out;
2529
2530 if (usecase->stream.out == voip_out && voip_in != NULL)
2531 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002532 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002533 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302534 if (usecase->stream.in == NULL) {
2535 ALOGE("%s: stream.in is NULL", __func__);
2536 return -EINVAL;
2537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002538 usecase->devices = usecase->stream.in->device;
2539 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002540 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002541 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002542 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002543 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002544
2545 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002546 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2547 USECASE_AUDIO_PLAYBACK_VOIP);
2548
Carter Hsu2e429db2019-05-14 18:50:52 +08002549 usecase->stream.in->enable_ec_port = false;
2550
Eric Laurent637e2d42018-11-15 12:24:31 -08002551 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2552 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2553 } else if (voip_usecase) {
2554 out_device = voip_usecase->stream.out->devices;
2555 } else if (adev->primary_output &&
2556 !adev->primary_output->standby) {
2557 out_device = adev->primary_output->devices;
2558 } else {
2559 /* forcing speaker o/p device to get matching i/p pair
2560 in case o/p is not routed from same primary HAL */
2561 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2562 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002563 priority_in = voip_in;
2564 } else {
2565 /* get the input with the highest priority source*/
2566 priority_in = get_priority_input(adev);
2567
2568 if (!priority_in)
2569 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002570 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002571
Eric Laurent637e2d42018-11-15 12:24:31 -08002572 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002573 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002574 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002575 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002576 }
2577 }
2578
2579 if (out_snd_device == usecase->out_snd_device &&
2580 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302581
2582 if (!force_device_switch(usecase))
2583 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 }
2585
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302586 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002587 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302588 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2589 return 0;
2590 }
2591
Aalique Grahame22e49102018-12-18 14:23:57 -08002592 if (out_snd_device != SND_DEVICE_NONE &&
2593 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2594 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2595 __func__,
2596 use_case_table[uc_id],
2597 adev->last_logged_snd_device[uc_id][0],
2598 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2599 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2600 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2601 -1,
2602 out_snd_device,
2603 platform_get_snd_device_name(out_snd_device),
2604 platform_get_snd_device_acdb_id(out_snd_device));
2605 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2606 }
2607 if (in_snd_device != SND_DEVICE_NONE &&
2608 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2609 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2610 __func__,
2611 use_case_table[uc_id],
2612 adev->last_logged_snd_device[uc_id][1],
2613 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2614 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2615 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2616 -1,
2617 in_snd_device,
2618 platform_get_snd_device_name(in_snd_device),
2619 platform_get_snd_device_acdb_id(in_snd_device));
2620 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2621 }
2622
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 /*
2625 * Limitation: While in call, to do a device switch we need to disable
2626 * and enable both RX and TX devices though one of them is same as current
2627 * device.
2628 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002629 if ((usecase->type == VOICE_CALL) &&
2630 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2631 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002632 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002633 }
2634
2635 if (((usecase->type == VOICE_CALL) ||
2636 (usecase->type == VOIP_CALL)) &&
2637 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2638 /* Disable sidetone only if voice/voip call already exists */
2639 if (voice_is_call_state_active(adev) ||
2640 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002641 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002642
2643 /* Disable aanc only if voice call exists */
2644 if (voice_is_call_state_active(adev))
2645 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002646 }
2647
Aalique Grahame22e49102018-12-18 14:23:57 -08002648 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2649 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002650 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302651 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002652 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2653 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2654 else
2655 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302656 }
2657
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002658 /* Disable current sound devices */
2659 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002660 disable_audio_route(adev, usecase);
2661 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 }
2663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002664 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002665 disable_audio_route(adev, usecase);
2666 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 }
2668
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002669 /* Applicable only on the targets that has external modem.
2670 * New device information should be sent to modem before enabling
2671 * the devices to reduce in-call device switch time.
2672 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002673 if ((usecase->type == VOICE_CALL) &&
2674 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2675 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002676 status = platform_switch_voice_call_enable_device_config(adev->platform,
2677 out_snd_device,
2678 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002679 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 /* Enable new sound devices */
2682 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002683 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302684 if (platform_check_codec_asrc_support(adev->platform))
2685 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002686 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 }
2688
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002689 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302690 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002691 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002693
Avinash Vaish71a8b972014-07-24 15:36:33 +05302694 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002695 status = platform_switch_voice_call_device_post(adev->platform,
2696 out_snd_device,
2697 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302698 enable_audio_route_for_voice_usecases(adev, usecase);
2699 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002700
sangwoo170731f2013-06-08 15:36:36 +09002701 usecase->in_snd_device = in_snd_device;
2702 usecase->out_snd_device = out_snd_device;
2703
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302704 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2705 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302706 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002707 if ((24 == usecase->stream.out->bit_width) &&
2708 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2709 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2710 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2711 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2712 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2713 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2714 /*
2715 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2716 * configured device sample rate, if not update the COPP rate to be equal to the
2717 * device sample rate, else open COPP at stream sample rate
2718 */
2719 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2720 usecase->stream.out->sample_rate,
2721 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302722 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2723 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002724 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2725 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2726 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2727 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002728 }
2729 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002730
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002731 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002732
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002733 /* If input stream is already running then effect needs to be
2734 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002735 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002736 check_and_enable_effect(adev);
2737
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002738 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002739 /* Enable aanc only if voice call exists */
2740 if (voice_is_call_state_active(adev))
2741 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2742
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002743 /* Enable sidetone only if other voice/voip call already exists */
2744 if (voice_is_call_state_active(adev) ||
2745 voice_extn_compress_voip_is_started(adev))
2746 voice_set_sidetone(adev, out_snd_device, true);
2747 }
2748
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002749 /* Applicable only on the targets that has external modem.
2750 * Enable device command should be sent to modem only after
2751 * enabling voice call mixer controls
2752 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002753 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002754 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2755 out_snd_device,
2756 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302757
2758 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002759 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302760 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002761 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302762 if (is_bt_soc_on(adev) == false){
2763 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002764 if (in->pcm != NULL)
2765 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302766 }
2767 }
2768 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2769 && usecase->stream.out->started) {
2770 if (is_bt_soc_on(adev) == false) {
2771 ALOGD("BT SCO/A2DP disconnected while in connection");
2772 out_standby_l(&usecase->stream.out->stream.common);
2773 }
2774 }
2775 } else if ((usecase->stream.out != NULL) &&
2776 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302777 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2778 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302779 usecase->stream.out->started) {
2780 if (is_bt_soc_on(adev) == false) {
2781 ALOGD("BT SCO/A2dp disconnected while in connection");
2782 out_standby_l(&usecase->stream.out->stream.common);
2783 }
2784 }
2785 }
2786
Yung Ti Su70cb8242018-06-22 17:38:47 +08002787 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002788 struct stream_out *voip_out = voip_usecase->stream.out;
2789 audio_extn_utils_send_app_type_gain(adev,
2790 voip_out->app_type_cfg.app_type,
2791 &voip_out->app_type_cfg.gain[0]);
2792 }
2793
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302794 ALOGD("%s: done",__func__);
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 return status;
2797}
2798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799static int stop_input_stream(struct stream_in *in)
2800{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302801 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302803
2804 if (in == NULL) {
2805 ALOGE("%s: stream_in ptr is NULL", __func__);
2806 return -EINVAL;
2807 }
2808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002810 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811
Eric Laurent994a6932013-07-17 11:51:42 -07002812 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002813 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 uc_info = get_usecase_from_list(adev, in->usecase);
2815 if (uc_info == NULL) {
2816 ALOGE("%s: Could not find the usecase (%d) in the list",
2817 __func__, in->usecase);
2818 return -EINVAL;
2819 }
2820
Carter Hsu2e429db2019-05-14 18:50:52 +08002821 priority_in = get_priority_input(adev);
2822
Derek Chenea197282019-01-07 17:35:01 -08002823 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2824 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002825
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002826 /* Close in-call recording streams */
2827 voice_check_and_stop_incall_rec_usecase(adev, in);
2828
Eric Laurent150dbfe2013-02-27 14:31:02 -08002829 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002830 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002831
2832 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002833 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302835 if (is_loopback_input_device(in->device))
2836 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2837
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002838 list_remove(&uc_info->list);
2839 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840
Carter Hsu2e429db2019-05-14 18:50:52 +08002841 if (priority_in == in) {
2842 priority_in = get_priority_input(adev);
2843 if (priority_in)
2844 select_devices(adev, priority_in->usecase);
2845 }
2846
Vatsal Buchac09ae062018-11-14 13:25:08 +05302847 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002848 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 return ret;
2850}
2851
2852int start_input_stream(struct stream_in *in)
2853{
2854 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002855 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302857
2858 if (in == NULL) {
2859 ALOGE("%s: stream_in ptr is NULL", __func__);
2860 return -EINVAL;
2861 }
2862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002864 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002865 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866
Mingming Yin2664a5b2015-09-03 10:53:11 -07002867 if (get_usecase_from_list(adev, usecase) == NULL)
2868 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302869 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2870 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002871
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302872 if (CARD_STATUS_OFFLINE == in->card_status||
2873 CARD_STATUS_OFFLINE == adev->card_status) {
2874 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302875 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302876 goto error_config;
2877 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302878
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302879 if (audio_is_bluetooth_sco_device(in->device)) {
2880 if (!adev->bt_sco_on) {
2881 ALOGE("%s: SCO profile is not ready, return error", __func__);
2882 ret = -EIO;
2883 goto error_config;
2884 }
2885 }
2886
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002887 /* Check if source matches incall recording usecase criteria */
2888 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2889 if (ret)
2890 goto error_config;
2891 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002892 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2893
2894 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2895 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2896 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002897 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002898 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002899
Eric Laurentb23d5282013-05-14 15:27:20 -07002900 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 if (in->pcm_device_id < 0) {
2902 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2903 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002904 ret = -EINVAL;
2905 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002909
2910 if (!uc_info) {
2911 ret = -ENOMEM;
2912 goto error_config;
2913 }
2914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 uc_info->id = in->usecase;
2916 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002917 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002918 uc_info->devices = in->device;
2919 uc_info->in_snd_device = SND_DEVICE_NONE;
2920 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002922 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002923 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302924 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2925 adev->perf_lock_opts,
2926 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002927 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928
Derek Chenea197282019-01-07 17:35:01 -08002929 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2930 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002931
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302932 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2933
Haynes Mathew George16081042017-05-31 17:16:49 -07002934 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302935 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302936 if (ret)
2937 goto error_open;
2938 else
2939 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002940 }
2941
Haynes Mathew George16081042017-05-31 17:16:49 -07002942 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002943 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002944 ALOGE("%s: pcm stream not ready", __func__);
2945 goto error_open;
2946 }
2947 ret = pcm_start(in->pcm);
2948 if (ret < 0) {
2949 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2950 goto error_open;
2951 }
2952 } else {
2953 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2954 unsigned int pcm_open_retry_count = 0;
2955
2956 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2957 flags |= PCM_MMAP | PCM_NOIRQ;
2958 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2959 } else if (in->realtime) {
2960 flags |= PCM_MMAP | PCM_NOIRQ;
2961 }
2962
Garmond Leunge2433c32017-09-28 21:51:22 -07002963 if (audio_extn_ffv_get_stream() == in) {
2964 ALOGD("%s: ffv stream, update pcm config", __func__);
2965 audio_extn_ffv_update_pcm_config(&config);
2966 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002967 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2968 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2969
2970 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002971 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002972 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002973 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002974 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302975 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302976 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2977 adev->card_status = CARD_STATUS_OFFLINE;
2978 in->card_status = CARD_STATUS_OFFLINE;
2979 ret = -EIO;
2980 goto error_open;
2981 }
2982
Haynes Mathew George16081042017-05-31 17:16:49 -07002983 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2984 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2985 if (in->pcm != NULL) {
2986 pcm_close(in->pcm);
2987 in->pcm = NULL;
2988 }
2989 if (pcm_open_retry_count-- == 0) {
2990 ret = -EIO;
2991 goto error_open;
2992 }
2993 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2994 continue;
2995 }
2996 break;
2997 }
2998
2999 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003000 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003001 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003002 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003003 if (ret < 0) {
3004 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3005 pcm_close(in->pcm);
3006 in->pcm = NULL;
3007 goto error_open;
3008 }
3009 register_in_stream(in);
3010 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003011 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003012 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003013 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003014 if (ret < 0) {
3015 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003016 pcm_close(in->pcm);
3017 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003018 goto error_open;
3019 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003020 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003021 }
3022
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003023 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003024 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3025 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003026
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303027 if (is_loopback_input_device(in->device))
3028 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3029
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303030done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003031 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303032 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003033 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303034 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003035 return ret;
3036
3037error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003038 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303039 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003041
Eric Laurentc8400632013-02-14 19:04:54 -08003042error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303043 /*
3044 * sleep 50ms to allow sufficient time for kernel
3045 * drivers to recover incases like SSR.
3046 */
3047 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003048 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303049 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003050 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051}
3052
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003053void lock_input_stream(struct stream_in *in)
3054{
3055 pthread_mutex_lock(&in->pre_lock);
3056 pthread_mutex_lock(&in->lock);
3057 pthread_mutex_unlock(&in->pre_lock);
3058}
3059
3060void lock_output_stream(struct stream_out *out)
3061{
3062 pthread_mutex_lock(&out->pre_lock);
3063 pthread_mutex_lock(&out->lock);
3064 pthread_mutex_unlock(&out->pre_lock);
3065}
3066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067/* must be called with out->lock locked */
3068static int send_offload_cmd_l(struct stream_out* out, int command)
3069{
3070 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3071
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003072 if (!cmd) {
3073 ALOGE("failed to allocate mem for command 0x%x", command);
3074 return -ENOMEM;
3075 }
3076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 ALOGVV("%s %d", __func__, command);
3078
3079 cmd->cmd = command;
3080 list_add_tail(&out->offload_cmd_list, &cmd->node);
3081 pthread_cond_signal(&out->offload_cond);
3082 return 0;
3083}
3084
3085/* must be called iwth out->lock locked */
3086static void stop_compressed_output_l(struct stream_out *out)
3087{
3088 out->offload_state = OFFLOAD_STATE_IDLE;
3089 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003090 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 if (out->compr != NULL) {
3092 compress_stop(out->compr);
3093 while (out->offload_thread_blocked) {
3094 pthread_cond_wait(&out->cond, &out->lock);
3095 }
3096 }
3097}
3098
Varun Balaraje49253e2017-07-06 19:48:56 +05303099bool is_interactive_usecase(audio_usecase_t uc_id)
3100{
3101 unsigned int i;
3102 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3103 if (uc_id == interactive_usecases[i])
3104 return true;
3105 }
3106 return false;
3107}
3108
3109static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3110{
3111 audio_usecase_t ret_uc = USECASE_INVALID;
3112 unsigned int intract_uc_index;
3113 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3114
3115 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3116 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3117 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3118 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3119 ret_uc = interactive_usecases[intract_uc_index];
3120 break;
3121 }
3122 }
3123
3124 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3125 return ret_uc;
3126}
3127
3128static void free_interactive_usecase(struct audio_device *adev,
3129 audio_usecase_t uc_id)
3130{
3131 unsigned int interact_uc_index;
3132 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3133
3134 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3135 if (interactive_usecases[interact_uc_index] == uc_id) {
3136 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3137 break;
3138 }
3139 }
3140 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3141}
3142
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003143bool is_offload_usecase(audio_usecase_t uc_id)
3144{
3145 unsigned int i;
3146 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3147 if (uc_id == offload_usecases[i])
3148 return true;
3149 }
3150 return false;
3151}
3152
Dhananjay Kumarac341582017-02-23 23:42:25 +05303153static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003154{
vivek mehta446c3962015-09-14 10:57:35 -07003155 audio_usecase_t ret_uc = USECASE_INVALID;
3156 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003157 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003158 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303159 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003160 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3161 else
3162 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003163
vivek mehta446c3962015-09-14 10:57:35 -07003164 pthread_mutex_lock(&adev->lock);
3165 if (get_usecase_from_list(adev, ret_uc) != NULL)
3166 ret_uc = USECASE_INVALID;
3167 pthread_mutex_unlock(&adev->lock);
3168
3169 return ret_uc;
3170 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003171
3172 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003173 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3174 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3175 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3176 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003177 break;
3178 }
3179 }
vivek mehta446c3962015-09-14 10:57:35 -07003180
3181 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3182 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003183}
3184
3185static void free_offload_usecase(struct audio_device *adev,
3186 audio_usecase_t uc_id)
3187{
vivek mehta446c3962015-09-14 10:57:35 -07003188 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003189 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003190
3191 if (!adev->multi_offload_enable)
3192 return;
3193
3194 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3195 if (offload_usecases[offload_uc_index] == uc_id) {
3196 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003197 break;
3198 }
3199 }
3200 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3201}
3202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003203static void *offload_thread_loop(void *context)
3204{
3205 struct stream_out *out = (struct stream_out *) context;
3206 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003207 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003208
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003210 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3212
3213 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003214 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003215 out->offload_state = OFFLOAD_STATE_IDLE;
3216 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 for (;;) {
3218 struct offload_cmd *cmd = NULL;
3219 stream_callback_event_t event;
3220 bool send_callback = false;
3221
3222 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3223 __func__, list_empty(&out->offload_cmd_list),
3224 out->offload_state);
3225 if (list_empty(&out->offload_cmd_list)) {
3226 ALOGV("%s SLEEPING", __func__);
3227 pthread_cond_wait(&out->offload_cond, &out->lock);
3228 ALOGV("%s RUNNING", __func__);
3229 continue;
3230 }
3231
3232 item = list_head(&out->offload_cmd_list);
3233 cmd = node_to_item(item, struct offload_cmd, node);
3234 list_remove(item);
3235
3236 ALOGVV("%s STATE %d CMD %d out->compr %p",
3237 __func__, out->offload_state, cmd->cmd, out->compr);
3238
3239 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3240 free(cmd);
3241 break;
3242 }
3243
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003244 // allow OFFLOAD_CMD_ERROR reporting during standby
3245 // this is needed to handle failures during compress_open
3246 // Note however that on a pause timeout, the stream is closed
3247 // and no offload usecase will be active. Therefore this
3248 // special case is needed for compress_open failures alone
3249 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3250 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003252 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 pthread_cond_signal(&out->cond);
3254 continue;
3255 }
3256 out->offload_thread_blocked = true;
3257 pthread_mutex_unlock(&out->lock);
3258 send_callback = false;
3259 switch(cmd->cmd) {
3260 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003261 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003263 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 send_callback = true;
3265 event = STREAM_CBK_EVENT_WRITE_READY;
3266 break;
3267 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003268 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303269 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003270 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303271 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003272 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303273 if (ret < 0)
3274 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303275 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303276 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003277 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003278 else
3279 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003280 if (-ENETRESET != ret && !(-EINTR == ret &&
3281 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303282 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303283 pthread_mutex_lock(&out->lock);
3284 out->send_new_metadata = 1;
3285 out->send_next_track_params = true;
3286 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303287 event = STREAM_CBK_EVENT_DRAIN_READY;
3288 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3289 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303290 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003291 break;
3292 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003293 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003294 ret = compress_drain(out->compr);
3295 ALOGD("copl(%p):out of compress_drain", out);
3296 // EINTR check avoids drain interruption due to SSR
3297 if (-ENETRESET != ret && !(-EINTR == ret &&
3298 CARD_STATUS_OFFLINE == out->card_status)) {
3299 send_callback = true;
3300 event = STREAM_CBK_EVENT_DRAIN_READY;
3301 } else
3302 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003303 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303304 case OFFLOAD_CMD_ERROR:
3305 ALOGD("copl(%p): sending error callback to AF", out);
3306 send_callback = true;
3307 event = STREAM_CBK_EVENT_ERROR;
3308 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 default:
3310 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3311 break;
3312 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003313 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003314 out->offload_thread_blocked = false;
3315 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003316 if (send_callback && out->client_callback) {
3317 ALOGVV("%s: sending client_callback event %d", __func__, event);
3318 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003319 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003320 free(cmd);
3321 }
3322
3323 pthread_cond_signal(&out->cond);
3324 while (!list_empty(&out->offload_cmd_list)) {
3325 item = list_head(&out->offload_cmd_list);
3326 list_remove(item);
3327 free(node_to_item(item, struct offload_cmd, node));
3328 }
3329 pthread_mutex_unlock(&out->lock);
3330
3331 return NULL;
3332}
3333
3334static int create_offload_callback_thread(struct stream_out *out)
3335{
3336 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3337 list_init(&out->offload_cmd_list);
3338 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3339 offload_thread_loop, out);
3340 return 0;
3341}
3342
3343static int destroy_offload_callback_thread(struct stream_out *out)
3344{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003345 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 stop_compressed_output_l(out);
3347 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3348
3349 pthread_mutex_unlock(&out->lock);
3350 pthread_join(out->offload_thread, (void **) NULL);
3351 pthread_cond_destroy(&out->offload_cond);
3352
3353 return 0;
3354}
3355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356static int stop_output_stream(struct stream_out *out)
3357{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303358 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 struct audio_usecase *uc_info;
3360 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003361 bool has_voip_usecase =
3362 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363
Eric Laurent994a6932013-07-17 11:51:42 -07003364 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003365 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 uc_info = get_usecase_from_list(adev, out->usecase);
3367 if (uc_info == NULL) {
3368 ALOGE("%s: Could not find the usecase (%d) in the list",
3369 __func__, out->usecase);
3370 return -EINVAL;
3371 }
3372
Derek Chenea197282019-01-07 17:35:01 -08003373 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3374 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003375
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003376 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303377 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003378 if (adev->visualizer_stop_output != NULL)
3379 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003380
3381 audio_extn_dts_remove_state_notifier_node(out->usecase);
3382
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003383 if (adev->offload_effects_stop_output != NULL)
3384 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003385 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3386 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3387 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003388 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003389
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003390 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3391 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003392 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003393 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003394
Eric Laurent150dbfe2013-02-27 14:31:02 -08003395 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003396 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003397
3398 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003399 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Aalique Grahame22e49102018-12-18 14:23:57 -08003401 audio_extn_extspk_update(adev->extspk);
3402
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003403 if (is_offload_usecase(out->usecase)) {
3404 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3405 adev->dsp_bit_width_enforce_mode,
3406 false);
3407 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003408 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3409 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3410 false);
3411
3412 if (ret != 0)
3413 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3414 /* default service interval was successfully updated,
3415 reopen USB backend with new service interval */
3416 ret = 0;
3417 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003418
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003419 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303420 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003421 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303422 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003423 ALOGV("Disable passthrough , reset mixer to pcm");
3424 /* NO_PASSTHROUGH */
3425 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003426 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003427 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3428 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003429
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303430 /* Must be called after removing the usecase from list */
3431 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303432 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303433
Manish Dewangan21a850a2017-08-14 12:03:55 +05303434 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003435 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3436 if (ret < 0)
3437 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3438 }
3439
juyuchen2d415992018-11-16 14:15:16 +08003440 /* 1) media + voip output routing to handset must route media back to
3441 speaker when voip stops.
3442 2) trigger voip input to reroute when voip output changes to
3443 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003444 if (has_voip_usecase ||
3445 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3446 struct listnode *node;
3447 struct audio_usecase *usecase;
3448 list_for_each(node, &adev->usecase_list) {
3449 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003450 if ((usecase->type == PCM_CAPTURE &&
3451 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3452 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003453 continue;
3454
3455 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3456 __func__, usecase->id, use_case_table[usecase->id],
3457 out->usecase, use_case_table[out->usecase]);
3458 select_devices(adev, usecase->id);
3459 }
3460 }
3461
Garmond Leung5fd0b552018-04-17 11:56:12 -07003462 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003463 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 return ret;
3465}
3466
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003467struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3468 unsigned int flags, unsigned int pcm_open_retry_count,
3469 struct pcm_config *config)
3470{
3471 struct pcm* pcm = NULL;
3472
3473 while (1) {
3474 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3475 if (pcm == NULL || !pcm_is_ready(pcm)) {
3476 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3477 if (pcm != NULL) {
3478 pcm_close(pcm);
3479 pcm = NULL;
3480 }
3481 if (pcm_open_retry_count-- == 0)
3482 return NULL;
3483
3484 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3485 continue;
3486 }
3487 break;
3488 }
3489
3490 if (pcm_is_ready(pcm)) {
3491 int ret = pcm_prepare(pcm);
3492 if (ret < 0) {
3493 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3494 pcm_close(pcm);
3495 pcm = NULL;
3496 }
3497 }
3498
3499 return pcm;
3500}
3501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502int start_output_stream(struct stream_out *out)
3503{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 struct audio_usecase *uc_info;
3506 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003507 char mixer_ctl_name[128];
3508 struct mixer_ctl *ctl = NULL;
3509 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303510 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003511 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
Haynes Mathew George380745d2017-10-04 15:27:45 -07003513 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003514 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3515 ret = -EINVAL;
3516 goto error_config;
3517 }
3518
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003519 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303520 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003521 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303522
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303523 if (CARD_STATUS_OFFLINE == out->card_status ||
3524 CARD_STATUS_OFFLINE == adev->card_status) {
3525 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303526 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303527 goto error_config;
3528 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303529
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003530 //Update incall music usecase to reflect correct voice session
3531 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3532 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3533 if (ret != 0) {
3534 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3535 __func__, ret);
3536 goto error_config;
3537 }
3538 }
3539
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303540 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003541 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003542 if (out->devices &
3543 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303544 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303545 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303546 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3547 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3548 ret = -EAGAIN;
3549 goto error_config;
3550 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303551 }
3552 }
3553 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303554 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3555 if (!adev->bt_sco_on) {
3556 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3557 //combo usecase just by pass a2dp
3558 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3559 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3560 } else {
3561 ALOGE("%s: SCO profile is not ready, return error", __func__);
3562 ret = -EAGAIN;
3563 goto error_config;
3564 }
3565 }
3566 }
3567
Eric Laurentb23d5282013-05-14 15:27:20 -07003568 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 if (out->pcm_device_id < 0) {
3570 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3571 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003572 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003573 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 }
3575
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003576 if (is_haptic_usecase) {
3577 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3578 if (adev->haptic_pcm_device_id < 0) {
3579 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3580 __func__, adev->haptic_pcm_device_id, out->usecase);
3581 ret = -EINVAL;
3582 goto error_config;
3583 }
3584 }
3585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003587
3588 if (!uc_info) {
3589 ret = -ENOMEM;
3590 goto error_config;
3591 }
3592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 uc_info->id = out->usecase;
3594 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003595 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003596 uc_info->devices = out->devices;
3597 uc_info->in_snd_device = SND_DEVICE_NONE;
3598 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003599
3600 /* This must be called before adding this usecase to the list */
3601 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3602 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3603 /* USB backend is not reopened immediately.
3604 This is eventually done as part of select_devices */
3605 }
3606
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003607 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608
Wei Wangf7ca6c92017-11-21 14:51:20 -08003609 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303610 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3611 adev->perf_lock_opts,
3612 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303613
3614 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303615 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303616 if (audio_extn_passthru_is_enabled() &&
3617 audio_extn_passthru_is_passthrough_stream(out)) {
3618 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303619 }
3620 }
3621
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303622 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003623 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303624 if (!a2dp_combo) {
3625 check_a2dp_restore_l(adev, out, false);
3626 } else {
3627 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003628 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3629 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3630 else
3631 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303632 select_devices(adev, out->usecase);
3633 out->devices = dev;
3634 }
3635 } else {
3636 select_devices(adev, out->usecase);
3637 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003638
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003639 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3640 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003641 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003642 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003643
Derek Chenea197282019-01-07 17:35:01 -08003644 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3645 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003646
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003647 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3648 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003649
3650 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003651 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003652 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3653 ALOGE("%s: pcm stream not ready", __func__);
3654 goto error_open;
3655 }
3656 ret = pcm_start(out->pcm);
3657 if (ret < 0) {
3658 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3659 goto error_open;
3660 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003661 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003662 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 unsigned int flags = PCM_OUT;
3664 unsigned int pcm_open_retry_count = 0;
3665 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3666 flags |= PCM_MMAP | PCM_NOIRQ;
3667 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003668 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003669 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003670 } else
3671 flags |= PCM_MONOTONIC;
3672
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003673 if ((adev->vr_audio_mode_enabled) &&
3674 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3675 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3676 "PCM_Dev %d Topology", out->pcm_device_id);
3677 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3678 if (!ctl) {
3679 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3680 __func__, mixer_ctl_name);
3681 } else {
3682 //if success use ULLPP
3683 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3684 __func__, mixer_ctl_name, out->pcm_device_id);
3685 //There is a still a possibility that some sessions
3686 // that request for FAST|RAW when 3D audio is active
3687 //can go through ULLPP. Ideally we expects apps to
3688 //listen to audio focus and stop concurrent playback
3689 //Also, we will look for mode flag (voice_in_communication)
3690 //before enabling the realtime flag.
3691 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3692 }
3693 }
3694
Surendar Karka91fa3682018-07-02 18:12:12 +05303695 if (out->realtime)
3696 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3697 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3698
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003699 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3700 flags, pcm_open_retry_count,
3701 &(out->config));
3702 if (out->pcm == NULL) {
3703 ret = -EIO;
3704 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003705 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003706
3707 if (is_haptic_usecase) {
3708 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3709 adev->haptic_pcm_device_id,
3710 flags, pcm_open_retry_count,
3711 &(adev->haptics_config));
3712 // failure to open haptics pcm shouldnt stop audio,
3713 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003714
3715 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3716 ALOGD("%s: enable haptic audio synchronization", __func__);
3717 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3718 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003719 }
3720
Surendar Karka91fa3682018-07-02 18:12:12 +05303721 if (!out->realtime)
3722 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303723 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003724
Zhou Song2b8f28f2017-09-11 10:51:38 +08003725 // apply volume for voip playback after path is set up
3726 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3727 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303728 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3729 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303730 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3731 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003732 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3733 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303734 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003735 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003736 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303737 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003738 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3739 adev->dsp_bit_width_enforce_mode,
3740 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003742 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003743 out->compr = compress_open(adev->snd_card,
3744 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003745 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003746 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303747 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303748 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3749 adev->card_status = CARD_STATUS_OFFLINE;
3750 out->card_status = CARD_STATUS_OFFLINE;
3751 ret = -EIO;
3752 goto error_open;
3753 }
3754
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003756 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 compress_close(out->compr);
3758 out->compr = NULL;
3759 ret = -EIO;
3760 goto error_open;
3761 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303762 /* compress_open sends params of the track, so reset the flag here */
3763 out->is_compr_metadata_avail = false;
3764
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003765 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003766 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003767
Fred Oh3f43e742015-03-04 18:42:34 -08003768 /* Since small bufs uses blocking writes, a write will be blocked
3769 for the default max poll time (20s) in the event of an SSR.
3770 Reduce the poll time to observe and deal with SSR faster.
3771 */
Ashish Jain5106d362016-05-11 19:23:33 +05303772 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003773 compress_set_max_poll_wait(out->compr, 1000);
3774 }
3775
Manish Dewangan69426c82017-01-30 17:35:36 +05303776 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303777 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303778
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003779 audio_extn_dts_create_state_notifier_node(out->usecase);
3780 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3781 popcount(out->channel_mask),
3782 out->playback_started);
3783
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003784#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303785 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003786 audio_extn_dolby_send_ddp_endp_params(adev);
3787#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303788 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3789 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003790 if (adev->visualizer_start_output != NULL)
3791 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3792 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303793 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003794 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003795 }
Derek Chenf13dd492018-11-13 14:53:51 -08003796
3797 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3798 /* Update cached volume from media to offload/direct stream */
3799 struct listnode *node = NULL;
3800 list_for_each(node, &adev->active_outputs_list) {
3801 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3802 streams_output_ctxt_t,
3803 list);
3804 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3805 out->volume_l = out_ctxt->output->volume_l;
3806 out->volume_r = out_ctxt->output->volume_r;
3807 }
3808 }
3809 out_set_compr_volume(&out->stream,
3810 out->volume_l, out->volume_r);
3811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003813
3814 if (ret == 0) {
3815 register_out_stream(out);
3816 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003817 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3818 ALOGE("%s: pcm stream not ready", __func__);
3819 goto error_open;
3820 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003821 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003822 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003823 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003824 if (ret < 0)
3825 goto error_open;
3826 }
3827 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003828 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303829 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003830 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003831
vivek mehtad15d2bf2019-05-17 13:35:10 -07003832 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3833 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3834 audio_low_latency_hint_start();
3835 }
3836
Manish Dewangan21a850a2017-08-14 12:03:55 +05303837 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003838 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003839 if (ret < 0)
3840 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3841 }
3842
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003843 // consider a scenario where on pause lower layers are tear down.
3844 // so on resume, swap mixer control need to be sent only when
3845 // backend is active, hence rather than sending from enable device
3846 // sending it from start of streamtream
3847
3848 platform_set_swap_channels(adev, true);
3849
Haynes Mathew George380745d2017-10-04 15:27:45 -07003850 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303851 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003852 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003854 if (adev->haptic_pcm) {
3855 pcm_close(adev->haptic_pcm);
3856 adev->haptic_pcm = NULL;
3857 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003858 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303859 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003861error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303862 /*
3863 * sleep 50ms to allow sufficient time for kernel
3864 * drivers to recover incases like SSR.
3865 */
3866 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003867 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303868 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003869 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870}
3871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872static int check_input_parameters(uint32_t sample_rate,
3873 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003874 int channel_count,
3875 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003877 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303879 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3880 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3881 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003882 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003883 !audio_extn_compr_cap_format_supported(format) &&
3884 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003885 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003886
Aalique Grahame22e49102018-12-18 14:23:57 -08003887 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3888 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3889 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3890 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3891 return -EINVAL;
3892 }
3893
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003894 switch (channel_count) {
3895 case 1:
3896 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303897 case 3:
3898 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003899 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003900 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303901 case 10:
3902 case 12:
3903 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003904 break;
3905 default:
3906 ret = -EINVAL;
3907 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908
3909 switch (sample_rate) {
3910 case 8000:
3911 case 11025:
3912 case 12000:
3913 case 16000:
3914 case 22050:
3915 case 24000:
3916 case 32000:
3917 case 44100:
3918 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003919 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303920 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003921 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303922 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 break;
3924 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003925 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 }
3927
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003928 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929}
3930
Naresh Tanniru04f71882018-06-26 17:46:22 +05303931
3932/** Add a value in a list if not already present.
3933 * @return true if value was successfully inserted or already present,
3934 * false if the list is full and does not contain the value.
3935 */
3936static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3937 for (size_t i = 0; i < list_length; i++) {
3938 if (list[i] == value) return true; // value is already present
3939 if (list[i] == 0) { // no values in this slot
3940 list[i] = value;
3941 return true; // value inserted
3942 }
3943 }
3944 return false; // could not insert value
3945}
3946
3947/** Add channel_mask in supported_channel_masks if not already present.
3948 * @return true if channel_mask was successfully inserted or already present,
3949 * false if supported_channel_masks is full and does not contain channel_mask.
3950 */
3951static void register_channel_mask(audio_channel_mask_t channel_mask,
3952 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3953 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3954 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3955}
3956
3957/** Add format in supported_formats if not already present.
3958 * @return true if format was successfully inserted or already present,
3959 * false if supported_formats is full and does not contain format.
3960 */
3961static void register_format(audio_format_t format,
3962 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3963 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3964 "%s: stream can not declare supporting its format %x", __func__, format);
3965}
3966/** Add sample_rate in supported_sample_rates if not already present.
3967 * @return true if sample_rate was successfully inserted or already present,
3968 * false if supported_sample_rates is full and does not contain sample_rate.
3969 */
3970static void register_sample_rate(uint32_t sample_rate,
3971 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3972 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3973 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3974}
3975
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003976static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3977{
3978 uint32_t high = num1, low = num2, temp = 0;
3979
3980 if (!num1 || !num2)
3981 return 0;
3982
3983 if (num1 < num2) {
3984 high = num2;
3985 low = num1;
3986 }
3987
3988 while (low != 0) {
3989 temp = low;
3990 low = high % low;
3991 high = temp;
3992 }
3993 return (num1 * num2)/high;
3994}
3995
3996static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3997{
3998 uint32_t remainder = 0;
3999
4000 if (!multiplier)
4001 return num;
4002
4003 remainder = num % multiplier;
4004 if (remainder)
4005 num += (multiplier - remainder);
4006
4007 return num;
4008}
4009
Aalique Grahame22e49102018-12-18 14:23:57 -08004010static size_t get_stream_buffer_size(size_t duration_ms,
4011 uint32_t sample_rate,
4012 audio_format_t format,
4013 int channel_count,
4014 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015{
4016 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004017 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018
Aalique Grahame22e49102018-12-18 14:23:57 -08004019 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004020 if (is_low_latency)
4021 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304022
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004023 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004024 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025
Ralf Herzbd08d632018-09-28 15:50:49 +02004026 /* make sure the size is multiple of 32 bytes and additionally multiple of
4027 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004028 * At 48 kHz mono 16-bit PCM:
4029 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4030 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004031 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004032 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004033 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004034
4035 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036}
4037
Aalique Grahame22e49102018-12-18 14:23:57 -08004038static size_t get_input_buffer_size(uint32_t sample_rate,
4039 audio_format_t format,
4040 int channel_count,
4041 bool is_low_latency)
4042{
4043 /* Don't know if USB HIFI in this context so use true to be conservative */
4044 if (check_input_parameters(sample_rate, format, channel_count,
4045 true /*is_usb_hifi */) != 0)
4046 return 0;
4047
4048 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4049 sample_rate,
4050 format,
4051 channel_count,
4052 is_low_latency);
4053}
4054
Derek Chenf6318be2017-06-12 17:16:24 -04004055size_t get_output_period_size(uint32_t sample_rate,
4056 audio_format_t format,
4057 int channel_count,
4058 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304059{
4060 size_t size = 0;
4061 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4062
4063 if ((duration == 0) || (sample_rate == 0) ||
4064 (bytes_per_sample == 0) || (channel_count == 0)) {
4065 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4066 bytes_per_sample, channel_count);
4067 return -EINVAL;
4068 }
4069
4070 size = (sample_rate *
4071 duration *
4072 bytes_per_sample *
4073 channel_count) / 1000;
4074 /*
4075 * To have same PCM samples for all channels, the buffer size requires to
4076 * be multiple of (number of channels * bytes per sample)
4077 * For writes to succeed, the buffer must be written at address which is multiple of 32
4078 */
4079 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4080
4081 return (size/(channel_count * bytes_per_sample));
4082}
4083
Zhou Song48453a02018-01-10 17:50:59 +08004084static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304085{
4086 uint64_t actual_frames_rendered = 0;
4087 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4088
4089 /* This adjustment accounts for buffering after app processor.
4090 * It is based on estimated DSP latency per use case, rather than exact.
4091 */
4092 int64_t platform_latency = platform_render_latency(out->usecase) *
4093 out->sample_rate / 1000000LL;
4094
Zhou Song48453a02018-01-10 17:50:59 +08004095 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304096 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4097 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4098 * hence only estimate.
4099 */
4100 int64_t signed_frames = out->written - kernel_buffer_size;
4101
4102 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4103
Zhou Song48453a02018-01-10 17:50:59 +08004104 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304105 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004106 if (timestamp != NULL )
4107 *timestamp = out->writeAt;
4108 } else if (timestamp != NULL) {
4109 clock_gettime(CLOCK_MONOTONIC, timestamp);
4110 }
4111 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304112
4113 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4114 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4115 (long long int)out->written, (int)kernel_buffer_size,
4116 audio_bytes_per_sample(out->compr_config.codec->format),
4117 popcount(out->channel_mask));
4118
4119 return actual_frames_rendered;
4120}
4121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4123{
4124 struct stream_out *out = (struct stream_out *)stream;
4125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004126 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127}
4128
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004129static int out_set_sample_rate(struct audio_stream *stream __unused,
4130 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131{
4132 return -ENOSYS;
4133}
4134
4135static size_t out_get_buffer_size(const struct audio_stream *stream)
4136{
4137 struct stream_out *out = (struct stream_out *)stream;
4138
Varun Balaraje49253e2017-07-06 19:48:56 +05304139 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304140 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304141 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304142 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4143 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4144 else
4145 return out->compr_config.fragment_size;
4146 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004147 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304148 else if (is_offload_usecase(out->usecase) &&
4149 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304150 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004152 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004153 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154}
4155
4156static uint32_t out_get_channels(const struct audio_stream *stream)
4157{
4158 struct stream_out *out = (struct stream_out *)stream;
4159
4160 return out->channel_mask;
4161}
4162
4163static audio_format_t out_get_format(const struct audio_stream *stream)
4164{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004165 struct stream_out *out = (struct stream_out *)stream;
4166
4167 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168}
4169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004170static int out_set_format(struct audio_stream *stream __unused,
4171 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172{
4173 return -ENOSYS;
4174}
4175
4176static int out_standby(struct audio_stream *stream)
4177{
4178 struct stream_out *out = (struct stream_out *)stream;
4179 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004180 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004181
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304182 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4183 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004185 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004187 if (adev->adm_deregister_stream)
4188 adev->adm_deregister_stream(adev->adm_data, out->handle);
4189
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004190 if (is_offload_usecase(out->usecase))
4191 stop_compressed_output_l(out);
4192
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004193 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004195 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4196 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304197 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004198 pthread_mutex_unlock(&adev->lock);
4199 pthread_mutex_unlock(&out->lock);
4200 ALOGD("VOIP output entered standby");
4201 return 0;
4202 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004203 if (out->pcm) {
4204 pcm_close(out->pcm);
4205 out->pcm = NULL;
4206 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004207 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4208 do_stop = out->playback_started;
4209 out->playback_started = false;
4210 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004211 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004212 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304213 out->send_next_track_params = false;
4214 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004215 out->gapless_mdata.encoder_delay = 0;
4216 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004217 if (out->compr != NULL) {
4218 compress_close(out->compr);
4219 out->compr = NULL;
4220 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004221 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004222 if (do_stop) {
4223 stop_output_stream(out);
4224 }
Lakshman Chaluvaraju40459022019-06-24 10:04:52 +05304225 // if fm is active route on selected device in UI
4226 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004227 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228 }
4229 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304230 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231 return 0;
4232}
4233
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304234static int out_on_error(struct audio_stream *stream)
4235{
4236 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004237 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304238
4239 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004240 // always send CMD_ERROR for offload streams, this
4241 // is needed e.g. when SSR happens within compress_open
4242 // since the stream is active, offload_callback_thread is also active.
4243 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4244 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004245 }
4246 pthread_mutex_unlock(&out->lock);
4247
4248 status = out_standby(&out->stream.common);
4249
4250 lock_output_stream(out);
4251 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004252 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304253 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304254
4255 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4256 ALOGD("Setting previous card status if offline");
4257 out->prev_card_status_offline = true;
4258 }
4259
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304260 pthread_mutex_unlock(&out->lock);
4261
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004262 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304263}
4264
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304265/*
4266 *standby implementation without locks, assumes that the callee already
4267 *has taken adev and out lock.
4268 */
4269int out_standby_l(struct audio_stream *stream)
4270{
4271 struct stream_out *out = (struct stream_out *)stream;
4272 struct audio_device *adev = out->dev;
4273
4274 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4275 stream, out->usecase, use_case_table[out->usecase]);
4276
4277 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004278 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304279 if (adev->adm_deregister_stream)
4280 adev->adm_deregister_stream(adev->adm_data, out->handle);
4281
4282 if (is_offload_usecase(out->usecase))
4283 stop_compressed_output_l(out);
4284
4285 out->standby = true;
4286 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4287 voice_extn_compress_voip_close_output_stream(stream);
4288 out->started = 0;
4289 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004290 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304291 return 0;
4292 } else if (!is_offload_usecase(out->usecase)) {
4293 if (out->pcm) {
4294 pcm_close(out->pcm);
4295 out->pcm = NULL;
4296 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004297 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4298 if (adev->haptic_pcm) {
4299 pcm_close(adev->haptic_pcm);
4300 adev->haptic_pcm = NULL;
4301 }
4302
4303 if (adev->haptic_buffer != NULL) {
4304 free(adev->haptic_buffer);
4305 adev->haptic_buffer = NULL;
4306 adev->haptic_buffer_size = 0;
4307 }
4308 adev->haptic_pcm_device_id = 0;
4309 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304310 } else {
4311 ALOGD("copl(%p):standby", out);
4312 out->send_next_track_params = false;
4313 out->is_compr_metadata_avail = false;
4314 out->gapless_mdata.encoder_delay = 0;
4315 out->gapless_mdata.encoder_padding = 0;
4316 if (out->compr != NULL) {
4317 compress_close(out->compr);
4318 out->compr = NULL;
4319 }
4320 }
4321 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004322 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304323 }
4324 ALOGD("%s: exit", __func__);
4325 return 0;
4326}
4327
Aalique Grahame22e49102018-12-18 14:23:57 -08004328static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329{
Aalique Grahame22e49102018-12-18 14:23:57 -08004330 struct stream_out *out = (struct stream_out *)stream;
4331
4332 // We try to get the lock for consistency,
4333 // but it isn't necessary for these variables.
4334 // If we're not in standby, we may be blocked on a write.
4335 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4336 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4337 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4338
4339 if (locked) {
4340 pthread_mutex_unlock(&out->lock);
4341 }
4342
4343 // dump error info
4344 (void)error_log_dump(
4345 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 return 0;
4348}
4349
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004350static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4351{
4352 int ret = 0;
4353 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004354
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004355 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004356 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004357 return -EINVAL;
4358 }
4359
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304360 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004361
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004362 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4363 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304364 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004365 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004366 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4367 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304368 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004369 }
4370
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004371 ALOGV("%s new encoder delay %u and padding %u", __func__,
4372 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4373
4374 return 0;
4375}
4376
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004377static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4378{
4379 return out == adev->primary_output || out == adev->voice_tx_output;
4380}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004381
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304382// note: this call is safe only if the stream_cb is
4383// removed first in close_output_stream (as is done now).
4384static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4385{
4386 if (!stream || !parms)
4387 return;
4388
4389 struct stream_out *out = (struct stream_out *)stream;
4390 struct audio_device *adev = out->dev;
4391
4392 card_status_t status;
4393 int card;
4394 if (parse_snd_card_status(parms, &card, &status) < 0)
4395 return;
4396
4397 pthread_mutex_lock(&adev->lock);
4398 bool valid_cb = (card == adev->snd_card);
4399 pthread_mutex_unlock(&adev->lock);
4400
4401 if (!valid_cb)
4402 return;
4403
4404 lock_output_stream(out);
4405 if (out->card_status != status)
4406 out->card_status = status;
4407 pthread_mutex_unlock(&out->lock);
4408
4409 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4410 use_case_table[out->usecase],
4411 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4412
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304413 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304414 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304415 if (voice_is_call_state_active(adev) &&
4416 out == adev->primary_output) {
4417 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4418 pthread_mutex_lock(&adev->lock);
4419 voice_stop_call(adev);
4420 adev->mode = AUDIO_MODE_NORMAL;
4421 pthread_mutex_unlock(&adev->lock);
4422 }
4423 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304424 return;
4425}
4426
Kevin Rocardfce19002017-08-07 19:21:36 -07004427static int get_alive_usb_card(struct str_parms* parms) {
4428 int card;
4429 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4430 !audio_extn_usb_alive(card)) {
4431 return card;
4432 }
4433 return -ENODEV;
4434}
4435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4437{
4438 struct stream_out *out = (struct stream_out *)stream;
4439 struct audio_device *adev = out->dev;
4440 struct str_parms *parms;
4441 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004442 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304443 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004444 bool reconfig = false;
4445 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446
sangwoobc677242013-08-08 16:53:43 +09004447 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004448 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004449 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304450 if (!parms)
4451 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004452 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4453 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004455 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004456 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004458 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004459 * When HDMI cable is unplugged the music playback is paused and
4460 * the policy manager sends routing=0. But the audioflinger continues
4461 * to write data until standby time (3sec). As the HDMI core is
4462 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004463 * Avoid this by routing audio to speaker until standby.
4464 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004465 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4466 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304467 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004468 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4469 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004470 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304471 /*
4472 * When A2DP is disconnected the
4473 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004474 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304475 * (3sec). As BT is turned off, the write gets blocked.
4476 * Avoid this by routing audio to speaker until standby.
4477 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004478 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004479 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004480 !audio_extn_a2dp_source_is_ready() &&
4481 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304482 val = AUDIO_DEVICE_OUT_SPEAKER;
4483 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304484 /*
4485 * When USB headset is disconnected the music platback paused
4486 * and the policy manager send routing=0. But if the USB is connected
4487 * back before the standby time, AFE is not closed and opened
4488 * when USB is connected back. So routing to speker will guarantee
4489 * AFE reconfiguration and AFE will be opend once USB is connected again
4490 */
4491 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4492 (val == AUDIO_DEVICE_NONE) &&
4493 !audio_extn_usb_connected(parms)) {
4494 val = AUDIO_DEVICE_OUT_SPEAKER;
4495 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304496 /* To avoid a2dp to sco overlapping / BT device improper state
4497 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304498 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304499 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004500 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004501 if (val &
4502 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304503 //combo usecase just by pass a2dp
4504 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304505 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304506 } else {
4507 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4508 /* update device to a2dp and don't route as BT returned error
4509 * However it is still possible a2dp routing called because
4510 * of current active device disconnection (like wired headset)
4511 */
4512 out->devices = val;
4513 pthread_mutex_unlock(&out->lock);
4514 pthread_mutex_unlock(&adev->lock);
4515 goto error;
4516 }
4517 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304518 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004519
4520 audio_devices_t new_dev = val;
4521
4522 // Workaround: If routing to an non existing usb device, fail gracefully
4523 // The routing request will otherwise block during 10 second
4524 int card;
4525 if (audio_is_usb_out_device(new_dev) &&
4526 (card = get_alive_usb_card(parms)) >= 0) {
4527
4528 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4529 pthread_mutex_unlock(&adev->lock);
4530 pthread_mutex_unlock(&out->lock);
4531 ret = -ENOSYS;
4532 goto routing_fail;
4533 }
4534
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004535 /*
4536 * select_devices() call below switches all the usecases on the same
4537 * backend to the new device. Refer to check_usecases_codec_backend() in
4538 * the select_devices(). But how do we undo this?
4539 *
4540 * For example, music playback is active on headset (deep-buffer usecase)
4541 * and if we go to ringtones and select a ringtone, low-latency usecase
4542 * will be started on headset+speaker. As we can't enable headset+speaker
4543 * and headset devices at the same time, select_devices() switches the music
4544 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4545 * So when the ringtone playback is completed, how do we undo the same?
4546 *
4547 * We are relying on the out_set_parameters() call on deep-buffer output,
4548 * once the ringtone playback is ended.
4549 * NOTE: We should not check if the current devices are same as new devices.
4550 * Because select_devices() must be called to switch back the music
4551 * playback to headset.
4552 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004553 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004554 audio_devices_t new_dev = val;
4555 bool same_dev = out->devices == new_dev;
4556 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004557
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004558 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004559 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004560 if (adev->mode == AUDIO_MODE_IN_CALL) {
4561 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004562 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4563 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4564 audio_extn_usb_set_service_interval(true /*playback*/,
4565 service_interval,
4566 &reconfig);
4567 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4568 }
4569 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004570 }
4571 } else {
4572 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004573 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004574 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004575 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004576
4577 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004578 if (!same_dev) {
4579 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304580 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4581 adev->perf_lock_opts,
4582 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004583 if (adev->adm_on_routing_change)
4584 adev->adm_on_routing_change(adev->adm_data,
4585 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004586 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304587 if (!bypass_a2dp) {
4588 select_devices(adev, out->usecase);
4589 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004590 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4591 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4592 else
4593 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304594 select_devices(adev, out->usecase);
4595 out->devices = new_dev;
4596 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004597
4598 if (!same_dev) {
4599 // on device switch force swap, lower functions will make sure
4600 // to check if swap is allowed or not.
4601 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304602 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004603 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304604 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4605 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004606 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304607 pthread_mutex_lock(&out->compr_mute_lock);
4608 out->a2dp_compress_mute = false;
4609 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4610 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004611 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4612 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304613 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004614 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004615 }
4616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004618 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004619
4620 /*handles device and call state changes*/
4621 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004623 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004624
4625 if (out == adev->primary_output) {
4626 pthread_mutex_lock(&adev->lock);
4627 audio_extn_set_parameters(adev, parms);
4628 pthread_mutex_unlock(&adev->lock);
4629 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004630 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004631 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004632 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004633
4634 audio_extn_dts_create_state_notifier_node(out->usecase);
4635 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4636 popcount(out->channel_mask),
4637 out->playback_started);
4638
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004639 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004640 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004641
Surendar Karkaf51b5842018-04-26 11:28:38 +05304642 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4643 sizeof(value));
4644 if (err >= 0) {
4645 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4646 audio_extn_send_dual_mono_mixing_coefficients(out);
4647 }
4648
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304649 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4650 if (err >= 0) {
4651 strlcpy(out->profile, value, sizeof(out->profile));
4652 ALOGV("updating stream profile with value '%s'", out->profile);
4653 lock_output_stream(out);
4654 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4655 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004656 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304657 out->sample_rate, out->bit_width,
4658 out->channel_mask, out->profile,
4659 &out->app_type_cfg);
4660 pthread_mutex_unlock(&out->lock);
4661 }
4662
Alexy Joseph98988832017-01-13 14:56:59 -08004663 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004664 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4665 // and vendor.audio.hal.output.suspend.supported is set to true
4666 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004667 //check suspend parameter only for low latency and if the property
4668 //is enabled
4669 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4670 ALOGI("%s: got suspend_playback %s", __func__, value);
4671 lock_output_stream(out);
4672 if (!strncmp(value, "false", 5)) {
4673 //suspend_playback=false is supposed to set QOS value back to 75%
4674 //the mixer control sent with value Enable will achieve that
4675 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4676 } else if (!strncmp (value, "true", 4)) {
4677 //suspend_playback=true is supposed to remove QOS value
4678 //resetting the mixer control will set the default value
4679 //for the mixer control which is Disable and this removes the QOS vote
4680 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4681 } else {
4682 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4683 " got %s", __func__, value);
4684 ret = -1;
4685 }
4686
4687 if (ret != 0) {
4688 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4689 __func__, out->pm_qos_mixer_path, ret);
4690 }
4691
4692 pthread_mutex_unlock(&out->lock);
4693 }
4694 }
4695 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304697error:
Eric Laurent994a6932013-07-17 11:51:42 -07004698 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 return ret;
4700}
4701
Paul McLeana50b7332018-12-17 08:24:21 -07004702static int in_set_microphone_direction(const struct audio_stream_in *stream,
4703 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004704 struct stream_in *in = (struct stream_in *)stream;
4705
4706 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4707
4708 in->direction = dir;
4709
4710 if (in->standby)
4711 return 0;
4712
4713 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004714}
4715
4716static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004717 struct stream_in *in = (struct stream_in *)stream;
4718
4719 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4720
4721 if (zoom > 1.0 || zoom < -1.0)
4722 return -EINVAL;
4723
4724 in->zoom = zoom;
4725
4726 if (in->standby)
4727 return 0;
4728
4729 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004730}
4731
4732
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004733static bool stream_get_parameter_channels(struct str_parms *query,
4734 struct str_parms *reply,
4735 audio_channel_mask_t *supported_channel_masks) {
4736 int ret = -1;
4737 char value[512];
4738 bool first = true;
4739 size_t i, j;
4740
4741 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4742 ret = 0;
4743 value[0] = '\0';
4744 i = 0;
4745 while (supported_channel_masks[i] != 0) {
4746 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4747 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4748 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304749 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004750
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304751 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004752 first = false;
4753 break;
4754 }
4755 }
4756 i++;
4757 }
4758 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4759 }
4760 return ret == 0;
4761}
4762
4763static bool stream_get_parameter_formats(struct str_parms *query,
4764 struct str_parms *reply,
4765 audio_format_t *supported_formats) {
4766 int ret = -1;
4767 char value[256];
4768 size_t i, j;
4769 bool first = true;
4770
4771 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4772 ret = 0;
4773 value[0] = '\0';
4774 i = 0;
4775 while (supported_formats[i] != 0) {
4776 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4777 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4778 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304779 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004780 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304781 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004782 first = false;
4783 break;
4784 }
4785 }
4786 i++;
4787 }
4788 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4789 }
4790 return ret == 0;
4791}
4792
4793static bool stream_get_parameter_rates(struct str_parms *query,
4794 struct str_parms *reply,
4795 uint32_t *supported_sample_rates) {
4796
4797 int i;
4798 char value[256];
4799 int ret = -1;
4800 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4801 ret = 0;
4802 value[0] = '\0';
4803 i=0;
4804 int cursor = 0;
4805 while (supported_sample_rates[i]) {
4806 int avail = sizeof(value) - cursor;
4807 ret = snprintf(value + cursor, avail, "%s%d",
4808 cursor > 0 ? "|" : "",
4809 supported_sample_rates[i]);
4810 if (ret < 0 || ret >= avail) {
4811 // if cursor is at the last element of the array
4812 // overwrite with \0 is duplicate work as
4813 // snprintf already put a \0 in place.
4814 // else
4815 // we had space to write the '|' at value[cursor]
4816 // (which will be overwritten) or no space to fill
4817 // the first element (=> cursor == 0)
4818 value[cursor] = '\0';
4819 break;
4820 }
4821 cursor += ret;
4822 ++i;
4823 }
4824 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4825 value);
4826 }
4827 return ret >= 0;
4828}
4829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4831{
4832 struct stream_out *out = (struct stream_out *)stream;
4833 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004834 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835 char value[256];
4836 struct str_parms *reply = str_parms_create();
4837 size_t i, j;
4838 int ret;
4839 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004840
4841 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004842 if (reply) {
4843 str_parms_destroy(reply);
4844 }
4845 if (query) {
4846 str_parms_destroy(query);
4847 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004848 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4849 return NULL;
4850 }
4851
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004852 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4854 if (ret >= 0) {
4855 value[0] = '\0';
4856 i = 0;
4857 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004858 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4859 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004861 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004863 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 first = false;
4865 break;
4866 }
4867 }
4868 i++;
4869 }
4870 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4871 str = str_parms_to_str(reply);
4872 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004873 voice_extn_out_get_parameters(out, query, reply);
4874 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004876
Alexy Joseph62142aa2015-11-16 15:10:34 -08004877
4878 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4879 if (ret >= 0) {
4880 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304881 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4882 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004883 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304884 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004885 } else {
4886 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304887 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004888 }
4889 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004890 if (str)
4891 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004892 str = str_parms_to_str(reply);
4893 }
4894
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004895 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4896 if (ret >= 0) {
4897 value[0] = '\0';
4898 i = 0;
4899 first = true;
4900 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004901 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4902 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004903 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004904 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004905 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004906 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004907 first = false;
4908 break;
4909 }
4910 }
4911 i++;
4912 }
4913 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004914 if (str)
4915 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004916 str = str_parms_to_str(reply);
4917 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004918
4919 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4920 if (ret >= 0) {
4921 value[0] = '\0';
4922 i = 0;
4923 first = true;
4924 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004925 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4926 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004927 if (!first) {
4928 strlcat(value, "|", sizeof(value));
4929 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004930 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004931 first = false;
4932 break;
4933 }
4934 }
4935 i++;
4936 }
4937 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4938 if (str)
4939 free(str);
4940 str = str_parms_to_str(reply);
4941 }
4942
Alexy Joseph98988832017-01-13 14:56:59 -08004943 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4944 //only low latency track supports suspend_resume
4945 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004946 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004947 if (str)
4948 free(str);
4949 str = str_parms_to_str(reply);
4950 }
4951
4952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004953 str_parms_destroy(query);
4954 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004955 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 return str;
4957}
4958
4959static uint32_t out_get_latency(const struct audio_stream_out *stream)
4960{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004961 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004962 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004963 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004964
Alexy Josephaa54c872014-12-03 02:46:47 -08004965 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304966 lock_output_stream(out);
4967 latency = audio_extn_utils_compress_get_dsp_latency(out);
4968 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004969 } else if ((out->realtime) ||
4970 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004971 // since the buffer won't be filled up faster than realtime,
4972 // return a smaller number
4973 if (out->config.rate)
4974 period_ms = (out->af_period_multiplier * out->config.period_size *
4975 1000) / (out->config.rate);
4976 else
4977 period_ms = 0;
4978 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004979 } else {
4980 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004981 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004982 }
4983
yidongh0515e042017-07-06 15:00:34 +08004984 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004985 latency += audio_extn_a2dp_get_encoder_latency();
4986
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304987 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004988 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989}
4990
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304991static float AmpToDb(float amplification)
4992{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304993 float db = DSD_VOLUME_MIN_DB;
4994 if (amplification > 0) {
4995 db = 20 * log10(amplification);
4996 if(db < DSD_VOLUME_MIN_DB)
4997 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304998 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304999 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305000}
5001
Arun Mirpuri5d170872019-03-26 13:21:31 -07005002static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5003 float right)
5004{
5005 struct stream_out *out = (struct stream_out *)stream;
5006 long volume = 0;
5007 char mixer_ctl_name[128] = "";
5008 struct audio_device *adev = out->dev;
5009 struct mixer_ctl *ctl = NULL;
5010 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5011 PCM_PLAYBACK);
5012
5013 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5014 "Playback %d Volume", pcm_device_id);
5015 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5016 if (!ctl) {
5017 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5018 __func__, mixer_ctl_name);
5019 return -EINVAL;
5020 }
5021 if (left != right)
5022 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5023 __func__, left, right);
5024 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5025 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5026 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5027 __func__, mixer_ctl_name, volume);
5028 return -EINVAL;
5029 }
5030 return 0;
5031}
5032
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305033static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5034 float right)
5035{
5036 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305037 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305038 char mixer_ctl_name[128];
5039 struct audio_device *adev = out->dev;
5040 struct mixer_ctl *ctl;
5041 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5042 PCM_PLAYBACK);
5043
5044 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5045 "Compress Playback %d Volume", pcm_device_id);
5046 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5047 if (!ctl) {
5048 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5049 __func__, mixer_ctl_name);
5050 return -EINVAL;
5051 }
5052 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5053 __func__, mixer_ctl_name, left, right);
5054 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5055 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5056 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5057
5058 return 0;
5059}
5060
Zhou Song2b8f28f2017-09-11 10:51:38 +08005061static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5062 float right)
5063{
5064 struct stream_out *out = (struct stream_out *)stream;
5065 char mixer_ctl_name[] = "App Type Gain";
5066 struct audio_device *adev = out->dev;
5067 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305068 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005069
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005070 if (!is_valid_volume(left, right)) {
5071 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5072 __func__, left, right);
5073 return -EINVAL;
5074 }
5075
Zhou Song2b8f28f2017-09-11 10:51:38 +08005076 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5077 if (!ctl) {
5078 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5079 __func__, mixer_ctl_name);
5080 return -EINVAL;
5081 }
5082
5083 set_values[0] = 0; //0: Rx Session 1:Tx Session
5084 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305085 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5086 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005087
5088 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5089 return 0;
5090}
5091
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305092static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5093 float right)
5094{
5095 struct stream_out *out = (struct stream_out *)stream;
5096 /* Volume control for pcm playback */
5097 if (left != right) {
5098 return -EINVAL;
5099 } else {
5100 char mixer_ctl_name[128];
5101 struct audio_device *adev = out->dev;
5102 struct mixer_ctl *ctl;
5103 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5104 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5105 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5106 if (!ctl) {
5107 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5108 return -EINVAL;
5109 }
5110
5111 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5112 int ret = mixer_ctl_set_value(ctl, 0, volume);
5113 if (ret < 0) {
5114 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5115 return -EINVAL;
5116 }
5117
5118 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5119
5120 return 0;
5121 }
5122}
5123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005124static int out_set_volume(struct audio_stream_out *stream, float left,
5125 float right)
5126{
Eric Laurenta9024de2013-04-04 09:19:12 -07005127 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005128 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305129 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005130
Arun Mirpuri5d170872019-03-26 13:21:31 -07005131 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005132 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5133 /* only take left channel into account: the API is for stereo anyway */
5134 out->muted = (left == 0.0f);
5135 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005136 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305137 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005138 /*
5139 * Set mute or umute on HDMI passthrough stream.
5140 * Only take left channel into account.
5141 * Mute is 0 and unmute 1
5142 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305143 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305144 } else if (out->format == AUDIO_FORMAT_DSD){
5145 char mixer_ctl_name[128] = "DSD Volume";
5146 struct audio_device *adev = out->dev;
5147 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5148
5149 if (!ctl) {
5150 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5151 __func__, mixer_ctl_name);
5152 return -EINVAL;
5153 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305154 volume[0] = (long)(AmpToDb(left));
5155 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305156 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5157 return 0;
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005158 } else if ((out->devices & AUDIO_DEVICE_OUT_BUS) &&
5159 (audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) ==
5160 SND_DEVICE_OUT_BUS_MEDIA)) {
5161 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5162 struct listnode *node = NULL;
5163 list_for_each(node, &adev->active_outputs_list) {
5164 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5165 streams_output_ctxt_t,
5166 list);
5167 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5168 out->volume_l = out_ctxt->output->volume_l;
5169 out->volume_r = out_ctxt->output->volume_r;
5170 }
5171 }
5172 if (!out->a2dp_compress_mute) {
5173 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5174 }
5175 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005176 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305177 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005178 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305179 if (!out->a2dp_compress_mute)
5180 ret = out_set_compr_volume(stream, left, right);
5181 out->volume_l = left;
5182 out->volume_r = right;
5183 pthread_mutex_unlock(&out->compr_mute_lock);
5184 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005185 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005186 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005187 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5188 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5189 if (!out->standby) {
5190 audio_extn_utils_send_app_type_gain(out->dev,
5191 out->app_type_cfg.app_type,
5192 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005193 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005194 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005195 out->volume_l = left;
5196 out->volume_r = right;
5197 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005198 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5199 ALOGV("%s: MMAP set volume called", __func__);
5200 if (!out->standby)
5201 ret = out_set_mmap_volume(stream, left, right);
5202 out->volume_l = left;
5203 out->volume_r = right;
5204 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305205 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305206 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5207 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305208 /* Volume control for pcm playback */
5209 if (!out->standby)
5210 ret = out_set_pcm_volume(stream, left, right);
5211 else
5212 out->apply_volume = true;
5213
5214 out->volume_l = left;
5215 out->volume_r = right;
5216 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005217 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5218 ALOGV("%s: bus device set volume called", __func__);
5219 if (!out->standby)
5220 ret = out_set_pcm_volume(stream, left, right);
5221 out->volume_l = left;
5222 out->volume_r = right;
5223 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005224 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226 return -ENOSYS;
5227}
5228
Zhou Songc9672822017-08-16 16:01:39 +08005229static void update_frames_written(struct stream_out *out, size_t bytes)
5230{
5231 size_t bpf = 0;
5232
5233 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5234 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5235 bpf = 1;
5236 else if (!is_offload_usecase(out->usecase))
5237 bpf = audio_bytes_per_sample(out->format) *
5238 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005239
5240 pthread_mutex_lock(&out->position_query_lock);
5241 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005242 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005243 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5244 }
5245 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005246}
5247
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005248int split_and_write_audio_haptic_data(struct stream_out *out,
5249 const void *buffer, size_t bytes_to_write)
5250{
5251 struct audio_device *adev = out->dev;
5252
5253 int ret = 0;
5254 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5255 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5256 size_t frame_size = channel_count * bytes_per_sample;
5257 size_t frame_count = bytes_to_write / frame_size;
5258
5259 bool force_haptic_path =
5260 property_get_bool("vendor.audio.test_haptic", false);
5261
5262 // extract Haptics data from Audio buffer
5263 bool alloc_haptic_buffer = false;
5264 int haptic_channel_count = adev->haptics_config.channels;
5265 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5266 size_t audio_frame_size = frame_size - haptic_frame_size;
5267 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5268
5269 if (adev->haptic_buffer == NULL) {
5270 alloc_haptic_buffer = true;
5271 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5272 free(adev->haptic_buffer);
5273 adev->haptic_buffer_size = 0;
5274 alloc_haptic_buffer = true;
5275 }
5276
5277 if (alloc_haptic_buffer) {
5278 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005279 if(adev->haptic_buffer == NULL) {
5280 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5281 return -ENOMEM;
5282 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005283 adev->haptic_buffer_size = total_haptic_buffer_size;
5284 }
5285
5286 size_t src_index = 0, aud_index = 0, hap_index = 0;
5287 uint8_t *audio_buffer = (uint8_t *)buffer;
5288 uint8_t *haptic_buffer = adev->haptic_buffer;
5289
5290 // This is required for testing only. This works for stereo data only.
5291 // One channel is fed to audio stream and other to haptic stream for testing.
5292 if (force_haptic_path)
5293 audio_frame_size = haptic_frame_size = bytes_per_sample;
5294
5295 for (size_t i = 0; i < frame_count; i++) {
5296 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5297 audio_frame_size);
5298 aud_index += audio_frame_size;
5299 src_index += audio_frame_size;
5300
5301 if (adev->haptic_pcm)
5302 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5303 haptic_frame_size);
5304 hap_index += haptic_frame_size;
5305 src_index += haptic_frame_size;
5306
5307 // This is required for testing only.
5308 // Discard haptic channel data.
5309 if (force_haptic_path)
5310 src_index += haptic_frame_size;
5311 }
5312
5313 // write to audio pipeline
5314 ret = pcm_write(out->pcm, (void *)audio_buffer,
5315 frame_count * audio_frame_size);
5316
5317 // write to haptics pipeline
5318 if (adev->haptic_pcm)
5319 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5320 frame_count * haptic_frame_size);
5321
5322 return ret;
5323}
5324
Aalique Grahame22e49102018-12-18 14:23:57 -08005325#ifdef NO_AUDIO_OUT
5326static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5327 const void *buffer __unused, size_t bytes)
5328{
5329 struct stream_out *out = (struct stream_out *)stream;
5330
5331 /* No Output device supported other than BT for playback.
5332 * Sleep for the amount of buffer duration
5333 */
5334 lock_output_stream(out);
5335 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5336 (const struct audio_stream_out *)&out->stream) /
5337 out_get_sample_rate(&out->stream.common));
5338 pthread_mutex_unlock(&out->lock);
5339 return bytes;
5340}
5341#endif
5342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005343static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5344 size_t bytes)
5345{
5346 struct stream_out *out = (struct stream_out *)stream;
5347 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005348 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305349 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005350 const size_t frame_size = audio_stream_out_frame_size(stream);
5351 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305352 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353
Haynes Mathew George380745d2017-10-04 15:27:45 -07005354 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005355 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305356
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305357 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005358
Dhananjay Kumarac341582017-02-23 23:42:25 +05305359 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305360 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305361 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5362 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005363 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305364 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305365 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305366 ALOGD(" %s: sound card is not active/SSR state", __func__);
5367 ret= -EIO;
5368 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305369 }
5370 }
5371
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305372 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305373 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305374 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305375 goto exit;
5376 }
5377
Haynes Mathew George16081042017-05-31 17:16:49 -07005378 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5379 ret = -EINVAL;
5380 goto exit;
5381 }
5382
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305383 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5384 !out->is_iec61937_info_available) {
5385
5386 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5387 out->is_iec61937_info_available = true;
5388 } else if (audio_extn_passthru_is_enabled()) {
5389 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305390 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305391
5392 if((out->format == AUDIO_FORMAT_DTS) ||
5393 (out->format == AUDIO_FORMAT_DTS_HD)) {
5394 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5395 buffer, bytes);
5396 if (ret) {
5397 if (ret != -ENOSYS) {
5398 out->is_iec61937_info_available = false;
5399 ALOGD("iec61937 transmission info not yet updated retry");
5400 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305401 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305402 /* if stream has started and after that there is
5403 * stream config change (iec transmission config)
5404 * then trigger select_device to update backend configuration.
5405 */
5406 out->stream_config_changed = true;
5407 pthread_mutex_lock(&adev->lock);
5408 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305409 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005410 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305411 ret = -EINVAL;
5412 goto exit;
5413 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305414 pthread_mutex_unlock(&adev->lock);
5415 out->stream_config_changed = false;
5416 out->is_iec61937_info_available = true;
5417 }
5418 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305419
Garmond Leung317cbf12017-09-13 16:20:50 -07005420 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305421 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5422 (out->is_iec61937_info_available == true)) {
5423 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5424 ret = -EINVAL;
5425 goto exit;
5426 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305427 }
5428 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305429
5430 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005431 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005432 if (!(out->devices &
5433 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305434 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305435 ret = -EIO;
5436 goto exit;
5437 }
5438 }
5439 }
5440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005442 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005443 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005444 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5445 ret = voice_extn_compress_voip_start_output_stream(out);
5446 else
5447 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005448 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005449 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005451 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005452 goto exit;
5453 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305454 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005455 if (last_known_cal_step != -1) {
5456 ALOGD("%s: retry previous failed cal level set", __func__);
5457 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305458 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005459 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305460
5461 if ((out->is_iec61937_info_available == true) &&
5462 (audio_extn_passthru_is_passthrough_stream(out))&&
5463 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5464 ret = -EINVAL;
5465 goto exit;
5466 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305467 if (out->set_dual_mono)
5468 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005470
Ashish Jain81eb2a82015-05-13 10:52:34 +05305471 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005472 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305473 adev->is_channel_status_set = true;
5474 }
5475
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305476 if ((adev->use_old_pspd_mix_ctrl == true) &&
5477 (out->pspd_coeff_sent == false)) {
5478 /*
5479 * Need to resend pspd coefficients after stream started for
5480 * older kernel version as it does not save the coefficients
5481 * and also stream has to be started for coeff to apply.
5482 */
5483 usecase = get_usecase_from_list(adev, out->usecase);
5484 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305485 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305486 out->pspd_coeff_sent = true;
5487 }
5488 }
5489
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005490 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005491 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005492 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005493 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005494 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5495 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305496 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5497 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005498 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305499 out->send_next_track_params = false;
5500 out->is_compr_metadata_avail = false;
5501 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005502 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305503 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305504 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005505
Ashish Jain83a6cc22016-06-28 14:34:17 +05305506 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305507 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305508 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305509 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005510 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305511 return -EINVAL;
5512 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305513 audio_format_t dst_format = out->hal_op_format;
5514 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305515
Dieter Luecking5d57def2018-09-07 14:23:37 +02005516 /* prevent division-by-zero */
5517 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5518 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5519 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5520 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305521 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005522 ATRACE_END();
5523 return -EINVAL;
5524 }
5525
Ashish Jainf1eaa582016-05-23 20:54:24 +05305526 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5527 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5528
Ashish Jain83a6cc22016-06-28 14:34:17 +05305529 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305530 dst_format,
5531 buffer,
5532 src_format,
5533 frames);
5534
Ashish Jain83a6cc22016-06-28 14:34:17 +05305535 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305536 bytes_to_write);
5537
5538 /*Convert written bytes in audio flinger format*/
5539 if (ret > 0)
5540 ret = ((ret * format_to_bitwidth_table[out->format]) /
5541 format_to_bitwidth_table[dst_format]);
5542 }
5543 } else
5544 ret = compress_write(out->compr, buffer, bytes);
5545
Zhou Songc9672822017-08-16 16:01:39 +08005546 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5547 update_frames_written(out, bytes);
5548
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305549 if (ret < 0)
5550 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005551 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305552 /*msg to cb thread only if non blocking write is enabled*/
5553 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305554 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005555 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305556 } else if (-ENETRESET == ret) {
5557 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305558 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305559 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305560 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005561 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305562 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005563 }
Ashish Jain5106d362016-05-11 19:23:33 +05305564
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305565 /* Call compr start only when non-zero bytes of data is there to be rendered */
5566 if (!out->playback_started && ret > 0) {
5567 int status = compress_start(out->compr);
5568 if (status < 0) {
5569 ret = status;
5570 ALOGE("%s: compr start failed with err %d", __func__, errno);
5571 goto exit;
5572 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005573 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005574 out->playback_started = 1;
5575 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005576
5577 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5578 popcount(out->channel_mask),
5579 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005580 }
5581 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005582 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005583 return ret;
5584 } else {
5585 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005586 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005587 if (out->muted)
5588 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005589 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5590 __func__, frames, frame_size, bytes_to_write);
5591
Aalique Grahame22e49102018-12-18 14:23:57 -08005592 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005593 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5594 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5595 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005596 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5597 int16_t *src = (int16_t *)buffer;
5598 int16_t *dst = (int16_t *)buffer;
5599
5600 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5601 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005602 "out_write called for %s use case with wrong properties",
5603 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005604
5605 /*
5606 * FIXME: this can be removed once audio flinger mixer supports
5607 * mono output
5608 */
5609
5610 /*
5611 * Code below goes over each frame in the buffer and adds both
5612 * L and R samples and then divides by 2 to convert to mono
5613 */
5614 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5615 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5616 }
5617 bytes_to_write /= 2;
5618 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005619
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305620 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005621
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005622 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005623
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005624 if (out->config.rate)
5625 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5626 out->config.rate;
5627
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005628 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005629 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5630
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005631 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005632 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005633 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305634 out->convert_buffer != NULL) {
5635
5636 memcpy_by_audio_format(out->convert_buffer,
5637 out->hal_op_format,
5638 buffer,
5639 out->hal_ip_format,
5640 out->config.period_size * out->config.channels);
5641
5642 ret = pcm_write(out->pcm, out->convert_buffer,
5643 (out->config.period_size *
5644 out->config.channels *
5645 format_to_bitwidth_table[out->hal_op_format]));
5646 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305647 /*
5648 * To avoid underrun in DSP when the application is not pumping
5649 * data at required rate, check for the no. of bytes and ignore
5650 * pcm_write if it is less than actual buffer size.
5651 * It is a work around to a change in compress VOIP driver.
5652 */
5653 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5654 bytes < (out->config.period_size * out->config.channels *
5655 audio_bytes_per_sample(out->format))) {
5656 size_t voip_buf_size =
5657 out->config.period_size * out->config.channels *
5658 audio_bytes_per_sample(out->format);
5659 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5660 __func__, bytes, voip_buf_size);
5661 usleep(((uint64_t)voip_buf_size - bytes) *
5662 1000000 / audio_stream_out_frame_size(stream) /
5663 out_get_sample_rate(&out->stream.common));
5664 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005665 } else {
5666 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5667 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5668 else
5669 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5670 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305671 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005672
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005673 release_out_focus(out);
5674
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305675 if (ret < 0)
5676 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005677 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305678 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005679 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005680 }
5681
5682exit:
Zhou Songc9672822017-08-16 16:01:39 +08005683 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305684 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305685 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 pthread_mutex_unlock(&out->lock);
5688
5689 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005690 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005691 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305692 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305693 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305694 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305695 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305696 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305697 out->standby = true;
5698 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305699 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005700 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5701 /* prevent division-by-zero */
5702 uint32_t stream_size = audio_stream_out_frame_size(stream);
5703 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005704
Dieter Luecking5d57def2018-09-07 14:23:37 +02005705 if ((stream_size == 0) || (srate == 0)) {
5706 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5707 ATRACE_END();
5708 return -EINVAL;
5709 }
5710 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5711 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005712 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305713 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005714 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005715 return ret;
5716 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005717 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005718 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005719 return bytes;
5720}
5721
5722static int out_get_render_position(const struct audio_stream_out *stream,
5723 uint32_t *dsp_frames)
5724{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005725 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005726
5727 if (dsp_frames == NULL)
5728 return -EINVAL;
5729
5730 *dsp_frames = 0;
5731 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005732 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305733
5734 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5735 * this operation and adev_close_output_stream(where out gets reset).
5736 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305737 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005738 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305739 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005740 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305741 return 0;
5742 }
5743
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005744 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305745 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305746 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005747 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305748 if (ret < 0)
5749 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005750 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305751 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005752 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305753 if (-ENETRESET == ret) {
5754 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305755 out->card_status = CARD_STATUS_OFFLINE;
5756 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305757 } else if(ret < 0) {
5758 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305759 ret = -EINVAL;
5760 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305761 /*
5762 * Handle corner case where compress session is closed during SSR
5763 * and timestamp is queried
5764 */
5765 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305766 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305767 } else if (out->prev_card_status_offline) {
5768 ALOGE("ERROR: previously sound card was offline,return error");
5769 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305770 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305771 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005772 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305773 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305774 pthread_mutex_unlock(&out->lock);
5775 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005776 } else if (audio_is_linear_pcm(out->format)) {
5777 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005778 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005779 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005780 } else
5781 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782}
5783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005784static int out_add_audio_effect(const struct audio_stream *stream __unused,
5785 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005786{
5787 return 0;
5788}
5789
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005790static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5791 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005792{
5793 return 0;
5794}
5795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005796static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5797 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005798{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305799 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005800}
5801
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005802static int out_get_presentation_position(const struct audio_stream_out *stream,
5803 uint64_t *frames, struct timespec *timestamp)
5804{
5805 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305806 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005807 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005808
Ashish Jain5106d362016-05-11 19:23:33 +05305809 /* below piece of code is not guarded against any lock because audioFliner serializes
5810 * this operation and adev_close_output_stream( where out gets reset).
5811 */
5812 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305813 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005814 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305815 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5816 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5817 return 0;
5818 }
5819
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005820 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005821
Ashish Jain5106d362016-05-11 19:23:33 +05305822 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5823 ret = compress_get_tstamp(out->compr, &dsp_frames,
5824 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005825 // Adjustment accounts for A2dp encoder latency with offload usecases
5826 // Note: Encoder latency is returned in ms.
5827 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5828 unsigned long offset =
5829 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5830 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5831 }
Ashish Jain5106d362016-05-11 19:23:33 +05305832 ALOGVV("%s rendered frames %ld sample_rate %d",
5833 __func__, dsp_frames, out->sample_rate);
5834 *frames = dsp_frames;
5835 if (ret < 0)
5836 ret = -errno;
5837 if (-ENETRESET == ret) {
5838 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305839 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305840 ret = -EINVAL;
5841 } else
5842 ret = 0;
5843 /* this is the best we can do */
5844 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005845 } else {
5846 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005847 unsigned int avail;
5848 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5849 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5850 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5851 // This adjustment accounts for buffering after app processor.
5852 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005853 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005854 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005855
Weiyin Jiangd4633762018-03-16 12:05:03 +08005856 // Adjustment accounts for A2dp encoder latency with non offload usecases
5857 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5858 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5859 signed_frames -=
5860 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5861 }
5862
5863 // It would be unusual for this value to be negative, but check just in case ...
5864 if (signed_frames >= 0) {
5865 *frames = signed_frames;
5866 ret = 0;
5867 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005868 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305869 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305870 *frames = out->written;
5871 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305872 if (is_offload_usecase(out->usecase))
5873 ret = -EINVAL;
5874 else
5875 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005876 }
5877 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005878 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005879 return ret;
5880}
5881
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005882static int out_set_callback(struct audio_stream_out *stream,
5883 stream_callback_t callback, void *cookie)
5884{
5885 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005886 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005887
5888 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005889 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005890 out->client_callback = callback;
5891 out->client_cookie = cookie;
5892 if (out->adsp_hdlr_stream_handle) {
5893 ret = audio_extn_adsp_hdlr_stream_set_callback(
5894 out->adsp_hdlr_stream_handle,
5895 callback,
5896 cookie);
5897 if (ret)
5898 ALOGW("%s:adsp hdlr callback registration failed %d",
5899 __func__, ret);
5900 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005901 pthread_mutex_unlock(&out->lock);
5902 return 0;
5903}
5904
5905static int out_pause(struct audio_stream_out* stream)
5906{
5907 struct stream_out *out = (struct stream_out *)stream;
5908 int status = -ENOSYS;
5909 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005910 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005911 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005912 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005913 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305914 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305915 status = compress_pause(out->compr);
5916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005917 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005918
Mingming Yin21854652016-04-13 11:54:02 -07005919 if (audio_extn_passthru_is_active()) {
5920 ALOGV("offload use case, pause passthru");
5921 audio_extn_passthru_on_pause(out);
5922 }
5923
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305924 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005925 audio_extn_dts_notify_playback_state(out->usecase, 0,
5926 out->sample_rate, popcount(out->channel_mask),
5927 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005928 }
5929 pthread_mutex_unlock(&out->lock);
5930 }
5931 return status;
5932}
5933
5934static int out_resume(struct audio_stream_out* stream)
5935{
5936 struct stream_out *out = (struct stream_out *)stream;
5937 int status = -ENOSYS;
5938 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005939 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005940 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005941 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005942 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005943 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305944 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305945 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005946 }
5947 if (!status) {
5948 out->offload_state = OFFLOAD_STATE_PLAYING;
5949 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305950 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005951 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5952 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005953 }
5954 pthread_mutex_unlock(&out->lock);
5955 }
5956 return status;
5957}
5958
5959static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5960{
5961 struct stream_out *out = (struct stream_out *)stream;
5962 int status = -ENOSYS;
5963 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005964 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005965 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005966 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5967 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5968 else
5969 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5970 pthread_mutex_unlock(&out->lock);
5971 }
5972 return status;
5973}
5974
5975static int out_flush(struct audio_stream_out* stream)
5976{
5977 struct stream_out *out = (struct stream_out *)stream;
5978 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005979 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005980 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005981 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005982 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5983 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005984 } else {
5985 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5986 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005987 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005988 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005989 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005990 return 0;
5991 }
5992 return -ENOSYS;
5993}
5994
Haynes Mathew George16081042017-05-31 17:16:49 -07005995static int out_stop(const struct audio_stream_out* stream)
5996{
5997 struct stream_out *out = (struct stream_out *)stream;
5998 struct audio_device *adev = out->dev;
5999 int ret = -ENOSYS;
6000
6001 ALOGV("%s", __func__);
6002 pthread_mutex_lock(&adev->lock);
6003 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6004 out->playback_started && out->pcm != NULL) {
6005 pcm_stop(out->pcm);
6006 ret = stop_output_stream(out);
6007 out->playback_started = false;
6008 }
6009 pthread_mutex_unlock(&adev->lock);
6010 return ret;
6011}
6012
6013static int out_start(const struct audio_stream_out* stream)
6014{
6015 struct stream_out *out = (struct stream_out *)stream;
6016 struct audio_device *adev = out->dev;
6017 int ret = -ENOSYS;
6018
6019 ALOGV("%s", __func__);
6020 pthread_mutex_lock(&adev->lock);
6021 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6022 !out->playback_started && out->pcm != NULL) {
6023 ret = start_output_stream(out);
6024 if (ret == 0) {
6025 out->playback_started = true;
6026 }
6027 }
6028 pthread_mutex_unlock(&adev->lock);
6029 return ret;
6030}
6031
6032/*
6033 * Modify config->period_count based on min_size_frames
6034 */
6035static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6036{
6037 int periodCountRequested = (min_size_frames + config->period_size - 1)
6038 / config->period_size;
6039 int periodCount = MMAP_PERIOD_COUNT_MIN;
6040
6041 ALOGV("%s original config.period_size = %d config.period_count = %d",
6042 __func__, config->period_size, config->period_count);
6043
6044 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6045 periodCount *= 2;
6046 }
6047 config->period_count = periodCount;
6048
6049 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6050}
6051
Phil Burkfe17efd2019-03-25 10:23:35 -07006052// Read offset for the positional timestamp from a persistent vendor property.
6053// This is to workaround apparent inaccuracies in the timing information that
6054// is used by the AAudio timing model. The inaccuracies can cause glitches.
6055static int64_t get_mmap_out_time_offset() {
6056 const int32_t kDefaultOffsetMicros = 0;
6057 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006058 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006059 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6060 return mmap_time_offset_micros * (int64_t)1000;
6061}
6062
Haynes Mathew George16081042017-05-31 17:16:49 -07006063static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6064 int32_t min_size_frames,
6065 struct audio_mmap_buffer_info *info)
6066{
6067 struct stream_out *out = (struct stream_out *)stream;
6068 struct audio_device *adev = out->dev;
6069 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006070 unsigned int offset1 = 0;
6071 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006072 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006073 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006074 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006075
Arun Mirpuri5d170872019-03-26 13:21:31 -07006076 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306077 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006078 pthread_mutex_lock(&adev->lock);
6079
Sharad Sanglec6f32552018-05-04 16:15:38 +05306080 if (CARD_STATUS_OFFLINE == out->card_status ||
6081 CARD_STATUS_OFFLINE == adev->card_status) {
6082 ALOGW("out->card_status or adev->card_status offline, try again");
6083 ret = -EIO;
6084 goto exit;
6085 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006086 if (info == NULL || min_size_frames == 0) {
6087 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6088 ret = -EINVAL;
6089 goto exit;
6090 }
6091 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6092 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6093 ret = -ENOSYS;
6094 goto exit;
6095 }
6096 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6097 if (out->pcm_device_id < 0) {
6098 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6099 __func__, out->pcm_device_id, out->usecase);
6100 ret = -EINVAL;
6101 goto exit;
6102 }
6103
6104 adjust_mmap_period_count(&out->config, min_size_frames);
6105
Arun Mirpuri5d170872019-03-26 13:21:31 -07006106 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006107 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6108 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6109 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306110 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306111 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6112 out->card_status = CARD_STATUS_OFFLINE;
6113 adev->card_status = CARD_STATUS_OFFLINE;
6114 ret = -EIO;
6115 goto exit;
6116 }
6117
Haynes Mathew George16081042017-05-31 17:16:49 -07006118 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6119 step = "open";
6120 ret = -ENODEV;
6121 goto exit;
6122 }
6123 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6124 if (ret < 0) {
6125 step = "begin";
6126 goto exit;
6127 }
6128 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006129 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006130 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006131 ret = platform_get_mmap_data_fd(adev->platform,
6132 out->pcm_device_id, 0 /*playback*/,
6133 &info->shared_memory_fd,
6134 &mmap_size);
6135 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006136 // Fall back to non exclusive mode
6137 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6138 } else {
6139 if (mmap_size < buffer_size) {
6140 step = "mmap";
6141 goto exit;
6142 }
6143 // FIXME: indicate exclusive mode support by returning a negative buffer size
6144 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006145 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006146 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006147 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006148
6149 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6150 if (ret < 0) {
6151 step = "commit";
6152 goto exit;
6153 }
6154
Phil Burkfe17efd2019-03-25 10:23:35 -07006155 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6156
Haynes Mathew George16081042017-05-31 17:16:49 -07006157 out->standby = false;
6158 ret = 0;
6159
Arun Mirpuri5d170872019-03-26 13:21:31 -07006160 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006161 __func__, info->shared_memory_address, info->buffer_size_frames);
6162
6163exit:
6164 if (ret != 0) {
6165 if (out->pcm == NULL) {
6166 ALOGE("%s: %s - %d", __func__, step, ret);
6167 } else {
6168 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6169 pcm_close(out->pcm);
6170 out->pcm = NULL;
6171 }
6172 }
6173 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306174 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006175 return ret;
6176}
6177
6178static int out_get_mmap_position(const struct audio_stream_out *stream,
6179 struct audio_mmap_position *position)
6180{
6181 struct stream_out *out = (struct stream_out *)stream;
6182 ALOGVV("%s", __func__);
6183 if (position == NULL) {
6184 return -EINVAL;
6185 }
6186 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006187 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006188 return -ENOSYS;
6189 }
6190 if (out->pcm == NULL) {
6191 return -ENOSYS;
6192 }
6193
6194 struct timespec ts = { 0, 0 };
6195 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6196 if (ret < 0) {
6197 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6198 return ret;
6199 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006200 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6201 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006202 return 0;
6203}
6204
6205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006206/** audio_stream_in implementation **/
6207static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6208{
6209 struct stream_in *in = (struct stream_in *)stream;
6210
6211 return in->config.rate;
6212}
6213
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006214static int in_set_sample_rate(struct audio_stream *stream __unused,
6215 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216{
6217 return -ENOSYS;
6218}
6219
6220static size_t in_get_buffer_size(const struct audio_stream *stream)
6221{
6222 struct stream_in *in = (struct stream_in *)stream;
6223
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006224 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6225 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006226 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6227 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306228 else if(audio_extn_cin_attached_usecase(in->usecase))
6229 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006230
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006231 return in->config.period_size * in->af_period_multiplier *
6232 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006233}
6234
6235static uint32_t in_get_channels(const struct audio_stream *stream)
6236{
6237 struct stream_in *in = (struct stream_in *)stream;
6238
6239 return in->channel_mask;
6240}
6241
6242static audio_format_t in_get_format(const struct audio_stream *stream)
6243{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006244 struct stream_in *in = (struct stream_in *)stream;
6245
6246 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006247}
6248
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006249static int in_set_format(struct audio_stream *stream __unused,
6250 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251{
6252 return -ENOSYS;
6253}
6254
6255static int in_standby(struct audio_stream *stream)
6256{
6257 struct stream_in *in = (struct stream_in *)stream;
6258 struct audio_device *adev = in->dev;
6259 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306260 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6261 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006262 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306263
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006264 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006265 if (!in->standby && in->is_st_session) {
6266 ALOGD("%s: sound trigger pcm stop lab", __func__);
6267 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006268 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006269 in->standby = 1;
6270 }
6271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006272 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006273 if (adev->adm_deregister_stream)
6274 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6275
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006276 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006277 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006278 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006279 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006280 voice_extn_compress_voip_close_input_stream(stream);
6281 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006282 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6283 do_stop = in->capture_started;
6284 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006285 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306286 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306287 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006288 }
6289
Arun Mirpuri5d170872019-03-26 13:21:31 -07006290 if (in->pcm) {
6291 ATRACE_BEGIN("pcm_in_close");
6292 pcm_close(in->pcm);
6293 ATRACE_END();
6294 in->pcm = NULL;
6295 }
6296
Carter Hsu2e429db2019-05-14 18:50:52 +08006297 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006298 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006299
6300 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006301 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006302
6303 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6304 adev->num_va_sessions--;
6305
Eric Laurent150dbfe2013-02-27 14:31:02 -08006306 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006307 }
6308 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006309 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006310 return status;
6311}
6312
Aalique Grahame22e49102018-12-18 14:23:57 -08006313static int in_dump(const struct audio_stream *stream,
6314 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006315{
Aalique Grahame22e49102018-12-18 14:23:57 -08006316 struct stream_in *in = (struct stream_in *)stream;
6317
6318 // We try to get the lock for consistency,
6319 // but it isn't necessary for these variables.
6320 // If we're not in standby, we may be blocked on a read.
6321 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6322 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6323 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6324 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6325
6326 if (locked) {
6327 pthread_mutex_unlock(&in->lock);
6328 }
6329
6330 // dump error info
6331 (void)error_log_dump(
6332 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006334 return 0;
6335}
6336
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306337static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6338{
6339 if (!stream || !parms)
6340 return;
6341
6342 struct stream_in *in = (struct stream_in *)stream;
6343 struct audio_device *adev = in->dev;
6344
6345 card_status_t status;
6346 int card;
6347 if (parse_snd_card_status(parms, &card, &status) < 0)
6348 return;
6349
6350 pthread_mutex_lock(&adev->lock);
6351 bool valid_cb = (card == adev->snd_card);
6352 pthread_mutex_unlock(&adev->lock);
6353
6354 if (!valid_cb)
6355 return;
6356
6357 lock_input_stream(in);
6358 if (in->card_status != status)
6359 in->card_status = status;
6360 pthread_mutex_unlock(&in->lock);
6361
6362 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6363 use_case_table[in->usecase],
6364 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6365
6366 // a better solution would be to report error back to AF and let
6367 // it put the stream to standby
6368 if (status == CARD_STATUS_OFFLINE)
6369 in_standby(&in->stream.common);
6370
6371 return;
6372}
6373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006374static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6375{
6376 struct stream_in *in = (struct stream_in *)stream;
6377 struct audio_device *adev = in->dev;
6378 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006379 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006380 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006381
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306382 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006383 parms = str_parms_create_str(kvpairs);
6384
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306385 if (!parms)
6386 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006387 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006388 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006389
6390 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6391 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392 val = atoi(value);
6393 /* no audio source uses val == 0 */
6394 if ((in->source != val) && (val != 0)) {
6395 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006396 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6397 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6398 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006399 (in->config.rate == 8000 || in->config.rate == 16000 ||
6400 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006401 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006402 err = voice_extn_compress_voip_open_input_stream(in);
6403 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006404 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006405 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006406 }
6407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408 }
6409 }
6410
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006411 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6412 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006413 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006414 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6415
6416 // Workaround: If routing to an non existing usb device, fail gracefully
6417 // The routing request will otherwise block during 10 second
6418 int card;
6419 if (audio_is_usb_in_device(val) &&
6420 (card = get_alive_usb_card(parms)) >= 0) {
6421
6422 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6423 ret = -ENOSYS;
6424 } else {
6425
6426 in->device = val;
6427 /* If recording is in progress, change the tx device to new device */
6428 if (!in->standby && !in->is_st_session) {
6429 ALOGV("update input routing change");
6430 // inform adm before actual routing to prevent glitches.
6431 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006432 adev->adm_on_routing_change(adev->adm_data,
6433 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006434 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006435 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6436 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006437 }
6438 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006439 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006440 }
6441 }
6442
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306443 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6444 if (err >= 0) {
6445 strlcpy(in->profile, value, sizeof(in->profile));
6446 ALOGV("updating stream profile with value '%s'", in->profile);
6447 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6448 &adev->streams_input_cfg_list,
6449 in->device, in->flags, in->format,
6450 in->sample_rate, in->bit_width,
6451 in->profile, &in->app_type_cfg);
6452 }
6453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006454 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006455 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006456
6457 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306458error:
Eric Laurent994a6932013-07-17 11:51:42 -07006459 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006460 return ret;
6461}
6462
6463static char* in_get_parameters(const struct audio_stream *stream,
6464 const char *keys)
6465{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006466 struct stream_in *in = (struct stream_in *)stream;
6467 struct str_parms *query = str_parms_create_str(keys);
6468 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006469 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006470
6471 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006472 if (reply) {
6473 str_parms_destroy(reply);
6474 }
6475 if (query) {
6476 str_parms_destroy(query);
6477 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006478 ALOGE("in_get_parameters: failed to create query or reply");
6479 return NULL;
6480 }
6481
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006482 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006483
6484 voice_extn_in_get_parameters(in, query, reply);
6485
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006486 stream_get_parameter_channels(query, reply,
6487 &in->supported_channel_masks[0]);
6488 stream_get_parameter_formats(query, reply,
6489 &in->supported_formats[0]);
6490 stream_get_parameter_rates(query, reply,
6491 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006492 str = str_parms_to_str(reply);
6493 str_parms_destroy(query);
6494 str_parms_destroy(reply);
6495
6496 ALOGV("%s: exit: returns - %s", __func__, str);
6497 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006498}
6499
Aalique Grahame22e49102018-12-18 14:23:57 -08006500static int in_set_gain(struct audio_stream_in *stream,
6501 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006502{
Aalique Grahame22e49102018-12-18 14:23:57 -08006503 struct stream_in *in = (struct stream_in *)stream;
6504 char mixer_ctl_name[128];
6505 struct mixer_ctl *ctl;
6506 int ctl_value;
6507
6508 ALOGV("%s: gain %f", __func__, gain);
6509
6510 if (stream == NULL)
6511 return -EINVAL;
6512
6513 /* in_set_gain() only used to silence MMAP capture for now */
6514 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6515 return -ENOSYS;
6516
6517 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6518
6519 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6520 if (!ctl) {
6521 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6522 __func__, mixer_ctl_name);
6523 return -ENOSYS;
6524 }
6525
6526 if (gain < RECORD_GAIN_MIN)
6527 gain = RECORD_GAIN_MIN;
6528 else if (gain > RECORD_GAIN_MAX)
6529 gain = RECORD_GAIN_MAX;
6530 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6531
6532 mixer_ctl_set_value(ctl, 0, ctl_value);
6533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006534 return 0;
6535}
6536
6537static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6538 size_t bytes)
6539{
6540 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306541
6542 if (in == NULL) {
6543 ALOGE("%s: stream_in ptr is NULL", __func__);
6544 return -EINVAL;
6545 }
6546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006547 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306548 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306549 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006550
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006551 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306552
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006553 if (in->is_st_session) {
6554 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6555 /* Read from sound trigger HAL */
6556 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006557 if (in->standby) {
6558 adev->num_va_sessions++;
6559 in->standby = 0;
6560 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006561 pthread_mutex_unlock(&in->lock);
6562 return bytes;
6563 }
6564
Haynes Mathew George16081042017-05-31 17:16:49 -07006565 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6566 ret = -ENOSYS;
6567 goto exit;
6568 }
6569
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006570 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6571 !in->standby && adev->adm_routing_changed) {
6572 ret = -ENOSYS;
6573 goto exit;
6574 }
6575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006576 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006577 pthread_mutex_lock(&adev->lock);
6578 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6579 ret = voice_extn_compress_voip_start_input_stream(in);
6580 else
6581 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006582 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6583 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006584 pthread_mutex_unlock(&adev->lock);
6585 if (ret != 0) {
6586 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006587 }
6588 in->standby = 0;
6589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006590
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306591 /* Avoid read if capture_stopped is set */
6592 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6593 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6594 ret = -EINVAL;
6595 goto exit;
6596 }
6597
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006598 // what's the duration requested by the client?
6599 long ns = 0;
6600
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306601 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006602 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6603 in->config.rate;
6604
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006605 ret = request_in_focus(in, ns);
6606 if (ret != 0)
6607 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006608 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006609
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306610 if (audio_extn_cin_attached_usecase(in->usecase)) {
6611 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6612 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306613 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006614 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306615 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006616 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006617 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006618 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006619 } else if (audio_extn_ffv_get_stream() == in) {
6620 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306621 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006622 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306623 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6624 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6625 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6626 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306627 ret = -EINVAL;
6628 goto exit;
6629 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306630 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306631 ret = -errno;
6632 }
6633 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306634 /* bytes read is always set to bytes for non compress usecases */
6635 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006636 }
6637
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006638 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006640 /*
Quinn Malef6050362019-01-30 15:55:40 -08006641 * Instead of writing zeroes here, we could trust the hardware to always
6642 * provide zeroes when muted. This is also muted with voice recognition
6643 * usecases so that other clients do not have access to voice recognition
6644 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006645 */
Quinn Malef6050362019-01-30 15:55:40 -08006646 if ((ret == 0 && voice_get_mic_mute(adev) &&
6647 !voice_is_in_call_rec_stream(in) &&
6648 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6649 (adev->num_va_sessions &&
6650 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6651 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6652 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006653 memset(buffer, 0, bytes);
6654
6655exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306656 frame_size = audio_stream_in_frame_size(stream);
6657 if (frame_size > 0)
6658 in->frames_read += bytes_read/frame_size;
6659
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006660 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306661 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006662 pthread_mutex_unlock(&in->lock);
6663
6664 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306665 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306666 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306667 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306668 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306669 in->standby = true;
6670 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306671 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6672 bytes_read = bytes;
6673 memset(buffer, 0, bytes);
6674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006675 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006676 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6677 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006678 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306679 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306680 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006681 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306682 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006683}
6684
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006685static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006686{
6687 return 0;
6688}
6689
Aalique Grahame22e49102018-12-18 14:23:57 -08006690static int in_get_capture_position(const struct audio_stream_in *stream,
6691 int64_t *frames, int64_t *time)
6692{
6693 if (stream == NULL || frames == NULL || time == NULL) {
6694 return -EINVAL;
6695 }
6696 struct stream_in *in = (struct stream_in *)stream;
6697 int ret = -ENOSYS;
6698
6699 lock_input_stream(in);
6700 // note: ST sessions do not close the alsa pcm driver synchronously
6701 // on standby. Therefore, we may return an error even though the
6702 // pcm stream is still opened.
6703 if (in->standby) {
6704 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6705 "%s stream in standby but pcm not NULL for non ST session", __func__);
6706 goto exit;
6707 }
6708 if (in->pcm) {
6709 struct timespec timestamp;
6710 unsigned int avail;
6711 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6712 *frames = in->frames_read + avail;
6713 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6714 ret = 0;
6715 }
6716 }
6717exit:
6718 pthread_mutex_unlock(&in->lock);
6719 return ret;
6720}
6721
Carter Hsu2e429db2019-05-14 18:50:52 +08006722static int in_update_effect_list(bool add, effect_handle_t effect,
6723 struct listnode *head)
6724{
6725 struct listnode *node;
6726 struct in_effect_list *elist = NULL;
6727 struct in_effect_list *target = NULL;
6728 int ret = 0;
6729
6730 if (!head)
6731 return ret;
6732
6733 list_for_each(node, head) {
6734 elist = node_to_item(node, struct in_effect_list, list);
6735 if (elist->handle == effect) {
6736 target = elist;
6737 break;
6738 }
6739 }
6740
6741 if (add) {
6742 if (target) {
6743 ALOGD("effect %p already exist", effect);
6744 return ret;
6745 }
6746
6747 target = (struct in_effect_list *)
6748 calloc(1, sizeof(struct in_effect_list));
6749
6750 if (!target) {
6751 ALOGE("%s:fail to allocate memory", __func__);
6752 return -ENOMEM;
6753 }
6754
6755 target->handle = effect;
6756 list_add_tail(head, &target->list);
6757 } else {
6758 if (target) {
6759 list_remove(&target->list);
6760 free(target);
6761 }
6762 }
6763
6764 return ret;
6765}
6766
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006767static int add_remove_audio_effect(const struct audio_stream *stream,
6768 effect_handle_t effect,
6769 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006771 struct stream_in *in = (struct stream_in *)stream;
6772 int status = 0;
6773 effect_descriptor_t desc;
6774
6775 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006776 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6777
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006778 if (status != 0)
6779 return status;
6780
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006781 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006782 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006783 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006784 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6785 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006786 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006787
6788 in_update_effect_list(enable, effect, &in->aec_list);
6789 enable = !list_empty(&in->aec_list);
6790 if (enable == in->enable_aec)
6791 goto exit;
6792
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006793 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006794 ALOGD("AEC enable %d", enable);
6795
Aalique Grahame22e49102018-12-18 14:23:57 -08006796 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6797 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6798 in->dev->enable_voicerx = enable;
6799 struct audio_usecase *usecase;
6800 struct listnode *node;
6801 list_for_each(node, &in->dev->usecase_list) {
6802 usecase = node_to_item(node, struct audio_usecase, list);
6803 if (usecase->type == PCM_PLAYBACK)
6804 select_devices(in->dev, usecase->id);
6805 }
6806 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006807 if (!in->standby) {
6808 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6809 select_devices(in->dev, in->usecase);
6810 }
6811
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006812 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006813 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6814
6815 in_update_effect_list(enable, effect, &in->ns_list);
6816 enable = !list_empty(&in->ns_list);
6817 if (enable == in->enable_ns)
6818 goto exit;
6819
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006820 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006821 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006822 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006823 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6824 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006825 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6826 select_devices(in->dev, in->usecase);
6827 } else
6828 select_devices(in->dev, in->usecase);
6829 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006830 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006831exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006832 pthread_mutex_unlock(&in->dev->lock);
6833 pthread_mutex_unlock(&in->lock);
6834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835 return 0;
6836}
6837
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006838static int in_add_audio_effect(const struct audio_stream *stream,
6839 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840{
Eric Laurent994a6932013-07-17 11:51:42 -07006841 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006842 return add_remove_audio_effect(stream, effect, true);
6843}
6844
6845static int in_remove_audio_effect(const struct audio_stream *stream,
6846 effect_handle_t effect)
6847{
Eric Laurent994a6932013-07-17 11:51:42 -07006848 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006849 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006850}
6851
Derek Chenf939fb72018-11-13 13:34:41 -08006852streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6853 audio_io_handle_t input)
6854{
6855 struct listnode *node;
6856
6857 list_for_each(node, &dev->active_inputs_list) {
6858 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6859 streams_input_ctxt_t,
6860 list);
6861 if (in_ctxt->input->capture_handle == input) {
6862 return in_ctxt;
6863 }
6864 }
6865 return NULL;
6866}
6867
6868streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6869 audio_io_handle_t output)
6870{
6871 struct listnode *node;
6872
6873 list_for_each(node, &dev->active_outputs_list) {
6874 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6875 streams_output_ctxt_t,
6876 list);
6877 if (out_ctxt->output->handle == output) {
6878 return out_ctxt;
6879 }
6880 }
6881 return NULL;
6882}
6883
Haynes Mathew George16081042017-05-31 17:16:49 -07006884static int in_stop(const struct audio_stream_in* stream)
6885{
6886 struct stream_in *in = (struct stream_in *)stream;
6887 struct audio_device *adev = in->dev;
6888
6889 int ret = -ENOSYS;
6890 ALOGV("%s", __func__);
6891 pthread_mutex_lock(&adev->lock);
6892 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6893 in->capture_started && in->pcm != NULL) {
6894 pcm_stop(in->pcm);
6895 ret = stop_input_stream(in);
6896 in->capture_started = false;
6897 }
6898 pthread_mutex_unlock(&adev->lock);
6899 return ret;
6900}
6901
6902static int in_start(const struct audio_stream_in* stream)
6903{
6904 struct stream_in *in = (struct stream_in *)stream;
6905 struct audio_device *adev = in->dev;
6906 int ret = -ENOSYS;
6907
6908 ALOGV("%s in %p", __func__, in);
6909 pthread_mutex_lock(&adev->lock);
6910 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6911 !in->capture_started && in->pcm != NULL) {
6912 if (!in->capture_started) {
6913 ret = start_input_stream(in);
6914 if (ret == 0) {
6915 in->capture_started = true;
6916 }
6917 }
6918 }
6919 pthread_mutex_unlock(&adev->lock);
6920 return ret;
6921}
6922
Phil Burke0a86d12019-02-16 22:28:11 -08006923// Read offset for the positional timestamp from a persistent vendor property.
6924// This is to workaround apparent inaccuracies in the timing information that
6925// is used by the AAudio timing model. The inaccuracies can cause glitches.
6926static int64_t in_get_mmap_time_offset() {
6927 const int32_t kDefaultOffsetMicros = 0;
6928 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006929 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006930 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6931 return mmap_time_offset_micros * (int64_t)1000;
6932}
6933
Haynes Mathew George16081042017-05-31 17:16:49 -07006934static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6935 int32_t min_size_frames,
6936 struct audio_mmap_buffer_info *info)
6937{
6938 struct stream_in *in = (struct stream_in *)stream;
6939 struct audio_device *adev = in->dev;
6940 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006941 unsigned int offset1 = 0;
6942 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006943 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006944 uint32_t mmap_size = 0;
6945 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006946
6947 pthread_mutex_lock(&adev->lock);
6948 ALOGV("%s in %p", __func__, in);
6949
Sharad Sanglec6f32552018-05-04 16:15:38 +05306950 if (CARD_STATUS_OFFLINE == in->card_status||
6951 CARD_STATUS_OFFLINE == adev->card_status) {
6952 ALOGW("in->card_status or adev->card_status offline, try again");
6953 ret = -EIO;
6954 goto exit;
6955 }
6956
Haynes Mathew George16081042017-05-31 17:16:49 -07006957 if (info == NULL || min_size_frames == 0) {
6958 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6959 ret = -EINVAL;
6960 goto exit;
6961 }
6962 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6963 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6964 ALOGV("%s in %p", __func__, in);
6965 ret = -ENOSYS;
6966 goto exit;
6967 }
6968 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6969 if (in->pcm_device_id < 0) {
6970 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6971 __func__, in->pcm_device_id, in->usecase);
6972 ret = -EINVAL;
6973 goto exit;
6974 }
6975
6976 adjust_mmap_period_count(&in->config, min_size_frames);
6977
6978 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6979 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6980 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6981 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306982 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306983 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6984 in->card_status = CARD_STATUS_OFFLINE;
6985 adev->card_status = CARD_STATUS_OFFLINE;
6986 ret = -EIO;
6987 goto exit;
6988 }
6989
Haynes Mathew George16081042017-05-31 17:16:49 -07006990 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6991 step = "open";
6992 ret = -ENODEV;
6993 goto exit;
6994 }
6995
6996 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6997 if (ret < 0) {
6998 step = "begin";
6999 goto exit;
7000 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007001
Arun Mirpuri5d170872019-03-26 13:21:31 -07007002 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7003 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7004 info->burst_size_frames = in->config.period_size;
7005 ret = platform_get_mmap_data_fd(adev->platform,
7006 in->pcm_device_id, 1 /*capture*/,
7007 &info->shared_memory_fd,
7008 &mmap_size);
7009 if (ret < 0) {
7010 // Fall back to non exclusive mode
7011 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7012 } else {
7013 if (mmap_size < buffer_size) {
7014 step = "mmap";
7015 goto exit;
7016 }
7017 // FIXME: indicate exclusive mode support by returning a negative buffer size
7018 info->buffer_size_frames *= -1;
7019 }
7020
7021 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007022
7023 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7024 if (ret < 0) {
7025 step = "commit";
7026 goto exit;
7027 }
7028
Phil Burke0a86d12019-02-16 22:28:11 -08007029 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7030
Haynes Mathew George16081042017-05-31 17:16:49 -07007031 in->standby = false;
7032 ret = 0;
7033
7034 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7035 __func__, info->shared_memory_address, info->buffer_size_frames);
7036
7037exit:
7038 if (ret != 0) {
7039 if (in->pcm == NULL) {
7040 ALOGE("%s: %s - %d", __func__, step, ret);
7041 } else {
7042 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7043 pcm_close(in->pcm);
7044 in->pcm = NULL;
7045 }
7046 }
7047 pthread_mutex_unlock(&adev->lock);
7048 return ret;
7049}
7050
7051static int in_get_mmap_position(const struct audio_stream_in *stream,
7052 struct audio_mmap_position *position)
7053{
7054 struct stream_in *in = (struct stream_in *)stream;
7055 ALOGVV("%s", __func__);
7056 if (position == NULL) {
7057 return -EINVAL;
7058 }
7059 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7060 return -ENOSYS;
7061 }
7062 if (in->pcm == NULL) {
7063 return -ENOSYS;
7064 }
7065 struct timespec ts = { 0, 0 };
7066 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7067 if (ret < 0) {
7068 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7069 return ret;
7070 }
Phil Burke0a86d12019-02-16 22:28:11 -08007071 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7072 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007073 return 0;
7074}
7075
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307076static int in_get_active_microphones(const struct audio_stream_in *stream,
7077 struct audio_microphone_characteristic_t *mic_array,
7078 size_t *mic_count) {
7079 struct stream_in *in = (struct stream_in *)stream;
7080 struct audio_device *adev = in->dev;
7081 ALOGVV("%s", __func__);
7082
7083 lock_input_stream(in);
7084 pthread_mutex_lock(&adev->lock);
7085 int ret = platform_get_active_microphones(adev->platform,
7086 audio_channel_count_from_in_mask(in->channel_mask),
7087 in->usecase, mic_array, mic_count);
7088 pthread_mutex_unlock(&adev->lock);
7089 pthread_mutex_unlock(&in->lock);
7090
7091 return ret;
7092}
7093
7094static int adev_get_microphones(const struct audio_hw_device *dev,
7095 struct audio_microphone_characteristic_t *mic_array,
7096 size_t *mic_count) {
7097 struct audio_device *adev = (struct audio_device *)dev;
7098 ALOGVV("%s", __func__);
7099
7100 pthread_mutex_lock(&adev->lock);
7101 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7102 pthread_mutex_unlock(&adev->lock);
7103
7104 return ret;
7105}
juyuchendb308c22019-01-21 11:57:17 -07007106
7107static void in_update_sink_metadata(struct audio_stream_in *stream,
7108 const struct sink_metadata *sink_metadata) {
7109
7110 if (stream == NULL
7111 || sink_metadata == NULL
7112 || sink_metadata->tracks == NULL) {
7113 return;
7114 }
7115
7116 int error = 0;
7117 struct stream_in *in = (struct stream_in *)stream;
7118 struct audio_device *adev = in->dev;
7119 audio_devices_t device = AUDIO_DEVICE_NONE;
7120
7121 if (sink_metadata->track_count != 0)
7122 device = sink_metadata->tracks->dest_device;
7123
7124 lock_input_stream(in);
7125 pthread_mutex_lock(&adev->lock);
7126 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7127
7128 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7129 && device != AUDIO_DEVICE_NONE
7130 && adev->voice_tx_output != NULL) {
7131 /* Use the rx device from afe-proxy record to route voice call because
7132 there is no routing if tx device is on primary hal and rx device
7133 is on other hal during voice call. */
7134 adev->voice_tx_output->devices = device;
7135
7136 if (!voice_is_call_state_active(adev)) {
7137 if (adev->mode == AUDIO_MODE_IN_CALL) {
7138 adev->current_call_output = adev->voice_tx_output;
7139 error = voice_start_call(adev);
7140 if (error != 0)
7141 ALOGE("%s: start voice call failed %d", __func__, error);
7142 }
7143 } else {
7144 adev->current_call_output = adev->voice_tx_output;
7145 voice_update_devices_for_all_voice_usecases(adev);
7146 }
7147 }
7148
7149 pthread_mutex_unlock(&adev->lock);
7150 pthread_mutex_unlock(&in->lock);
7151}
7152
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307153int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007154 audio_io_handle_t handle,
7155 audio_devices_t devices,
7156 audio_output_flags_t flags,
7157 struct audio_config *config,
7158 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007159 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007160{
7161 struct audio_device *adev = (struct audio_device *)dev;
7162 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307163 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007164 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007165 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307166 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007167 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7168 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7169 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7170 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007171 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007172 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7173 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007174 bool force_haptic_path =
7175 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007176 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177
kunleizdff872d2018-08-20 14:40:33 +08007178 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007179 is_usb_dev = false;
7180 devices = AUDIO_DEVICE_OUT_SPEAKER;
7181 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7182 __func__, devices);
7183 }
7184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007185 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307186
Rahul Sharma99770982019-03-06 17:05:26 +05307187 pthread_mutex_lock(&adev->lock);
7188 if (out_get_stream(adev, handle) != NULL) {
7189 ALOGW("%s, output stream already opened", __func__);
7190 ret = -EEXIST;
7191 }
7192 pthread_mutex_unlock(&adev->lock);
7193 if (ret)
7194 return ret;
7195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7197
Mingming Yin3a941d42016-02-17 18:08:05 -08007198 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007199 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7200 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307201
7202
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007203 if (!out) {
7204 return -ENOMEM;
7205 }
7206
Haynes Mathew George204045b2015-02-25 20:32:03 -08007207 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007208 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307209 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007210 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007211 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213 if (devices == AUDIO_DEVICE_NONE)
7214 devices = AUDIO_DEVICE_OUT_SPEAKER;
7215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007216 out->flags = flags;
7217 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007218 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007219 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007220 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307221 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307222 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7223 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7224 else
7225 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007226 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007227 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007228 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307229 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307230 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307231 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007232 out->hal_output_suspend_supported = 0;
7233 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307234 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307235 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307236 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307238 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307239 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007240 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7241
Aalique Grahame22e49102018-12-18 14:23:57 -08007242 if (direct_dev &&
7243 (audio_is_linear_pcm(out->format) ||
7244 config->format == AUDIO_FORMAT_DEFAULT) &&
7245 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7246 audio_format_t req_format = config->format;
7247 audio_channel_mask_t req_channel_mask = config->channel_mask;
7248 uint32_t req_sample_rate = config->sample_rate;
7249
7250 pthread_mutex_lock(&adev->lock);
7251 if (is_hdmi) {
7252 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7253 ret = read_hdmi_sink_caps(out);
7254 if (config->sample_rate == 0)
7255 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7256 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7257 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7258 if (config->format == AUDIO_FORMAT_DEFAULT)
7259 config->format = AUDIO_FORMAT_PCM_16_BIT;
7260 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007261 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7262 &config->format,
7263 &out->supported_formats[0],
7264 MAX_SUPPORTED_FORMATS,
7265 &config->channel_mask,
7266 &out->supported_channel_masks[0],
7267 MAX_SUPPORTED_CHANNEL_MASKS,
7268 &config->sample_rate,
7269 &out->supported_sample_rates[0],
7270 MAX_SUPPORTED_SAMPLE_RATES);
7271 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007272 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007273
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007274 pthread_mutex_unlock(&adev->lock);
7275 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007276 if (ret == -ENOSYS) {
7277 /* ignore and go with default */
7278 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007279 }
7280 // For MMAP NO IRQ, allow conversions in ADSP
7281 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7282 goto error_open;
7283 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007284 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007285 goto error_open;
7286 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007287
7288 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7289 config->sample_rate = req_sample_rate;
7290 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7291 config->channel_mask = req_channel_mask;
7292 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7293 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007294 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007295
7296 out->sample_rate = config->sample_rate;
7297 out->channel_mask = config->channel_mask;
7298 out->format = config->format;
7299 if (is_hdmi) {
7300 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7301 out->config = pcm_config_hdmi_multi;
7302 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7303 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7304 out->config = pcm_config_mmap_playback;
7305 out->stream.start = out_start;
7306 out->stream.stop = out_stop;
7307 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7308 out->stream.get_mmap_position = out_get_mmap_position;
7309 } else {
7310 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7311 out->config = pcm_config_hifi;
7312 }
7313
7314 out->config.rate = out->sample_rate;
7315 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7316 if (is_hdmi) {
7317 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7318 audio_bytes_per_sample(out->format));
7319 }
7320 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007321 }
7322
Derek Chenf6318be2017-06-12 17:16:24 -04007323 /* validate bus device address */
7324 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7325 /* extract car audio stream index */
7326 out->car_audio_stream =
7327 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7328 if (out->car_audio_stream < 0) {
7329 ALOGE("%s: invalid car audio stream %x",
7330 __func__, out->car_audio_stream);
7331 ret = -EINVAL;
7332 goto error_open;
7333 }
7334 /* save car audio stream and address for bus device */
7335 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7336 ALOGV("%s: address %s, car_audio_stream %x",
7337 __func__, out->address, out->car_audio_stream);
7338 }
7339
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007340 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007341 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007342 if (!voice_extn_is_compress_voip_supported()) {
7343 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7344 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007345 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7346 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007347 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7348 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007349 out->volume_l = INVALID_OUT_VOLUME;
7350 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007351
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007352 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007353 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007354 uint32_t channel_count =
7355 audio_channel_count_from_out_mask(out->channel_mask);
7356 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7357 out->sample_rate, out->format,
7358 channel_count, false);
7359 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7360 if (frame_size != 0)
7361 out->config.period_size = buffer_size / frame_size;
7362 else
7363 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007364 }
7365 } else {
7366 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7367 voice_extn_compress_voip_is_active(out->dev)) &&
7368 (voice_extn_compress_voip_is_config_supported(config))) {
7369 ret = voice_extn_compress_voip_open_output_stream(out);
7370 if (ret != 0) {
7371 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7372 __func__, ret);
7373 goto error_open;
7374 }
Sujin Panickerabaf5ad2019-09-16 18:28:06 +05307375 } else {
7376 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7377 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007378 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007379 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007380 } else if (audio_is_linear_pcm(out->format) &&
7381 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7382 out->channel_mask = config->channel_mask;
7383 out->sample_rate = config->sample_rate;
7384 out->format = config->format;
7385 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7386 // does this change?
7387 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7388 out->config.rate = config->sample_rate;
7389 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7390 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7391 audio_bytes_per_sample(config->format));
7392 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007393 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307394 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307395 pthread_mutex_lock(&adev->lock);
7396 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7397 pthread_mutex_unlock(&adev->lock);
7398
7399 // reject offload during card offline to allow
7400 // fallback to s/w paths
7401 if (offline) {
7402 ret = -ENODEV;
7403 goto error_open;
7404 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007405
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007406 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7407 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7408 ALOGE("%s: Unsupported Offload information", __func__);
7409 ret = -EINVAL;
7410 goto error_open;
7411 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007412
Atul Khare3fa6e542017-08-09 00:56:17 +05307413 if (config->offload_info.format == 0)
7414 config->offload_info.format = config->format;
7415 if (config->offload_info.sample_rate == 0)
7416 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007417
Mingming Yin90310102013-11-13 16:57:00 -08007418 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307419 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007420 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007421 ret = -EINVAL;
7422 goto error_open;
7423 }
7424
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007425 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7426 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7427 (audio_extn_passthru_is_passthrough_stream(out)) &&
7428 !((config->sample_rate == 48000) ||
7429 (config->sample_rate == 96000) ||
7430 (config->sample_rate == 192000))) {
7431 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7432 __func__, config->sample_rate, config->offload_info.format);
7433 ret = -EINVAL;
7434 goto error_open;
7435 }
7436
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007437 out->compr_config.codec = (struct snd_codec *)
7438 calloc(1, sizeof(struct snd_codec));
7439
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007440 if (!out->compr_config.codec) {
7441 ret = -ENOMEM;
7442 goto error_open;
7443 }
7444
Dhananjay Kumarac341582017-02-23 23:42:25 +05307445 out->stream.pause = out_pause;
7446 out->stream.resume = out_resume;
7447 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307448 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307449 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007450 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307451 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007452 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307453 } else {
7454 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7455 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007456 }
vivek mehta446c3962015-09-14 10:57:35 -07007457
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307458 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7459 ALOGD("%s: Setting latency mode to true", __func__);
7460 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7461 }
7462
vivek mehta446c3962015-09-14 10:57:35 -07007463 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007464 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7465 config->format == 0 && config->sample_rate == 0 &&
7466 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007467 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007468 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7469 } else {
7470 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7471 ret = -EEXIST;
7472 goto error_open;
7473 }
vivek mehta446c3962015-09-14 10:57:35 -07007474 }
7475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007476 if (config->offload_info.channel_mask)
7477 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007478 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007479 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007480 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007481 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307482 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007483 ret = -EINVAL;
7484 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007485 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007486
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007487 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007488 out->sample_rate = config->offload_info.sample_rate;
7489
Mingming Yin3ee55c62014-08-04 14:23:35 -07007490 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007491
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307492 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307493 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307494 audio_extn_dolby_send_ddp_endp_params(adev);
7495 audio_extn_dolby_set_dmid(adev);
7496 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007498 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007499 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007500 out->compr_config.codec->bit_rate =
7501 config->offload_info.bit_rate;
7502 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307503 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007504 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307505 /* Update bit width only for non passthrough usecases.
7506 * For passthrough usecases, the output will always be opened @16 bit
7507 */
7508 if (!audio_extn_passthru_is_passthrough_stream(out))
7509 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307510
7511 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7512 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7513 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7514
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007515 /*TODO: Do we need to change it for passthrough */
7516 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007517
Manish Dewangana6fc5442015-08-24 20:30:31 +05307518 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7519 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307520 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307521 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307522 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7523 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307524
7525 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7526 AUDIO_FORMAT_PCM) {
7527
7528 /*Based on platform support, configure appropriate alsa format for corresponding
7529 *hal input format.
7530 */
7531 out->compr_config.codec->format = hal_format_to_alsa(
7532 config->offload_info.format);
7533
Ashish Jain83a6cc22016-06-28 14:34:17 +05307534 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307535 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307536 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307537
Dhananjay Kumarac341582017-02-23 23:42:25 +05307538 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307539 *hal input format and alsa format might differ based on platform support.
7540 */
7541 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307542 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307543
7544 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7545
Deeraj Soman65358ab2019-02-07 15:40:49 +05307546 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7547 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7548 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7549
Ashish Jainf1eaa582016-05-23 20:54:24 +05307550 /* Check if alsa session is configured with the same format as HAL input format,
7551 * if not then derive correct fragment size needed to accomodate the
7552 * conversion of HAL input format to alsa format.
7553 */
7554 audio_extn_utils_update_direct_pcm_fragment_size(out);
7555
7556 /*if hal input and output fragment size is different this indicates HAL input format is
7557 *not same as the alsa format
7558 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307559 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307560 /*Allocate a buffer to convert input data to the alsa configured format.
7561 *size of convert buffer is equal to the size required to hold one fragment size
7562 *worth of pcm data, this is because flinger does not write more than fragment_size
7563 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307564 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7565 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307566 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7567 ret = -ENOMEM;
7568 goto error_open;
7569 }
7570 }
7571 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7572 out->compr_config.fragment_size =
7573 audio_extn_passthru_get_buffer_size(&config->offload_info);
7574 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7575 } else {
7576 out->compr_config.fragment_size =
7577 platform_get_compress_offload_buffer_size(&config->offload_info);
7578 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7579 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007580
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307581 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7582 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7583 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007584 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307585 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007586
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307587 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7588 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7589 }
7590
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007591 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7592 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007593
Manish Dewangan69426c82017-01-30 17:35:36 +05307594 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7595 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7596 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7597 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7598 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7599 } else {
7600 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7601 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007602
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307603 memset(&out->channel_map_param, 0,
7604 sizeof(struct audio_out_channel_map_param));
7605
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007606 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307607 out->send_next_track_params = false;
7608 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007609 out->offload_state = OFFLOAD_STATE_IDLE;
7610 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007611 out->writeAt.tv_sec = 0;
7612 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007613
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007614 audio_extn_dts_create_state_notifier_node(out->usecase);
7615
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007616 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7617 __func__, config->offload_info.version,
7618 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307619
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307620 /* Check if DSD audio format is supported in codec
7621 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307622 */
7623
7624 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307625 (!platform_check_codec_dsd_support(adev->platform) ||
7626 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307627 ret = -EINVAL;
7628 goto error_open;
7629 }
7630
Ashish Jain5106d362016-05-11 19:23:33 +05307631 /* Disable gapless if any of the following is true
7632 * passthrough playback
7633 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307634 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307635 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307636 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307637 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007638 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307639 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307640 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307641 check_and_set_gapless_mode(adev, false);
7642 } else
7643 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007644
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307645 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007646 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7647 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307648 if (config->format == AUDIO_FORMAT_DSD) {
7649 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7650 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7651 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007652
7653 create_offload_callback_thread(out);
7654
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007655 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007656 switch (config->sample_rate) {
7657 case 0:
7658 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7659 break;
7660 case 8000:
7661 case 16000:
7662 case 48000:
7663 out->sample_rate = config->sample_rate;
7664 break;
7665 default:
7666 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7667 config->sample_rate);
7668 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7669 ret = -EINVAL;
7670 goto error_open;
7671 }
7672 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7673 switch (config->channel_mask) {
7674 case AUDIO_CHANNEL_NONE:
7675 case AUDIO_CHANNEL_OUT_STEREO:
7676 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7677 break;
7678 default:
7679 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7680 config->channel_mask);
7681 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7682 ret = -EINVAL;
7683 goto error_open;
7684 }
7685 switch (config->format) {
7686 case AUDIO_FORMAT_DEFAULT:
7687 case AUDIO_FORMAT_PCM_16_BIT:
7688 out->format = AUDIO_FORMAT_PCM_16_BIT;
7689 break;
7690 default:
7691 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7692 config->format);
7693 config->format = AUDIO_FORMAT_PCM_16_BIT;
7694 ret = -EINVAL;
7695 goto error_open;
7696 }
7697
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307698 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007699 if (ret != 0) {
7700 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007701 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007702 goto error_open;
7703 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007704 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007705 switch (config->sample_rate) {
7706 case 0:
7707 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7708 break;
7709 case 8000:
7710 case 16000:
7711 case 48000:
7712 out->sample_rate = config->sample_rate;
7713 break;
7714 default:
7715 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7716 config->sample_rate);
7717 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7718 ret = -EINVAL;
7719 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007720 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007721 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7722 switch (config->channel_mask) {
7723 case AUDIO_CHANNEL_NONE:
7724 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7725 break;
7726 case AUDIO_CHANNEL_OUT_STEREO:
7727 out->channel_mask = config->channel_mask;
7728 break;
7729 default:
7730 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7731 config->channel_mask);
7732 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7733 ret = -EINVAL;
7734 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007735 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007736 switch (config->format) {
7737 case AUDIO_FORMAT_DEFAULT:
7738 out->format = AUDIO_FORMAT_PCM_16_BIT;
7739 break;
7740 case AUDIO_FORMAT_PCM_16_BIT:
7741 out->format = config->format;
7742 break;
7743 default:
7744 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7745 config->format);
7746 config->format = AUDIO_FORMAT_PCM_16_BIT;
7747 ret = -EINVAL;
7748 break;
7749 }
7750 if (ret != 0)
7751 goto error_open;
7752
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007753 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7754 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007755 out->config.rate = out->sample_rate;
7756 out->config.channels =
7757 audio_channel_count_from_out_mask(out->channel_mask);
7758 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007759 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007760 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307761 unsigned int channels = 0;
7762 /*Update config params to default if not set by the caller*/
7763 if (config->sample_rate == 0)
7764 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7765 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7766 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7767 if (config->format == AUDIO_FORMAT_DEFAULT)
7768 config->format = AUDIO_FORMAT_PCM_16_BIT;
7769
7770 channels = audio_channel_count_from_out_mask(out->channel_mask);
7771
Varun Balaraje49253e2017-07-06 19:48:56 +05307772 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7773 out->usecase = get_interactive_usecase(adev);
7774 out->config = pcm_config_low_latency;
7775 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307776 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007777 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7778 out->flags);
7779 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007780 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7781 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7782 out->config = pcm_config_mmap_playback;
7783 out->stream.start = out_start;
7784 out->stream.stop = out_stop;
7785 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7786 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307787 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7788 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007789 out->hal_output_suspend_supported =
7790 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7791 out->dynamic_pm_qos_config_supported =
7792 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7793 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007794 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7795 } else {
7796 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7797 //the mixer path will be a string similar to "low-latency-playback resume"
7798 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7799 strlcat(out->pm_qos_mixer_path,
7800 " resume", MAX_MIXER_PATH_LEN);
7801 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7802 out->pm_qos_mixer_path);
7803 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307804 out->config = pcm_config_low_latency;
7805 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7806 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7807 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307808 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7809 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7810 if (out->config.period_size <= 0) {
7811 ALOGE("Invalid configuration period size is not valid");
7812 ret = -EINVAL;
7813 goto error_open;
7814 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007815 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7816 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7817 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007818 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7819 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7820 out->config = pcm_config_haptics_audio;
7821 if (force_haptic_path)
7822 adev->haptics_config = pcm_config_haptics_audio;
7823 else
7824 adev->haptics_config = pcm_config_haptics;
7825
7826 out->config.channels =
7827 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7828
7829 if (force_haptic_path) {
7830 out->config.channels = 1;
7831 adev->haptics_config.channels = 1;
7832 } else
7833 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007834 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7835 ret = audio_extn_auto_hal_open_output_stream(out);
7836 if (ret) {
7837 ALOGE("%s: Failed to open output stream for bus device", __func__);
7838 ret = -EINVAL;
7839 goto error_open;
7840 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307841 } else {
7842 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007843 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7844 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307845 }
7846 out->hal_ip_format = format = out->format;
7847 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7848 out->hal_op_format = pcm_format_to_hal(out->config.format);
7849 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7850 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007851 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307852 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307853 if (out->hal_ip_format != out->hal_op_format) {
7854 uint32_t buffer_size = out->config.period_size *
7855 format_to_bitwidth_table[out->hal_op_format] *
7856 out->config.channels;
7857 out->convert_buffer = calloc(1, buffer_size);
7858 if (out->convert_buffer == NULL){
7859 ALOGE("Allocation failed for convert buffer for size %d",
7860 out->compr_config.fragment_size);
7861 ret = -ENOMEM;
7862 goto error_open;
7863 }
7864 ALOGD("Convert buffer allocated of size %d", buffer_size);
7865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007866 }
7867
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007868 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7869 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307870
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007871 /* TODO remove this hardcoding and check why width is zero*/
7872 if (out->bit_width == 0)
7873 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307874 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007875 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007876 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307877 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307878 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007879 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007880 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7881 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007882 if(adev->primary_output == NULL)
7883 adev->primary_output = out;
7884 else {
7885 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007886 ret = -EEXIST;
7887 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007888 }
7889 }
7890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007891 /* Check if this usecase is already existing */
7892 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007893 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7894 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007895 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007896 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007897 ret = -EEXIST;
7898 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007899 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007901 pthread_mutex_unlock(&adev->lock);
7902
7903 out->stream.common.get_sample_rate = out_get_sample_rate;
7904 out->stream.common.set_sample_rate = out_set_sample_rate;
7905 out->stream.common.get_buffer_size = out_get_buffer_size;
7906 out->stream.common.get_channels = out_get_channels;
7907 out->stream.common.get_format = out_get_format;
7908 out->stream.common.set_format = out_set_format;
7909 out->stream.common.standby = out_standby;
7910 out->stream.common.dump = out_dump;
7911 out->stream.common.set_parameters = out_set_parameters;
7912 out->stream.common.get_parameters = out_get_parameters;
7913 out->stream.common.add_audio_effect = out_add_audio_effect;
7914 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7915 out->stream.get_latency = out_get_latency;
7916 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007917#ifdef NO_AUDIO_OUT
7918 out->stream.write = out_write_for_no_output;
7919#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007920 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007921#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007922 out->stream.get_render_position = out_get_render_position;
7923 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007924 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007925
Haynes Mathew George16081042017-05-31 17:16:49 -07007926 if (out->realtime)
7927 out->af_period_multiplier = af_period_multiplier;
7928 else
7929 out->af_period_multiplier = 1;
7930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007931 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007932 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007933 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007934
7935 config->format = out->stream.common.get_format(&out->stream.common);
7936 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7937 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307938 register_format(out->format, out->supported_formats);
7939 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7940 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007941
Aalique Grahame22e49102018-12-18 14:23:57 -08007942 out->error_log = error_log_create(
7943 ERROR_LOG_ENTRIES,
7944 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7945
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307946 /*
7947 By locking output stream before registering, we allow the callback
7948 to update stream's state only after stream's initial state is set to
7949 adev state.
7950 */
7951 lock_output_stream(out);
7952 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7953 pthread_mutex_lock(&adev->lock);
7954 out->card_status = adev->card_status;
7955 pthread_mutex_unlock(&adev->lock);
7956 pthread_mutex_unlock(&out->lock);
7957
Aalique Grahame22e49102018-12-18 14:23:57 -08007958 stream_app_type_cfg_init(&out->app_type_cfg);
7959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007960 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307961 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007962 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007963
7964 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7965 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7966 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007967 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307968 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007969 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007970 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307971 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7972 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007973 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7974 out->usecase, PCM_PLAYBACK);
7975 hdlr_stream_cfg.flags = out->flags;
7976 hdlr_stream_cfg.type = PCM_PLAYBACK;
7977 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7978 &hdlr_stream_cfg);
7979 if (ret) {
7980 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7981 out->adsp_hdlr_stream_handle = NULL;
7982 }
7983 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307984 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7985 is_direct_passthough, false);
7986 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7987 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007988 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007989 if (ret < 0) {
7990 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7991 out->ip_hdlr_handle = NULL;
7992 }
7993 }
Derek Chenf939fb72018-11-13 13:34:41 -08007994
7995 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7996 calloc(1, sizeof(streams_output_ctxt_t));
7997 if (out_ctxt == NULL) {
7998 ALOGE("%s fail to allocate output ctxt", __func__);
7999 ret = -ENOMEM;
8000 goto error_open;
8001 }
8002 out_ctxt->output = out;
8003
8004 pthread_mutex_lock(&adev->lock);
8005 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8006 pthread_mutex_unlock(&adev->lock);
8007
Eric Laurent994a6932013-07-17 11:51:42 -07008008 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008009 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008010
8011error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308012 if (out->convert_buffer)
8013 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008014 free(out);
8015 *stream_out = NULL;
8016 ALOGD("%s: exit: ret %d", __func__, ret);
8017 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008018}
8019
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308020void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008021 struct audio_stream_out *stream)
8022{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008023 struct stream_out *out = (struct stream_out *)stream;
8024 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008025 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008026
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008027 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308028
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308029 // must deregister from sndmonitor first to prevent races
8030 // between the callback and close_stream
8031 audio_extn_snd_mon_unregister_listener(out);
8032
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008033 /* close adsp hdrl session before standby */
8034 if (out->adsp_hdlr_stream_handle) {
8035 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8036 if (ret)
8037 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8038 out->adsp_hdlr_stream_handle = NULL;
8039 }
8040
Manish Dewangan21a850a2017-08-14 12:03:55 +05308041 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008042 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8043 out->ip_hdlr_handle = NULL;
8044 }
8045
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008046 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308047 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008048 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308049 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308050 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008051 if(ret != 0)
8052 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8053 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008054 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008055 out_standby(&stream->common);
8056
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008057 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008058 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008059 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008060 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008061 if (out->compr_config.codec != NULL)
8062 free(out->compr_config.codec);
8063 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008064
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308065 out->a2dp_compress_mute = false;
8066
Varun Balaraje49253e2017-07-06 19:48:56 +05308067 if (is_interactive_usecase(out->usecase))
8068 free_interactive_usecase(adev, out->usecase);
8069
Ashish Jain83a6cc22016-06-28 14:34:17 +05308070 if (out->convert_buffer != NULL) {
8071 free(out->convert_buffer);
8072 out->convert_buffer = NULL;
8073 }
8074
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008075 if (adev->voice_tx_output == out)
8076 adev->voice_tx_output = NULL;
8077
Aalique Grahame22e49102018-12-18 14:23:57 -08008078 error_log_destroy(out->error_log);
8079 out->error_log = NULL;
8080
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308081 if (adev->primary_output == out)
8082 adev->primary_output = NULL;
8083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008084 pthread_cond_destroy(&out->cond);
8085 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008086
8087 pthread_mutex_lock(&adev->lock);
8088 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8089 if (out_ctxt != NULL) {
8090 list_remove(&out_ctxt->list);
8091 free(out_ctxt);
8092 } else {
8093 ALOGW("%s, output stream already closed", __func__);
8094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008095 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008096 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008097 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008098}
8099
8100static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8101{
8102 struct audio_device *adev = (struct audio_device *)dev;
8103 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008104 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008105 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008106 int ret;
8107 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008108 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008109 struct listnode *node;
8110 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008111
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008112 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008113 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008114
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308115 if (!parms)
8116 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308117
Derek Chen6f293672019-04-01 01:40:24 -07008118 /* notify adev and input/output streams on the snd card status */
8119 adev_snd_mon_cb((void *)adev, parms);
8120
8121 list_for_each(node, &adev->active_outputs_list) {
8122 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8123 streams_output_ctxt_t,
8124 list);
8125 out_snd_mon_cb((void *)out_ctxt->output, parms);
8126 }
8127
8128 list_for_each(node, &adev->active_inputs_list) {
8129 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8130 streams_input_ctxt_t,
8131 list);
8132 in_snd_mon_cb((void *)in_ctxt->input, parms);
8133 }
8134
Zhou Songd6d71752019-05-21 18:08:51 +08008135 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308136 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8137 if (ret >= 0) {
8138 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008139 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308140 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008141 } else {
8142 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308143 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008144 audio_extn_sco_reset_configuration();
8145 list_for_each(node, &adev->usecase_list) {
8146 usecase = node_to_item(node, struct audio_usecase, list);
8147 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
8148 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
8149 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
8150 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
8151 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
8152 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
8153 else
8154 continue;
8155 select_devices(adev, usecase->id);
8156 }
8157 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308158 }
8159
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008160 status = voice_set_parameters(adev, parms);
8161 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008162 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008163
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008164 status = platform_set_parameters(adev->platform, parms);
8165 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008166 goto done;
8167
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008168 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8169 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008170 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008171 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8172 adev->bluetooth_nrec = true;
8173 else
8174 adev->bluetooth_nrec = false;
8175 }
8176
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008177 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8178 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008179 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8180 adev->screen_off = false;
8181 else
8182 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008183 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008184 }
8185
Eric Laurent4b084132018-10-19 17:33:43 -07008186 ret = str_parms_get_int(parms, "rotation", &val);
8187 if (ret >= 0) {
8188 bool reverse_speakers = false;
8189 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8190 switch (val) {
8191 // FIXME: note that the code below assumes that the speakers are in the correct placement
8192 // relative to the user when the device is rotated 90deg from its default rotation. This
8193 // assumption is device-specific, not platform-specific like this code.
8194 case 270:
8195 reverse_speakers = true;
8196 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8197 break;
8198 case 0:
8199 case 180:
8200 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8201 break;
8202 case 90:
8203 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8204 break;
8205 default:
8206 ALOGE("%s: unexpected rotation of %d", __func__, val);
8207 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008208 }
Eric Laurent4b084132018-10-19 17:33:43 -07008209 if (status == 0) {
8210 // check and set swap
8211 // - check if orientation changed and speaker active
8212 // - set rotation and cache the rotation value
8213 adev->camera_orientation =
8214 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8215 if (!audio_extn_is_maxx_audio_enabled())
8216 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8217 }
8218 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008219
Mingming Yin514a8bc2014-07-29 15:22:21 -07008220 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8221 if (ret >= 0) {
8222 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8223 adev->bt_wb_speech_enabled = true;
8224 else
8225 adev->bt_wb_speech_enabled = false;
8226 }
8227
Zhou Song12c29502019-03-16 10:37:18 +08008228 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8229 if (ret >= 0) {
8230 val = atoi(value);
8231 adev->swb_speech_mode = val;
8232 }
8233
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008234 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8235 if (ret >= 0) {
8236 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308237 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008238 if (audio_is_output_device(val) &&
8239 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008240 ALOGV("cache new ext disp type and edid");
8241 ret = platform_get_ext_disp_type(adev->platform);
8242 if (ret < 0) {
8243 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308244 } else {
8245 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008246 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308247 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008248 /*
8249 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8250 * Per AudioPolicyManager, USB device is higher priority than WFD.
8251 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8252 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8253 * starting voice call on USB
8254 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008255 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308256 if (ret >= 0)
8257 audio_extn_usb_add_device(device, atoi(value));
8258
Zhou Song6f862822017-11-06 17:27:57 +08008259 if (!audio_extn_usb_is_tunnel_supported()) {
8260 ALOGV("detected USB connect .. disable proxy");
8261 adev->allow_afe_proxy_usage = false;
8262 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008263 }
8264 }
8265
8266 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8267 if (ret >= 0) {
8268 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308269 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008270 /*
8271 * The HDMI / Displayport disconnect handling has been moved to
8272 * audio extension to ensure that its parameters are not
8273 * invalidated prior to updating sysfs of the disconnect event
8274 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8275 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308276 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008277 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308278 if (ret >= 0)
8279 audio_extn_usb_remove_device(device, atoi(value));
8280
Zhou Song6f862822017-11-06 17:27:57 +08008281 if (!audio_extn_usb_is_tunnel_supported()) {
8282 ALOGV("detected USB disconnect .. enable proxy");
8283 adev->allow_afe_proxy_usage = true;
8284 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008285 }
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05308286 if (audio_is_a2dp_out_device(device)) {
8287 struct audio_usecase *usecase;
8288 struct listnode *node;
8289 list_for_each(node, &adev->usecase_list) {
8290 usecase = node_to_item(node, struct audio_usecase, list);
8291 if (PCM_PLAYBACK == usecase->type && usecase->stream.out &&
8292 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8293 usecase->stream.out->a2dp_compress_mute) {
8294 struct stream_out *out = usecase->stream.out;
8295 ALOGD("Unmuting the stream when Bt-A2dp disconnected and stream is mute");
8296 out->a2dp_compress_mute = false;
8297 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8298 }
8299 }
8300 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008301 }
8302
Aalique Grahame22e49102018-12-18 14:23:57 -08008303 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008304 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008305
8306 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008307 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308308 struct audio_usecase *usecase;
8309 struct listnode *node;
8310 list_for_each(node, &adev->usecase_list) {
8311 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308312 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008313 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308314 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008315 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308316 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008317 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308318 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308319 ALOGD("Switching to speaker and muting the stream before select_devices");
8320 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308321 //force device switch to re configure encoder
8322 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308323 ALOGD("Unmuting the stream after select_devices");
8324 usecase->stream.out->a2dp_compress_mute = false;
8325 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 +05308326 audio_extn_a2dp_set_handoff_mode(false);
8327 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308328 break;
8329 }
8330 }
8331 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008332
8333 //handle vr audio setparam
8334 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8335 value, sizeof(value));
8336 if (ret >= 0) {
8337 ALOGI("Setting vr mode to be %s", value);
8338 if (!strncmp(value, "true", 4)) {
8339 adev->vr_audio_mode_enabled = true;
8340 ALOGI("Setting vr mode to true");
8341 } else if (!strncmp(value, "false", 5)) {
8342 adev->vr_audio_mode_enabled = false;
8343 ALOGI("Setting vr mode to false");
8344 } else {
8345 ALOGI("wrong vr mode set");
8346 }
8347 }
8348
Eric Laurent4b084132018-10-19 17:33:43 -07008349 //FIXME: to be replaced by proper video capture properties API
8350 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8351 if (ret >= 0) {
8352 int camera_facing = CAMERA_FACING_BACK;
8353 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8354 camera_facing = CAMERA_FACING_FRONT;
8355 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8356 camera_facing = CAMERA_FACING_BACK;
8357 else {
8358 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8359 goto done;
8360 }
8361 adev->camera_orientation =
8362 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8363 struct audio_usecase *usecase;
8364 struct listnode *node;
8365 list_for_each(node, &adev->usecase_list) {
8366 usecase = node_to_item(node, struct audio_usecase, list);
8367 struct stream_in *in = usecase->stream.in;
8368 if (usecase->type == PCM_CAPTURE && in != NULL &&
8369 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8370 select_devices(adev, in->usecase);
8371 }
8372 }
8373 }
8374
Balázs Triszkaa68afd52017-05-11 03:19:29 +02008375 ret = str_parms_get_int(parms, "ultrasound-sensor", &val);
8376 if (ret >= 0) {
8377 if (val == 1) {
8378 us_start();
8379 } else {
8380 us_stop();
8381 }
8382 }
8383
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308384 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008385done:
8386 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008387 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308388error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008389 ALOGV("%s: exit with code(%d)", __func__, status);
8390 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008391}
8392
8393static char* adev_get_parameters(const struct audio_hw_device *dev,
8394 const char *keys)
8395{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308396 ALOGD("%s:%s", __func__, keys);
8397
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008398 struct audio_device *adev = (struct audio_device *)dev;
8399 struct str_parms *reply = str_parms_create();
8400 struct str_parms *query = str_parms_create_str(keys);
8401 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308402 char value[256] = {0};
8403 int ret = 0;
8404
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008405 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008406 if (reply) {
8407 str_parms_destroy(reply);
8408 }
8409 if (query) {
8410 str_parms_destroy(query);
8411 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008412 ALOGE("adev_get_parameters: failed to create query or reply");
8413 return NULL;
8414 }
8415
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008416 //handle vr audio getparam
8417
8418 ret = str_parms_get_str(query,
8419 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8420 value, sizeof(value));
8421
8422 if (ret >= 0) {
8423 bool vr_audio_enabled = false;
8424 pthread_mutex_lock(&adev->lock);
8425 vr_audio_enabled = adev->vr_audio_mode_enabled;
8426 pthread_mutex_unlock(&adev->lock);
8427
8428 ALOGI("getting vr mode to %d", vr_audio_enabled);
8429
8430 if (vr_audio_enabled) {
8431 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8432 "true");
8433 goto exit;
8434 } else {
8435 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8436 "false");
8437 goto exit;
8438 }
8439 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008440
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008441 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008442 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008443 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008444 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008445 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308446 pthread_mutex_unlock(&adev->lock);
8447
Naresh Tannirud7205b62014-06-20 02:54:48 +05308448exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008449 str = str_parms_to_str(reply);
8450 str_parms_destroy(query);
8451 str_parms_destroy(reply);
8452
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308453 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008454 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008455}
8456
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008457static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008458{
8459 return 0;
8460}
8461
8462static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8463{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008464 int ret;
8465 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008466
8467 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8468
Haynes Mathew George5191a852013-09-11 14:19:36 -07008469 pthread_mutex_lock(&adev->lock);
8470 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008471 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008472 pthread_mutex_unlock(&adev->lock);
8473 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474}
8475
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008476static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8477 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008478{
8479 return -ENOSYS;
8480}
8481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008482static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8483 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008484{
8485 return -ENOSYS;
8486}
8487
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008488static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8489 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008490{
8491 return -ENOSYS;
8492}
8493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008494static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8495 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496{
8497 return -ENOSYS;
8498}
8499
8500static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8501{
8502 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008503 struct listnode *node;
8504 struct audio_usecase *usecase = NULL;
8505 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008507 pthread_mutex_lock(&adev->lock);
8508 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008509 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008510 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008511 if (voice_is_in_call(adev) &&
8512 (mode == AUDIO_MODE_NORMAL ||
8513 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008514 list_for_each(node, &adev->usecase_list) {
8515 usecase = node_to_item(node, struct audio_usecase, list);
8516 if (usecase->type == VOICE_CALL)
8517 break;
8518 }
8519 if (usecase &&
8520 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8521 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8522 true);
8523 if (ret != 0) {
8524 /* default service interval was successfully updated,
8525 reopen USB backend with new service interval */
8526 check_usecases_codec_backend(adev,
8527 usecase,
8528 usecase->out_snd_device);
8529 }
8530 }
8531
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008532 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008533 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008534 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008535 // restore device for other active usecases after stop call
8536 list_for_each(node, &adev->usecase_list) {
8537 usecase = node_to_item(node, struct audio_usecase, list);
8538 select_devices(adev, usecase->id);
8539 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008540 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008541 }
8542 pthread_mutex_unlock(&adev->lock);
8543 return 0;
8544}
8545
8546static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8547{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008548 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008549 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008550
8551 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008552 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008553 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008554
Derek Chend2530072014-11-24 12:39:14 -08008555 if (adev->ext_hw_plugin)
8556 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008557
8558 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008559 pthread_mutex_unlock(&adev->lock);
8560
8561 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008562}
8563
8564static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8565{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008566 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008567 return 0;
8568}
8569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008570static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008571 const struct audio_config *config)
8572{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008573 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008574
Aalique Grahame22e49102018-12-18 14:23:57 -08008575 /* Don't know if USB HIFI in this context so use true to be conservative */
8576 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8577 true /*is_usb_hifi */) != 0)
8578 return 0;
8579
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008580 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8581 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008582}
8583
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008584static bool adev_input_allow_hifi_record(struct audio_device *adev,
8585 audio_devices_t devices,
8586 audio_input_flags_t flags,
8587 audio_source_t source) {
8588 const bool allowed = true;
8589
8590 if (!audio_is_usb_in_device(devices))
8591 return !allowed;
8592
8593 switch (flags) {
8594 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008595 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008596 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8597 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008598 default:
8599 return !allowed;
8600 }
8601
8602 switch (source) {
8603 case AUDIO_SOURCE_DEFAULT:
8604 case AUDIO_SOURCE_MIC:
8605 case AUDIO_SOURCE_UNPROCESSED:
8606 break;
8607 default:
8608 return !allowed;
8609 }
8610
8611 switch (adev->mode) {
8612 case 0:
8613 break;
8614 default:
8615 return !allowed;
8616 }
8617
8618 return allowed;
8619}
8620
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008621static int adev_update_voice_comm_input_stream(struct stream_in *in,
8622 struct audio_config *config)
8623{
8624 bool valid_rate = (config->sample_rate == 8000 ||
8625 config->sample_rate == 16000 ||
8626 config->sample_rate == 32000 ||
8627 config->sample_rate == 48000);
8628 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8629
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008630 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008631 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008632 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8633 in->config = default_pcm_config_voip_copp;
8634 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8635 DEFAULT_VOIP_BUF_DURATION_MS,
8636 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008637 } else {
8638 ALOGW("%s No valid input in voip, use defaults"
8639 "sample rate %u, channel mask 0x%X",
8640 __func__, config->sample_rate, in->channel_mask);
8641 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008642 in->config.rate = config->sample_rate;
8643 in->sample_rate = config->sample_rate;
8644 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008645 //XXX needed for voice_extn_compress_voip_open_input_stream
8646 in->config.rate = config->sample_rate;
8647 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathacd1de7d2019-08-23 15:13:46 +05308648 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008649 voice_extn_compress_voip_is_active(in->dev)) &&
8650 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8651 valid_rate && valid_ch) {
8652 voice_extn_compress_voip_open_input_stream(in);
8653 // update rate entries to match config from AF
8654 in->config.rate = config->sample_rate;
8655 in->sample_rate = config->sample_rate;
8656 } else {
8657 ALOGW("%s compress voip not active, use defaults", __func__);
8658 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008659 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008660 return 0;
8661}
8662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008663static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008664 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008665 audio_devices_t devices,
8666 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008667 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308668 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008669 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008670 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008671{
8672 struct audio_device *adev = (struct audio_device *)dev;
8673 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008674 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008675 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008676 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308677 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008678 bool is_usb_dev = audio_is_usb_in_device(devices);
8679 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8680 devices,
8681 flags,
8682 source);
Andy Hung94320602018-10-29 18:31:12 -07008683 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8684 " sample_rate %u, channel_mask %#x, format %#x",
8685 __func__, flags, is_usb_dev, may_use_hifi_record,
8686 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308687
kunleizdff872d2018-08-20 14:40:33 +08008688 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008689 is_usb_dev = false;
8690 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8691 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8692 __func__, devices);
8693 }
8694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008695 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008696
8697 if (!(is_usb_dev && may_use_hifi_record)) {
8698 if (config->sample_rate == 0)
8699 config->sample_rate = 48000;
8700 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8701 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8702 if (config->format == AUDIO_FORMAT_DEFAULT)
8703 config->format = AUDIO_FORMAT_PCM_16_BIT;
8704
8705 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8706
Aalique Grahame22e49102018-12-18 14:23:57 -08008707 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8708 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008709 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008711
Rahul Sharma99770982019-03-06 17:05:26 +05308712 pthread_mutex_lock(&adev->lock);
8713 if (in_get_stream(adev, handle) != NULL) {
8714 ALOGW("%s, input stream already opened", __func__);
8715 ret = -EEXIST;
8716 }
8717 pthread_mutex_unlock(&adev->lock);
8718 if (ret)
8719 return ret;
8720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008721 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008722
8723 if (!in) {
8724 ALOGE("failed to allocate input stream");
8725 return -ENOMEM;
8726 }
8727
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308728 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308729 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8730 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008731 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008732 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008734 in->stream.common.get_sample_rate = in_get_sample_rate;
8735 in->stream.common.set_sample_rate = in_set_sample_rate;
8736 in->stream.common.get_buffer_size = in_get_buffer_size;
8737 in->stream.common.get_channels = in_get_channels;
8738 in->stream.common.get_format = in_get_format;
8739 in->stream.common.set_format = in_set_format;
8740 in->stream.common.standby = in_standby;
8741 in->stream.common.dump = in_dump;
8742 in->stream.common.set_parameters = in_set_parameters;
8743 in->stream.common.get_parameters = in_get_parameters;
8744 in->stream.common.add_audio_effect = in_add_audio_effect;
8745 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8746 in->stream.set_gain = in_set_gain;
8747 in->stream.read = in_read;
8748 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008749 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308750 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008751 in->stream.set_microphone_direction = in_set_microphone_direction;
8752 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008753 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008754
8755 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008756 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008757 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008758 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008759 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008760 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008761 in->bit_width = 16;
8762 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008763 in->direction = MIC_DIRECTION_UNSPECIFIED;
8764 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008765 list_init(&in->aec_list);
8766 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008767
Andy Hung94320602018-10-29 18:31:12 -07008768 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008769 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8770 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8771 /* Force channel config requested to mono if incall
8772 record is being requested for only uplink/downlink */
8773 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8774 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8775 ret = -EINVAL;
8776 goto err_open;
8777 }
8778 }
8779
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008780 if (is_usb_dev && may_use_hifi_record) {
8781 /* HiFi record selects an appropriate format, channel, rate combo
8782 depending on sink capabilities*/
8783 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8784 &config->format,
8785 &in->supported_formats[0],
8786 MAX_SUPPORTED_FORMATS,
8787 &config->channel_mask,
8788 &in->supported_channel_masks[0],
8789 MAX_SUPPORTED_CHANNEL_MASKS,
8790 &config->sample_rate,
8791 &in->supported_sample_rates[0],
8792 MAX_SUPPORTED_SAMPLE_RATES);
8793 if (ret != 0) {
8794 ret = -EINVAL;
8795 goto err_open;
8796 }
8797 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008798 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308799 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308800 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8801 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8802 in->config.format = PCM_FORMAT_S32_LE;
8803 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308804 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8805 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8806 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8807 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8808 bool ret_error = false;
8809 in->bit_width = 24;
8810 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8811 from HAL is 24_packed and 8_24
8812 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8813 24_packed return error indicating supported format is 24_packed
8814 *> In case of any other source requesting 24 bit or float return error
8815 indicating format supported is 16 bit only.
8816
8817 on error flinger will retry with supported format passed
8818 */
8819 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8820 (source != AUDIO_SOURCE_CAMCORDER)) {
8821 config->format = AUDIO_FORMAT_PCM_16_BIT;
8822 if (config->sample_rate > 48000)
8823 config->sample_rate = 48000;
8824 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008825 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8826 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308827 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8828 ret_error = true;
8829 }
8830
8831 if (ret_error) {
8832 ret = -EINVAL;
8833 goto err_open;
8834 }
8835 }
8836
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008837 in->channel_mask = config->channel_mask;
8838 in->format = config->format;
8839
8840 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308841
8842 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8843 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8844 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8845 else {
8846 ret = -EINVAL;
8847 goto err_open;
8848 }
8849 }
8850
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008851 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308852 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8853 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008854 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8855 is_low_latency = true;
8856#if LOW_LATENCY_CAPTURE_USE_CASE
8857 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8858#endif
8859 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008860 if (!in->realtime) {
8861 in->config = pcm_config_audio_capture;
8862 frame_size = audio_stream_in_frame_size(&in->stream);
8863 buffer_size = get_input_buffer_size(config->sample_rate,
8864 config->format,
8865 channel_count,
8866 is_low_latency);
8867 in->config.period_size = buffer_size / frame_size;
8868 in->config.rate = config->sample_rate;
8869 in->af_period_multiplier = 1;
8870 } else {
8871 // period size is left untouched for rt mode playback
8872 in->config = pcm_config_audio_capture_rt;
8873 in->af_period_multiplier = af_period_multiplier;
8874 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008875 }
8876
8877 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8878 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8879 in->realtime = 0;
8880 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8881 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008882 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008883 in->stream.start = in_start;
8884 in->stream.stop = in_stop;
8885 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8886 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008887 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8888 } else if (in->realtime) {
8889 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008890 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008891 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008892 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008893 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8894 in->config = pcm_config_audio_capture;
8895 frame_size = audio_stream_in_frame_size(&in->stream);
8896 buffer_size = get_input_buffer_size(config->sample_rate,
8897 config->format,
8898 channel_count,
8899 false /*is_low_latency*/);
8900 in->config.period_size = buffer_size / frame_size;
8901 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008902 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008903 switch (config->format) {
8904 case AUDIO_FORMAT_PCM_32_BIT:
8905 in->bit_width = 32;
8906 break;
8907 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8908 case AUDIO_FORMAT_PCM_8_24_BIT:
8909 in->bit_width = 24;
8910 break;
8911 default:
8912 in->bit_width = 16;
8913 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008914 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308915 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008916 if (config->sample_rate == 0)
8917 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8918 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8919 config->sample_rate != 8000) {
8920 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8921 ret = -EINVAL;
8922 goto err_open;
8923 }
8924 if (config->format == AUDIO_FORMAT_DEFAULT)
8925 config->format = AUDIO_FORMAT_PCM_16_BIT;
8926 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8927 config->format = AUDIO_FORMAT_PCM_16_BIT;
8928 ret = -EINVAL;
8929 goto err_open;
8930 }
8931
8932 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8933 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008934 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008935 in->af_period_multiplier = 1;
8936 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8937 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8938 (config->sample_rate == 8000 ||
8939 config->sample_rate == 16000 ||
8940 config->sample_rate == 32000 ||
8941 config->sample_rate == 48000) &&
8942 channel_count == 1) {
8943 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8944 in->config = pcm_config_audio_capture;
8945 frame_size = audio_stream_in_frame_size(&in->stream);
8946 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8947 config->sample_rate,
8948 config->format,
8949 channel_count, false /*is_low_latency*/);
8950 in->config.period_size = buffer_size / frame_size;
8951 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8952 in->config.rate = config->sample_rate;
8953 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008954 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308955 int ret_val;
8956 pthread_mutex_lock(&adev->lock);
8957 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8958 in, config, &channel_mask_updated);
8959 pthread_mutex_unlock(&adev->lock);
8960
8961 if (!ret_val) {
8962 if (channel_mask_updated == true) {
8963 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8964 __func__, config->channel_mask);
8965 ret = -EINVAL;
8966 goto err_open;
8967 }
8968 ALOGD("%s: created multi-channel session succesfully",__func__);
8969 } else if (audio_extn_compr_cap_enabled() &&
8970 audio_extn_compr_cap_format_supported(config->format) &&
8971 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8972 audio_extn_compr_cap_init(in);
8973 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05308974 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308975 if (ret)
8976 goto err_open;
8977 } else {
8978 in->config = pcm_config_audio_capture;
8979 in->config.rate = config->sample_rate;
8980 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308981 in->format = config->format;
8982 frame_size = audio_stream_in_frame_size(&in->stream);
8983 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008984 config->format,
8985 channel_count,
8986 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008987 /* prevent division-by-zero */
8988 if (frame_size == 0) {
8989 ALOGE("%s: Error frame_size==0", __func__);
8990 ret = -EINVAL;
8991 goto err_open;
8992 }
8993
Revathi Uddarajud2634032017-12-07 14:42:34 +05308994 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008995 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008996
Revathi Uddarajud2634032017-12-07 14:42:34 +05308997 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8998 /* optionally use VOIP usecase depending on config(s) */
8999 ret = adev_update_voice_comm_input_stream(in, config);
9000 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009001
Revathi Uddarajud2634032017-12-07 14:42:34 +05309002 if (ret) {
9003 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9004 goto err_open;
9005 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009006 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309007 if (audio_extn_is_concurrent_capture_enabled()) {
9008 /* Acquire lock to avoid two concurrent use cases initialized to
9009 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009010
Samyak Jainc37062f2019-04-25 18:41:06 +05309011 if (in->usecase == USECASE_AUDIO_RECORD) {
9012 pthread_mutex_lock(&adev->lock);
9013 if (!(adev->pcm_record_uc_state)) {
9014 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9015 adev->pcm_record_uc_state = 1;
9016 pthread_mutex_unlock(&adev->lock);
9017 } else {
9018 pthread_mutex_unlock(&adev->lock);
9019 /* Assign compress record use case for second record */
9020 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9021 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9022 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9023 if (audio_extn_cin_applicable_stream(in)) {
9024 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309025 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309026 if (ret)
9027 goto err_open;
9028 }
9029 }
9030 }
kunleiz28c73e72019-03-27 17:24:04 +08009031 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009032 }
Ramjee Singh8b09cc12019-08-21 16:31:33 +05309033 if (audio_extn_ssr_get_stream() != in)
9034 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009035
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009036 in->sample_rate = in->config.rate;
9037
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309038 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9039 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009040 devices, flags, in->format,
9041 in->sample_rate, in->bit_width,
9042 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309043 register_format(in->format, in->supported_formats);
9044 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9045 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309046
Aalique Grahame22e49102018-12-18 14:23:57 -08009047 in->error_log = error_log_create(
9048 ERROR_LOG_ENTRIES,
9049 1000000000 /* aggregate consecutive identical errors within one second */);
9050
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009051 /* This stream could be for sound trigger lab,
9052 get sound trigger pcm if present */
9053 audio_extn_sound_trigger_check_and_get_session(in);
9054
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309055 lock_input_stream(in);
9056 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9057 pthread_mutex_lock(&adev->lock);
9058 in->card_status = adev->card_status;
9059 pthread_mutex_unlock(&adev->lock);
9060 pthread_mutex_unlock(&in->lock);
9061
Aalique Grahame22e49102018-12-18 14:23:57 -08009062 stream_app_type_cfg_init(&in->app_type_cfg);
9063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009064 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009065
9066 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9067 calloc(1, sizeof(streams_input_ctxt_t));
9068 if (in_ctxt == NULL) {
9069 ALOGE("%s fail to allocate input ctxt", __func__);
9070 ret = -ENOMEM;
9071 goto err_open;
9072 }
9073 in_ctxt->input = in;
9074
9075 pthread_mutex_lock(&adev->lock);
9076 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9077 pthread_mutex_unlock(&adev->lock);
9078
Eric Laurent994a6932013-07-17 11:51:42 -07009079 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009080 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009081
9082err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309083 if (in->usecase == USECASE_AUDIO_RECORD) {
9084 pthread_mutex_lock(&adev->lock);
9085 adev->pcm_record_uc_state = 0;
9086 pthread_mutex_unlock(&adev->lock);
9087 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009088 free(in);
9089 *stream_in = NULL;
9090 return ret;
9091}
9092
9093static void adev_close_input_stream(struct audio_hw_device *dev,
9094 struct audio_stream_in *stream)
9095{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009096 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009097 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009098 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309099
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309100 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009101
kunleiz70e57612018-12-28 17:50:23 +08009102 /* must deregister from sndmonitor first to prevent races
9103 * between the callback and close_stream
9104 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309105 audio_extn_snd_mon_unregister_listener(stream);
9106
kunleiz70e57612018-12-28 17:50:23 +08009107 /* Disable echo reference if there are no active input, hfp call
9108 * and sound trigger while closing input stream
9109 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009110 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009111 !audio_extn_hfp_is_active(adev) &&
9112 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009113 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009114 else
9115 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309116
Pallavid7c7a272018-01-16 11:22:55 +05309117 if (in == NULL) {
9118 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9119 return;
9120 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009121 error_log_destroy(in->error_log);
9122 in->error_log = NULL;
9123
Pallavid7c7a272018-01-16 11:22:55 +05309124
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009125 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309126 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009127 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309128 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009129 if (ret != 0)
9130 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9131 __func__, ret);
9132 } else
9133 in_standby(&stream->common);
9134
Revathi Uddarajud2634032017-12-07 14:42:34 +05309135 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309136 if (in->usecase == USECASE_AUDIO_RECORD) {
9137 adev->pcm_record_uc_state = 0;
9138 }
9139
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009140 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009141 audio_extn_ssr_deinit();
9142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009143
Garmond Leunge2433c32017-09-28 21:51:22 -07009144 if (audio_extn_ffv_get_stream() == in) {
9145 audio_extn_ffv_stream_deinit();
9146 }
9147
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309148 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009149 audio_extn_compr_cap_format_supported(in->config.format))
9150 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309151
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309152 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309153 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009154
Mingming Yinfd7607b2016-01-22 12:48:44 -08009155 if (in->is_st_session) {
9156 ALOGV("%s: sound trigger pcm stop lab", __func__);
9157 audio_extn_sound_trigger_stop_lab(in);
9158 }
Derek Chenf939fb72018-11-13 13:34:41 -08009159 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9160 if (in_ctxt != NULL) {
9161 list_remove(&in_ctxt->list);
9162 free(in_ctxt);
9163 } else {
9164 ALOGW("%s, input stream already closed", __func__);
9165 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009166 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309167 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009168 return;
9169}
9170
Aalique Grahame22e49102018-12-18 14:23:57 -08009171/* verifies input and output devices and their capabilities.
9172 *
9173 * This verification is required when enabling extended bit-depth or
9174 * sampling rates, as not all qcom products support it.
9175 *
9176 * Suitable for calling only on initialization such as adev_open().
9177 * It fills the audio_device use_case_table[] array.
9178 *
9179 * Has a side-effect that it needs to configure audio routing / devices
9180 * in order to power up the devices and read the device parameters.
9181 * It does not acquire any hw device lock. Should restore the devices
9182 * back to "normal state" upon completion.
9183 */
9184static int adev_verify_devices(struct audio_device *adev)
9185{
9186 /* enumeration is a bit difficult because one really wants to pull
9187 * the use_case, device id, etc from the hidden pcm_device_table[].
9188 * In this case there are the following use cases and device ids.
9189 *
9190 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9191 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9192 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9193 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9194 * [USECASE_AUDIO_RECORD] = {0, 0},
9195 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9196 * [USECASE_VOICE_CALL] = {2, 2},
9197 *
9198 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9199 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9200 */
9201
9202 /* should be the usecases enabled in adev_open_input_stream() */
9203 static const int test_in_usecases[] = {
9204 USECASE_AUDIO_RECORD,
9205 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9206 };
9207 /* should be the usecases enabled in adev_open_output_stream()*/
9208 static const int test_out_usecases[] = {
9209 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9210 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9211 };
9212 static const usecase_type_t usecase_type_by_dir[] = {
9213 PCM_PLAYBACK,
9214 PCM_CAPTURE,
9215 };
9216 static const unsigned flags_by_dir[] = {
9217 PCM_OUT,
9218 PCM_IN,
9219 };
9220
9221 size_t i;
9222 unsigned dir;
9223 const unsigned card_id = adev->snd_card;
9224
9225 for (dir = 0; dir < 2; ++dir) {
9226 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9227 const unsigned flags_dir = flags_by_dir[dir];
9228 const size_t testsize =
9229 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9230 const int *testcases =
9231 dir ? test_in_usecases : test_out_usecases;
9232 const audio_devices_t audio_device =
9233 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9234
9235 for (i = 0; i < testsize; ++i) {
9236 const audio_usecase_t audio_usecase = testcases[i];
9237 int device_id;
9238 struct pcm_params **pparams;
9239 struct stream_out out;
9240 struct stream_in in;
9241 struct audio_usecase uc_info;
9242 int retval;
9243
9244 pparams = &adev->use_case_table[audio_usecase];
9245 pcm_params_free(*pparams); /* can accept null input */
9246 *pparams = NULL;
9247
9248 /* find the device ID for the use case (signed, for error) */
9249 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9250 if (device_id < 0)
9251 continue;
9252
9253 /* prepare structures for device probing */
9254 memset(&uc_info, 0, sizeof(uc_info));
9255 uc_info.id = audio_usecase;
9256 uc_info.type = usecase_type;
9257 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009258 memset(&in, 0, sizeof(in));
9259 in.device = audio_device;
9260 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9261 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009262 }
9263 memset(&out, 0, sizeof(out));
9264 out.devices = audio_device; /* only field needed in select_devices */
9265 uc_info.stream.out = &out;
9266 uc_info.devices = audio_device;
9267 uc_info.in_snd_device = SND_DEVICE_NONE;
9268 uc_info.out_snd_device = SND_DEVICE_NONE;
9269 list_add_tail(&adev->usecase_list, &uc_info.list);
9270
9271 /* select device - similar to start_(in/out)put_stream() */
9272 retval = select_devices(adev, audio_usecase);
9273 if (retval >= 0) {
9274 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9275#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009276 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009277 if (*pparams) {
9278 ALOGV("%s: (%s) card %d device %d", __func__,
9279 dir ? "input" : "output", card_id, device_id);
9280 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9281 } else {
9282 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9283 }
9284#endif
9285 }
9286
9287 /* deselect device - similar to stop_(in/out)put_stream() */
9288 /* 1. Get and set stream specific mixer controls */
9289 retval = disable_audio_route(adev, &uc_info);
9290 /* 2. Disable the rx device */
9291 retval = disable_snd_device(adev,
9292 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9293 list_remove(&uc_info.list);
9294 }
9295 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009296 return 0;
9297}
9298
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309299int adev_create_audio_patch(struct audio_hw_device *dev,
9300 unsigned int num_sources,
9301 const struct audio_port_config *sources,
9302 unsigned int num_sinks,
9303 const struct audio_port_config *sinks,
9304 audio_patch_handle_t *handle)
9305{
Derek Chenf939fb72018-11-13 13:34:41 -08009306 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309307
Derek Chenf939fb72018-11-13 13:34:41 -08009308 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9309 num_sources,
9310 sources,
9311 num_sinks,
9312 sinks,
9313 handle);
9314 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9315 num_sources,
9316 sources,
9317 num_sinks,
9318 sinks,
9319 handle);
9320 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309321}
9322
9323int adev_release_audio_patch(struct audio_hw_device *dev,
9324 audio_patch_handle_t handle)
9325{
Derek Chenf939fb72018-11-13 13:34:41 -08009326 int ret;
9327
9328 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9329 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9330 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309331}
9332
9333int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9334{
Derek Chenf13dd492018-11-13 14:53:51 -08009335 int ret = 0;
9336
9337 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9338 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9339 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309340}
9341
9342int adev_set_audio_port_config(struct audio_hw_device *dev,
9343 const struct audio_port_config *config)
9344{
Derek Chenf13dd492018-11-13 14:53:51 -08009345 int ret = 0;
9346
9347 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9348 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9349 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309350}
9351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009352static int adev_dump(const audio_hw_device_t *device __unused,
9353 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009354{
9355 return 0;
9356}
9357
9358static int adev_close(hw_device_t *device)
9359{
Aalique Grahame22e49102018-12-18 14:23:57 -08009360 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309361 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009362
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309363 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009364 return 0;
9365
9366 pthread_mutex_lock(&adev_init_lock);
9367
9368 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309369 if (audio_extn_spkr_prot_is_enabled())
9370 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309371 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009372 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009373 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009374 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009375 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309376 audio_extn_utils_release_streams_cfg_lists(
9377 &adev->streams_output_cfg_list,
9378 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309379 if (audio_extn_qap_is_enabled())
9380 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309381 if (audio_extn_qaf_is_enabled())
9382 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009383 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009384 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009385 free(adev->snd_dev_ref_cnt);
9386 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009387 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9388 pcm_params_free(adev->use_case_table[i]);
9389 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009390 if (adev->adm_deinit)
9391 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309392 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009393 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309394 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309395 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009396 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309397 if (adev->device_cfg_params) {
9398 free(adev->device_cfg_params);
9399 adev->device_cfg_params = NULL;
9400 }
Derek Chend2530072014-11-24 12:39:14 -08009401 if(adev->ext_hw_plugin)
9402 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009403 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009404 free(device);
9405 adev = NULL;
9406 }
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009407
9408 us_deinit();
9409
Kiran Kandi910e1862013-10-29 13:29:42 -07009410 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309411 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009412 return 0;
9413}
9414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009415/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9416 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9417 * just that it _might_ work.
9418 */
9419static int period_size_is_plausible_for_low_latency(int period_size)
9420{
9421 switch (period_size) {
9422 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009423 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009424 case 240:
9425 case 320:
9426 case 480:
9427 return 1;
9428 default:
9429 return 0;
9430 }
9431}
9432
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309433static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9434{
9435 bool is_snd_card_status = false;
9436 bool is_ext_device_status = false;
9437 char value[32];
9438 int card = -1;
9439 card_status_t status;
9440
9441 if (cookie != adev || !parms)
9442 return;
9443
9444 if (!parse_snd_card_status(parms, &card, &status)) {
9445 is_snd_card_status = true;
9446 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9447 is_ext_device_status = true;
9448 } else {
9449 // not a valid event
9450 return;
9451 }
9452
9453 pthread_mutex_lock(&adev->lock);
9454 if (card == adev->snd_card || is_ext_device_status) {
9455 if (is_snd_card_status && adev->card_status != status) {
9456 adev->card_status = status;
9457 platform_snd_card_update(adev->platform, status);
9458 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009459 audio_extn_auto_hal_set_parameters(adev, parms);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309460 } else if (is_ext_device_status) {
9461 platform_set_parameters(adev->platform, parms);
9462 }
9463 }
9464 pthread_mutex_unlock(&adev->lock);
9465 return;
9466}
9467
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309468/* out and adev lock held */
9469static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9470{
9471 struct audio_usecase *uc_info;
9472 float left_p;
9473 float right_p;
9474 audio_devices_t devices;
9475
9476 uc_info = get_usecase_from_list(adev, out->usecase);
9477 if (uc_info == NULL) {
9478 ALOGE("%s: Could not find the usecase (%d) in the list",
9479 __func__, out->usecase);
9480 return -EINVAL;
9481 }
9482
9483 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9484 out->usecase, use_case_table[out->usecase]);
9485
9486 if (restore) {
9487 // restore A2DP device for active usecases and unmute if required
9488 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9489 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9490 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9491 select_devices(adev, uc_info->id);
9492 pthread_mutex_lock(&out->compr_mute_lock);
9493 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05309494 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309495 out->a2dp_compress_mute = false;
9496 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9497 }
9498 pthread_mutex_unlock(&out->compr_mute_lock);
9499 }
9500 } else {
9501 // mute compress stream if suspended
9502 pthread_mutex_lock(&out->compr_mute_lock);
9503 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9504 (!out->a2dp_compress_mute)) {
9505 if (!out->standby) {
9506 ALOGD("%s: selecting speaker and muting stream", __func__);
9507 devices = out->devices;
9508 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9509 left_p = out->volume_l;
9510 right_p = out->volume_r;
9511 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9512 compress_pause(out->compr);
9513 out_set_compr_volume(&out->stream, (float)0, (float)0);
9514 out->a2dp_compress_mute = true;
9515 select_devices(adev, out->usecase);
9516 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9517 compress_resume(out->compr);
9518 out->devices = devices;
9519 out->volume_l = left_p;
9520 out->volume_r = right_p;
9521 }
9522 }
9523 pthread_mutex_unlock(&out->compr_mute_lock);
9524 }
9525 ALOGV("%s: exit", __func__);
9526 return 0;
9527}
9528
9529int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9530{
9531 int ret = 0;
9532
9533 lock_output_stream(out);
9534 pthread_mutex_lock(&adev->lock);
9535
9536 ret = check_a2dp_restore_l(adev, out, restore);
9537
9538 pthread_mutex_unlock(&adev->lock);
9539 pthread_mutex_unlock(&out->lock);
9540 return ret;
9541}
9542
Haynes Mathew George01156f92018-04-13 15:29:54 -07009543void adev_on_battery_status_changed(bool charging)
9544{
9545 pthread_mutex_lock(&adev->lock);
9546 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9547 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009548 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009549 pthread_mutex_unlock(&adev->lock);
9550}
9551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009552static int adev_open(const hw_module_t *module, const char *name,
9553 hw_device_t **device)
9554{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309555 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009556 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309557 char mixer_ctl_name[128] = {0};
9558 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309559
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009560 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009561 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9562
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009563 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009564 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009565 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009566 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009567 ALOGD("%s: returning existing instance of adev", __func__);
9568 ALOGD("%s: exit", __func__);
9569 pthread_mutex_unlock(&adev_init_lock);
9570 return 0;
9571 }
9572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009573 adev = calloc(1, sizeof(struct audio_device));
9574
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009575 if (!adev) {
9576 pthread_mutex_unlock(&adev_init_lock);
9577 return -ENOMEM;
9578 }
9579
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009580 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9581
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009582 // register audio ext hidl at the earliest
9583 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309584#ifdef DYNAMIC_LOG_ENABLED
9585 register_for_dynamic_logging("hal");
9586#endif
9587
Derek Chenf939fb72018-11-13 13:34:41 -08009588 /* default audio HAL major version */
9589 uint32_t maj_version = 2;
9590 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9591 maj_version = atoi(value);
9592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009593 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009594 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009595 adev->device.common.module = (struct hw_module_t *)module;
9596 adev->device.common.close = adev_close;
9597
9598 adev->device.init_check = adev_init_check;
9599 adev->device.set_voice_volume = adev_set_voice_volume;
9600 adev->device.set_master_volume = adev_set_master_volume;
9601 adev->device.get_master_volume = adev_get_master_volume;
9602 adev->device.set_master_mute = adev_set_master_mute;
9603 adev->device.get_master_mute = adev_get_master_mute;
9604 adev->device.set_mode = adev_set_mode;
9605 adev->device.set_mic_mute = adev_set_mic_mute;
9606 adev->device.get_mic_mute = adev_get_mic_mute;
9607 adev->device.set_parameters = adev_set_parameters;
9608 adev->device.get_parameters = adev_get_parameters;
9609 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9610 adev->device.open_output_stream = adev_open_output_stream;
9611 adev->device.close_output_stream = adev_close_output_stream;
9612 adev->device.open_input_stream = adev_open_input_stream;
9613 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309614 adev->device.create_audio_patch = adev_create_audio_patch;
9615 adev->device.release_audio_patch = adev_release_audio_patch;
9616 adev->device.get_audio_port = adev_get_audio_port;
9617 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009618 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309619 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009620
9621 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009622 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009623 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009624 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009625 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009626 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009627 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309628 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009629 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009630 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009631 /* Init audio and voice feature */
9632 audio_extn_feature_init();
9633 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009634 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009635 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009636 list_init(&adev->active_inputs_list);
9637 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +05309638 list_init(&adev->audio_patch_record_list);
9639 adev->audio_patch_index = 0;
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009640 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009641 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309642 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309643 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309644 adev->perf_lock_opts[0] = 0x101;
9645 adev->perf_lock_opts[1] = 0x20E;
9646 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009647 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009648 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309649 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009650 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009652 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009653 adev->platform = platform_init(adev);
9654 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009655 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009656 free(adev->snd_dev_ref_cnt);
9657 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009658 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009659 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9660 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009661 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009662 return -EINVAL;
9663 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009664
Aalique Grahame22e49102018-12-18 14:23:57 -08009665 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309666 if (audio_extn_qap_is_enabled()) {
9667 ret = audio_extn_qap_init(adev);
9668 if (ret < 0) {
9669 pthread_mutex_destroy(&adev->lock);
9670 free(adev);
9671 adev = NULL;
9672 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9673 *device = NULL;
9674 pthread_mutex_unlock(&adev_init_lock);
9675 return ret;
9676 }
9677 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
9678 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
9679 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009680
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309681 if (audio_extn_qaf_is_enabled()) {
9682 ret = audio_extn_qaf_init(adev);
9683 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009684 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309685 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009686 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309687 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9688 *device = NULL;
9689 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309690 return ret;
9691 }
9692
9693 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9694 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9695 }
9696
Derek Chenae7b0342019-02-08 15:17:04 -08009697 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009698 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9699
Eric Laurentc4aef752013-09-12 17:45:53 -07009700 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9701 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9702 if (adev->visualizer_lib == NULL) {
9703 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9704 } else {
9705 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9706 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009707 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009708 "visualizer_hal_start_output");
9709 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009710 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009711 "visualizer_hal_stop_output");
9712 }
9713 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309714 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009715 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009716 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009717 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309718 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009719 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009720
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009721 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9722 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9723 if (adev->offload_effects_lib == NULL) {
9724 ALOGE("%s: DLOPEN failed for %s", __func__,
9725 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9726 } else {
9727 ALOGV("%s: DLOPEN successful for %s", __func__,
9728 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9729 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309730 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009731 "offload_effects_bundle_hal_start_output");
9732 adev->offload_effects_stop_output =
9733 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9734 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009735 adev->offload_effects_set_hpx_state =
9736 (int (*)(bool))dlsym(adev->offload_effects_lib,
9737 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309738 adev->offload_effects_get_parameters =
9739 (void (*)(struct str_parms *, struct str_parms *))
9740 dlsym(adev->offload_effects_lib,
9741 "offload_effects_bundle_get_parameters");
9742 adev->offload_effects_set_parameters =
9743 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9744 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009745 }
9746 }
9747
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009748 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9749 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9750 if (adev->adm_lib == NULL) {
9751 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9752 } else {
9753 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9754 adev->adm_init = (adm_init_t)
9755 dlsym(adev->adm_lib, "adm_init");
9756 adev->adm_deinit = (adm_deinit_t)
9757 dlsym(adev->adm_lib, "adm_deinit");
9758 adev->adm_register_input_stream = (adm_register_input_stream_t)
9759 dlsym(adev->adm_lib, "adm_register_input_stream");
9760 adev->adm_register_output_stream = (adm_register_output_stream_t)
9761 dlsym(adev->adm_lib, "adm_register_output_stream");
9762 adev->adm_deregister_stream = (adm_deregister_stream_t)
9763 dlsym(adev->adm_lib, "adm_deregister_stream");
9764 adev->adm_request_focus = (adm_request_focus_t)
9765 dlsym(adev->adm_lib, "adm_request_focus");
9766 adev->adm_abandon_focus = (adm_abandon_focus_t)
9767 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009768 adev->adm_set_config = (adm_set_config_t)
9769 dlsym(adev->adm_lib, "adm_set_config");
9770 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9771 dlsym(adev->adm_lib, "adm_request_focus_v2");
9772 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9773 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9774 adev->adm_on_routing_change = (adm_on_routing_change_t)
9775 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009776 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9777 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009778 }
9779 }
9780
Aalique Grahame22e49102018-12-18 14:23:57 -08009781 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009782 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009783 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009784 //initialize this to false for now,
9785 //this will be set to true through set param
9786 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009787
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009788 audio_extn_ds2_enable(adev);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009789
9790 us_init(adev);
9791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009792 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009793
9794 if (k_enable_extended_precision)
9795 adev_verify_devices(adev);
9796
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009797 adev->dsp_bit_width_enforce_mode =
9798 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009799
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309800 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9801 &adev->streams_output_cfg_list,
9802 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009803
Kiran Kandi910e1862013-10-29 13:29:42 -07009804 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009805
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009806 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009807 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9808 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009809 trial = atoi(value);
9810 if (period_size_is_plausible_for_low_latency(trial)) {
9811 pcm_config_low_latency.period_size = trial;
9812 pcm_config_low_latency.start_threshold = trial / 4;
9813 pcm_config_low_latency.avail_min = trial / 4;
9814 configured_low_latency_capture_period_size = trial;
9815 }
9816 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009817 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9818 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009819 trial = atoi(value);
9820 if (period_size_is_plausible_for_low_latency(trial)) {
9821 configured_low_latency_capture_period_size = trial;
9822 }
9823 }
9824
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009825 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9826
Eric Laurent4b084132018-10-19 17:33:43 -07009827 adev->camera_orientation = CAMERA_DEFAULT;
9828
Aalique Grahame22e49102018-12-18 14:23:57 -08009829 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9830 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009831 af_period_multiplier = atoi(value);
9832 if (af_period_multiplier < 0)
9833 af_period_multiplier = 2;
9834 else if (af_period_multiplier > 4)
9835 af_period_multiplier = 4;
9836
9837 ALOGV("new period_multiplier = %d", af_period_multiplier);
9838 }
9839
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009840 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009841
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009842 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009843 pthread_mutex_unlock(&adev_init_lock);
9844
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009845 if (adev->adm_init)
9846 adev->adm_data = adev->adm_init();
9847
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309848 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309849 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009850 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309851
9852 audio_extn_snd_mon_init();
9853 pthread_mutex_lock(&adev->lock);
9854 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9855 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009856 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9857 /*
9858 * if the battery state callback happens before charging can be queried,
9859 * it will be guarded with the adev->lock held in the cb function and so
9860 * the callback value will reflect the latest state
9861 */
9862 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309863 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009864 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009865 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009866 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309867 /* Allocate memory for Device config params */
9868 adev->device_cfg_params = (struct audio_device_config_param*)
9869 calloc(platform_get_max_codec_backend(),
9870 sizeof(struct audio_device_config_param));
9871 if (adev->device_cfg_params == NULL)
9872 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309873
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309874 /*
9875 * Check if new PSPD matrix mixer control is supported. If not
9876 * supported, then set flag so that old mixer ctrl is sent while
9877 * sending pspd coefficients on older kernel version. Query mixer
9878 * control for default pcm id and channel value one.
9879 */
9880 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9881 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9882
9883 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9884 if (!ctl) {
9885 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9886 __func__, mixer_ctl_name);
9887 adev->use_old_pspd_mix_ctrl = true;
9888 }
9889
Eric Laurent994a6932013-07-17 11:51:42 -07009890 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009891 return 0;
9892}
9893
9894static struct hw_module_methods_t hal_module_methods = {
9895 .open = adev_open,
9896};
9897
9898struct audio_module HAL_MODULE_INFO_SYM = {
9899 .common = {
9900 .tag = HARDWARE_MODULE_TAG,
9901 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9902 .hal_api_version = HARDWARE_HAL_API_VERSION,
9903 .id = AUDIO_HARDWARE_MODULE_ID,
9904 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009905 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009906 .methods = &hal_module_methods,
9907 },
9908};