blob: 59d1888270a07a18c5768cfdcd59c650489acf79 [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"
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +053078#include "audio_amplifier.h"
Balázs Triszkaa68afd52017-05-11 03:19:29 +020079#include "ultrasound.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080080
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070081#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080082#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080083
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053084#ifdef DYNAMIC_LOG_ENABLED
85#include <log_xml_parser.h>
86#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
87#include <log_utils.h>
88#endif
89
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053091/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
92#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070093#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070094#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070095#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053096#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053097#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070098#define INVALID_OUT_VOLUME -1
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700331 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
332 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700334 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700335 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700343 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
344 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700345 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800346 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700347
Eric Laurentb23d5282013-05-14 15:27:20 -0700348 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700349 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530350 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
351 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
352 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530353 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
354 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700356 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700358 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700359
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800360 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800361 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700363
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700364 [USECASE_VOICE2_CALL] = "voice2-call",
365 [USECASE_VOLTE_CALL] = "volte-call",
366 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800367 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800368 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
369 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800370 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700371 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
372 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
373 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800374 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
375 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
376 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
377
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700378 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
379 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700380 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
381 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700382
383 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
384 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530385 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700386
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530387 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530388 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
389 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700390
391 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
392 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530393 /* For Interactive Audio Streams */
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700402
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800403 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
404
Derek Chenf6318be2017-06-12 17:16:24 -0400405 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
406
407 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
408 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
409 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
410 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530411 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Balázs Triszkaa68afd52017-05-11 03:19:29 +0200412
413 /* For Elliptic Ultrasound proximity sensor */
414 [USECASE_AUDIO_ULTRASOUND_RX] = "ultrasound-rx",
415 [USECASE_AUDIO_ULTRASOUND_TX] = "ultrasound-tx",
Eric Laurentb23d5282013-05-14 15:27:20 -0700416};
417
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700418static const audio_usecase_t offload_usecases[] = {
419 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429
Varun Balaraje49253e2017-07-06 19:48:56 +0530430static const audio_usecase_t interactive_usecases[] = {
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
439};
440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441#define STRING_TO_ENUM(string) { #string, string }
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443struct string_to_enum {
444 const char *name;
445 uint32_t value;
446};
447
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700448static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
458 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800468};
469
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700470static const struct string_to_enum formats_name_to_enum_table[] = {
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
472 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700474 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
475 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
476 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700477 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800478 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
479 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700480 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800481};
482
483//list of all supported sample rates by HDMI specification.
484static const int out_hdmi_sample_rates[] = {
485 32000, 44100, 48000, 88200, 96000, 176400, 192000,
486};
487
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700488static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800489 STRING_TO_ENUM(32000),
490 STRING_TO_ENUM(44100),
491 STRING_TO_ENUM(48000),
492 STRING_TO_ENUM(88200),
493 STRING_TO_ENUM(96000),
494 STRING_TO_ENUM(176400),
495 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700496};
497
Carter Hsu2e429db2019-05-14 18:50:52 +0800498struct in_effect_list {
499 struct listnode list;
500 effect_handle_t handle;
501};
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700504static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700505static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700506//cache last MBDRC cal step level
507static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700508
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530509static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
510static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700511static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800512static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530513static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530514
Derek Chen6f293672019-04-01 01:40:24 -0700515static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
516static void in_snd_mon_cb(void * stream, struct str_parms * parms);
517static void out_snd_mon_cb(void * stream, struct str_parms * parms);
518
Vatsal Buchac09ae062018-11-14 13:25:08 +0530519#ifdef AUDIO_FEATURE_ENABLED_GCOV
520extern void __gcov_flush();
521static void enable_gcov()
522{
523 __gcov_flush();
524}
525#else
526static void enable_gcov()
527{
528}
529#endif
530
justinweng20fb6d82019-02-21 18:49:00 -0700531static int in_set_microphone_direction(const struct audio_stream_in *stream,
532 audio_microphone_direction_t dir);
533static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
534
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700535static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
536 int flags __unused)
537{
538 int dir = 0;
539 switch (uc_id) {
540 case USECASE_AUDIO_RECORD_LOW_LATENCY:
541 dir = 1;
542 case USECASE_AUDIO_PLAYBACK_ULL:
543 break;
544 default:
545 return false;
546 }
547
548 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
549 PCM_PLAYBACK : PCM_CAPTURE);
550 if (adev->adm_is_noirq_avail)
551 return adev->adm_is_noirq_avail(adev->adm_data,
552 adev->snd_card, dev_id, dir);
553 return false;
554}
555
556static void register_out_stream(struct stream_out *out)
557{
558 struct audio_device *adev = out->dev;
559 if (is_offload_usecase(out->usecase) ||
560 !adev->adm_register_output_stream)
561 return;
562
563 // register stream first for backward compatibility
564 adev->adm_register_output_stream(adev->adm_data,
565 out->handle,
566 out->flags);
567
568 if (!adev->adm_set_config)
569 return;
570
571 if (out->realtime)
572 adev->adm_set_config(adev->adm_data,
573 out->handle,
574 out->pcm, &out->config);
575}
576
577static void register_in_stream(struct stream_in *in)
578{
579 struct audio_device *adev = in->dev;
580 if (!adev->adm_register_input_stream)
581 return;
582
583 adev->adm_register_input_stream(adev->adm_data,
584 in->capture_handle,
585 in->flags);
586
587 if (!adev->adm_set_config)
588 return;
589
590 if (in->realtime)
591 adev->adm_set_config(adev->adm_data,
592 in->capture_handle,
593 in->pcm,
594 &in->config);
595}
596
597static void request_out_focus(struct stream_out *out, long ns)
598{
599 struct audio_device *adev = out->dev;
600
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700601 if (adev->adm_request_focus_v2)
602 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
603 else if (adev->adm_request_focus)
604 adev->adm_request_focus(adev->adm_data, out->handle);
605}
606
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700607static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700608{
609 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700610 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700612 if (adev->adm_request_focus_v2_1)
613 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
614 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700615 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
616 else if (adev->adm_request_focus)
617 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618
619 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700620}
621
622static void release_out_focus(struct stream_out *out)
623{
624 struct audio_device *adev = out->dev;
625
626 if (adev->adm_abandon_focus)
627 adev->adm_abandon_focus(adev->adm_data, out->handle);
628}
629
630static void release_in_focus(struct stream_in *in)
631{
632 struct audio_device *adev = in->dev;
633 if (adev->adm_abandon_focus)
634 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
635}
636
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530637static int parse_snd_card_status(struct str_parms *parms, int *card,
638 card_status_t *status)
639{
640 char value[32]={0};
641 char state[32]={0};
642
643 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
644 if (ret < 0)
645 return -1;
646
647 // sscanf should be okay as value is of max length 32.
648 // same as sizeof state.
649 if (sscanf(value, "%d,%s", card, state) < 2)
650 return -1;
651
652 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
653 CARD_STATUS_OFFLINE;
654 return 0;
655}
656
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700657static inline void adjust_frames_for_device_delay(struct stream_out *out,
658 uint32_t *dsp_frames) {
659 // Adjustment accounts for A2dp encoder latency with offload usecases
660 // Note: Encoder latency is returned in ms.
661 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
662 unsigned long offset =
663 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
664 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
665 }
666}
667
vivek mehtaa76401a2015-04-24 14:12:15 -0700668__attribute__ ((visibility ("default")))
669bool audio_hw_send_gain_dep_calibration(int level) {
670 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700671 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700672
673 pthread_mutex_lock(&adev_init_lock);
674
675 if (adev != NULL && adev->platform != NULL) {
676 pthread_mutex_lock(&adev->lock);
677 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700678
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530679 // cache level info for any of the use case which
680 // was not started.
681 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700682
vivek mehtaa76401a2015-04-24 14:12:15 -0700683 pthread_mutex_unlock(&adev->lock);
684 } else {
685 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
686 }
687
688 pthread_mutex_unlock(&adev_init_lock);
689
690 return ret_val;
691}
692
Ashish Jain5106d362016-05-11 19:23:33 +0530693static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
694{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800695 bool gapless_enabled = false;
696 const char *mixer_ctl_name = "Compress Gapless Playback";
697 struct mixer_ctl *ctl;
698
699 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700700 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530701
702 /*Disable gapless if its AV playback*/
703 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800704
705 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
706 if (!ctl) {
707 ALOGE("%s: Could not get ctl for mixer cmd - %s",
708 __func__, mixer_ctl_name);
709 return -EINVAL;
710 }
711
712 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
713 ALOGE("%s: Could not set gapless mode %d",
714 __func__, gapless_enabled);
715 return -EINVAL;
716 }
717 return 0;
718}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700719
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700720__attribute__ ((visibility ("default")))
721int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
722 int table_size) {
723 int ret_val = 0;
724 ALOGV("%s: enter ... ", __func__);
725
726 pthread_mutex_lock(&adev_init_lock);
727 if (adev == NULL) {
728 ALOGW("%s: adev is NULL .... ", __func__);
729 goto done;
730 }
731
732 pthread_mutex_lock(&adev->lock);
733 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
734 pthread_mutex_unlock(&adev->lock);
735done:
736 pthread_mutex_unlock(&adev_init_lock);
737 ALOGV("%s: exit ... ", __func__);
738 return ret_val;
739}
740
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800741bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800742{
743 bool ret = false;
744 ALOGV("%s: enter ...", __func__);
745
746 pthread_mutex_lock(&adev_init_lock);
747
748 if (adev != NULL && adev->platform != NULL) {
749 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800750 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800751 pthread_mutex_unlock(&adev->lock);
752 }
753
754 pthread_mutex_unlock(&adev_init_lock);
755
756 ALOGV("%s: exit with ret %d", __func__, ret);
757 return ret;
758}
Aalique Grahame22e49102018-12-18 14:23:57 -0800759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700760static bool is_supported_format(audio_format_t format)
761{
Eric Laurent86e17132013-09-12 17:49:30 -0700762 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530763 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530764 format == AUDIO_FORMAT_AAC_LC ||
765 format == AUDIO_FORMAT_AAC_HE_V1 ||
766 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530767 format == AUDIO_FORMAT_AAC_ADTS_LC ||
768 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
769 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530770 format == AUDIO_FORMAT_AAC_LATM_LC ||
771 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
772 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530773 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
774 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530775 format == AUDIO_FORMAT_PCM_FLOAT ||
776 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700777 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530778 format == AUDIO_FORMAT_AC3 ||
779 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700780 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530781 format == AUDIO_FORMAT_DTS ||
782 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800783 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530784 format == AUDIO_FORMAT_ALAC ||
785 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530786 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530787 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800788 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530789 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700790 format == AUDIO_FORMAT_APTX ||
791 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800792 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700793
794 return false;
795}
796
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700797static inline bool is_mmap_usecase(audio_usecase_t uc_id)
798{
799 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
800 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
801}
802
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700803static inline bool is_valid_volume(float left, float right)
804{
805 return ((left >= 0.0f && right >= 0.0f) ? true : false);
806}
807
Avinash Vaish71a8b972014-07-24 15:36:33 +0530808static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
809 struct audio_usecase *uc_info)
810{
811 struct listnode *node;
812 struct audio_usecase *usecase;
813
814 if (uc_info == NULL)
815 return -EINVAL;
816
817 /* Re-route all voice usecases on the shared backend other than the
818 specified usecase to new snd devices */
819 list_for_each(node, &adev->usecase_list) {
820 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800821 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530822 enable_audio_route(adev, usecase);
823 }
824 return 0;
825}
826
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530827static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530828{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530829 ALOGV("%s", __func__);
830 audio_route_apply_and_update_path(adev->audio_route,
831 "asrc-mode");
832 adev->asrc_mode_enabled = true;
833}
834
835static void disable_asrc_mode(struct audio_device *adev)
836{
837 ALOGV("%s", __func__);
838 audio_route_reset_and_update_path(adev->audio_route,
839 "asrc-mode");
840 adev->asrc_mode_enabled = false;
841}
842
843/*
844 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
845 * 44.1 or Native DSD backends are enabled for any of current use case.
846 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
847 * - Disable current mix path use case(Headphone backend) and re-enable it with
848 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
849 * e.g. Naitve DSD or Headphone 44.1 -> + 48
850 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530851static void check_and_set_asrc_mode(struct audio_device *adev,
852 struct audio_usecase *uc_info,
853 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530854{
855 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530856 int i, num_new_devices = 0;
857 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
858 /*
859 *Split snd device for new combo use case
860 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
861 */
862 if (platform_split_snd_device(adev->platform,
863 snd_device,
864 &num_new_devices,
865 split_new_snd_devices) == 0) {
866 for (i = 0; i < num_new_devices; i++)
867 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
868 } else {
869 int new_backend_idx = platform_get_backend_index(snd_device);
870 if (((new_backend_idx == HEADPHONE_BACKEND) ||
871 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
872 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
873 !adev->asrc_mode_enabled) {
874 struct listnode *node = NULL;
875 struct audio_usecase *uc = NULL;
876 struct stream_out *curr_out = NULL;
877 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
878 int i, num_devices, ret = 0;
879 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530880
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530881 list_for_each(node, &adev->usecase_list) {
882 uc = node_to_item(node, struct audio_usecase, list);
883 curr_out = (struct stream_out*) uc->stream.out;
884 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
885 /*
886 *Split snd device for existing combo use case
887 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
888 */
889 ret = platform_split_snd_device(adev->platform,
890 uc->out_snd_device,
891 &num_devices,
892 split_snd_devices);
893 if (ret < 0 || num_devices == 0) {
894 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
895 split_snd_devices[0] = uc->out_snd_device;
896 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800897 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530898 for (i = 0; i < num_devices; i++) {
899 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
900 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
901 if((new_backend_idx == HEADPHONE_BACKEND) &&
902 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
903 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
904 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
905 __func__);
906 enable_asrc_mode(adev);
907 break;
908 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
909 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
910 (usecase_backend_idx == HEADPHONE_BACKEND)) {
911 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
912 __func__);
913 disable_audio_route(adev, uc);
914 disable_snd_device(adev, uc->out_snd_device);
915 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
916 if (new_backend_idx == DSD_NATIVE_BACKEND)
917 audio_route_apply_and_update_path(adev->audio_route,
918 "hph-true-highquality-mode");
919 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
920 (curr_out->bit_width >= 24))
921 audio_route_apply_and_update_path(adev->audio_route,
922 "hph-highquality-mode");
923 enable_asrc_mode(adev);
924 enable_snd_device(adev, uc->out_snd_device);
925 enable_audio_route(adev, uc);
926 break;
927 }
928 }
929 // reset split devices count
930 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800931 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530932 if (adev->asrc_mode_enabled)
933 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530934 }
935 }
936 }
937}
938
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700939static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
940 struct audio_effect_config effect_config,
941 unsigned int param_value)
942{
943 char mixer_ctl_name[] = "Audio Effect";
944 struct mixer_ctl *ctl;
945 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800946 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700947
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700948 if (in == NULL) {
949 ALOGE("%s: active input stream is NULL", __func__);
950 return -EINVAL;
951 }
952
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700953 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
954 if (!ctl) {
955 ALOGE("%s: Could not get mixer ctl - %s",
956 __func__, mixer_ctl_name);
957 return -EINVAL;
958 }
959
960 set_values[0] = 1; //0:Rx 1:Tx
961 set_values[1] = in->app_type_cfg.app_type;
962 set_values[2] = (long)effect_config.module_id;
963 set_values[3] = (long)effect_config.instance_id;
964 set_values[4] = (long)effect_config.param_id;
965 set_values[5] = param_value;
966
967 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
968
969 return 0;
970
971}
972
973static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
974 int effect_type, unsigned int *param_value)
975{
976 int ret = 0;
977 struct audio_effect_config other_effect_config;
978 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800979 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700980
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700981 if (in == NULL) {
982 ALOGE("%s: active input stream is NULL", __func__);
983 return -EINVAL;
984 }
985
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700986 usecase = get_usecase_from_list(adev, in->usecase);
987 if (!usecase)
988 return -EINVAL;
989
990 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
991 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
992 if (ret < 0) {
993 ALOGE("%s Failed to get effect params %d", __func__, ret);
994 return ret;
995 }
996
997 if (module_id == other_effect_config.module_id) {
998 //Same module id for AEC/NS. Values need to be combined
999 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1000 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1001 *param_value |= other_effect_config.param_value;
1002 }
1003 }
1004
1005 return ret;
1006}
1007
1008static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301009{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001010 struct audio_effect_config effect_config;
1011 struct audio_usecase *usecase = NULL;
1012 int ret = 0;
1013 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001014 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001015
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001016 if(!voice_extn_is_dynamic_ecns_enabled())
1017 return ENOSYS;
1018
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001019 if (!in) {
1020 ALOGE("%s: Invalid input stream", __func__);
1021 return -EINVAL;
1022 }
1023
1024 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1025
1026 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001027 if (usecase == NULL) {
1028 ALOGE("%s: Could not find the usecase (%d) in the list",
1029 __func__, in->usecase);
1030 return -EINVAL;
1031 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032
1033 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1034 if (ret < 0) {
1035 ALOGE("%s Failed to get module id %d", __func__, ret);
1036 return ret;
1037 }
1038 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1039 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1040
1041 if(enable)
1042 param_value = effect_config.param_value;
1043
1044 /*Special handling for AEC & NS effects Param values need to be
1045 updated if module ids are same*/
1046
1047 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1048 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1049 if (ret < 0)
1050 return ret;
1051 }
1052
1053 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1054
1055 return ret;
1056}
1057
1058static void check_and_enable_effect(struct audio_device *adev)
1059{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001060 if(!voice_extn_is_dynamic_ecns_enabled())
1061 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001062
Eric Laurent637e2d42018-11-15 12:24:31 -08001063 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001064
Eric Laurent637e2d42018-11-15 12:24:31 -08001065 if (in != NULL && !in->standby) {
1066 if (in->enable_aec)
1067 enable_disable_effect(adev, EFFECT_AEC, true);
1068
1069 if (in->enable_ns &&
1070 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1071 enable_disable_effect(adev, EFFECT_NS, true);
1072 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001073 }
1074}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001075
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001076int pcm_ioctl(struct pcm *pcm, int request, ...)
1077{
1078 va_list ap;
1079 void * arg;
1080 int pcm_fd = *(int*)pcm;
1081
1082 va_start(ap, request);
1083 arg = va_arg(ap, void *);
1084 va_end(ap);
1085
1086 return ioctl(pcm_fd, request, arg);
1087}
1088
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001089int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001090 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001093 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301094 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301095 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301096 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001097
1098 if (usecase == NULL)
1099 return -EINVAL;
1100
1101 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1102
Carter Hsu2e429db2019-05-14 18:50:52 +08001103 if (usecase->type == PCM_CAPTURE) {
1104 struct stream_in *in = usecase->stream.in;
1105 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001106 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001107
1108 if (in) {
1109 if (in->enable_aec || in->enable_ec_port) {
1110 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1111 struct listnode *node;
1112 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1113 USECASE_AUDIO_PLAYBACK_VOIP);
1114 if (voip_usecase) {
1115 out_device = voip_usecase->stream.out->devices;
1116 } else if (adev->primary_output &&
1117 !adev->primary_output->standby) {
1118 out_device = adev->primary_output->devices;
1119 } else {
1120 list_for_each(node, &adev->usecase_list) {
1121 uinfo = node_to_item(node, struct audio_usecase, list);
1122 if (uinfo->type != PCM_CAPTURE) {
1123 out_device = uinfo->stream.out->devices;
1124 break;
1125 }
1126 }
1127 }
1128 platform_set_echo_reference(adev, true, out_device);
1129 in->ec_opened = true;
1130 }
1131 }
1132 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1133 snd_device = usecase->in_snd_device;
1134 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001136 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001137
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001138#ifdef DS1_DOLBY_DAP_ENABLED
1139 audio_extn_dolby_set_dmid(adev);
1140 audio_extn_dolby_set_endpoint(adev);
1141#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001142 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001143 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301144 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001145 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001146 if (audio_extn_is_maxx_audio_enabled())
1147 audio_extn_ma_set_device(usecase);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001148#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1149 if (usecase->id != USECASE_AUDIO_ULTRASOUND_TX)
1150#endif
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301151 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301152 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1153 out = usecase->stream.out;
1154 if (out && out->compr)
1155 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1156 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301157
1158 if (usecase->type == PCM_CAPTURE) {
1159 in = usecase->stream.in;
1160 if (in && is_loopback_input_device(in->device)) {
1161 ALOGD("%s: set custom mtmx params v1", __func__);
1162 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1163 }
1164 } else {
1165 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1166 }
Manish Dewangan58229382017-02-02 15:48:41 +05301167
Andy Hung756ecc12018-10-19 17:47:12 -07001168 // we shouldn't truncate mixer_path
1169 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1170 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1171 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001172 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001173 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301174 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1175 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1176 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1177 if (parms) {
1178 audio_extn_fm_set_parameters(adev, parms);
1179 str_parms_destroy(parms);
1180 }
1181 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182 ALOGV("%s: exit", __func__);
1183 return 0;
1184}
1185
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001186int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001187 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001190 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301191 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001192
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301193 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001194 return -EINVAL;
1195
1196 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301197 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001198 snd_device = usecase->in_snd_device;
1199 else
1200 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001201 // we shouldn't truncate mixer_path
1202 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1203 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1204 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001205 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001206 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001207 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 if (usecase->type == PCM_CAPTURE) {
1209 struct stream_in *in = usecase->stream.in;
1210 if (in && in->ec_opened) {
1211 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1212 in->ec_opened = false;
1213 }
1214 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001215 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301216 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301217
1218 if (usecase->type == PCM_CAPTURE) {
1219 in = usecase->stream.in;
1220 if (in && is_loopback_input_device(in->device)) {
1221 ALOGD("%s: reset custom mtmx params v1", __func__);
1222 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1223 }
1224 } else {
1225 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1226 }
1227
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001228 if ((usecase->type == PCM_PLAYBACK) &&
1229 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301230 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 ALOGV("%s: exit", __func__);
1233 return 0;
1234}
1235
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001236int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001237 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001238{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301239 int i, num_devices = 0;
1240 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001241 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1242
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001243 if (snd_device < SND_DEVICE_MIN ||
1244 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001245 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001246 return -EINVAL;
1247 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001248
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001249 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001250 ALOGE("%s: Invalid sound device returned", __func__);
1251 return -EINVAL;
1252 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001253
1254 adev->snd_dev_ref_cnt[snd_device]++;
1255
1256 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1257 (platform_split_snd_device(adev->platform,
1258 snd_device,
1259 &num_devices,
1260 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001261 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001262 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263 return 0;
1264 }
1265
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001266 if (audio_extn_spkr_prot_is_enabled())
1267 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001268
Aalique Grahame22e49102018-12-18 14:23:57 -08001269 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1270
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001271 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1272 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001273 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1274 goto err;
1275 }
1276 audio_extn_dev_arbi_acquire(snd_device);
1277 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001278 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001279 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001280 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001281 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001282 } else if (platform_split_snd_device(adev->platform,
1283 snd_device,
1284 &num_devices,
1285 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301286 for (i = 0; i < num_devices; i++) {
1287 enable_snd_device(adev, new_snd_devices[i]);
1288 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001289 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001290 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001291 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301292
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301293
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001294 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1295 (audio_extn_a2dp_start_playback() < 0)) {
1296 ALOGE(" fail to configure A2dp Source control path ");
1297 goto err;
1298 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001299
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001300 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1301 (audio_extn_a2dp_start_capture() < 0)) {
1302 ALOGE(" fail to configure A2dp Sink control path ");
1303 goto err;
1304 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301305
Zhou Song12c29502019-03-16 10:37:18 +08001306 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1307 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1308 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1309 (audio_extn_sco_start_configuration() < 0)) {
1310 ALOGE(" fail to configure sco control path ");
1311 goto err;
1312 }
1313
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001314 /* due to the possibility of calibration overwrite between listen
1315 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001316 audio_extn_sound_trigger_update_device_status(snd_device,
1317 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301318 audio_extn_listen_update_device_status(snd_device,
1319 LISTEN_EVENT_SND_DEVICE_BUSY);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001320#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1321 if (snd_device != SND_DEVICE_OUT_ULTRASOUND_HANDSET &&
1322 snd_device != SND_DEVICE_IN_ULTRASOUND_MIC)
1323#endif
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001324 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001325 audio_extn_sound_trigger_update_device_status(snd_device,
1326 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301327 audio_extn_listen_update_device_status(snd_device,
1328 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001329 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001330 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001331 audio_extn_dev_arbi_acquire(snd_device);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05301332 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001333 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301334
1335 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1336 !adev->native_playback_enabled &&
1337 audio_is_true_native_stream_active(adev)) {
1338 ALOGD("%s: %d: napb: enabling native mode in hardware",
1339 __func__, __LINE__);
1340 audio_route_apply_and_update_path(adev->audio_route,
1341 "true-native-mode");
1342 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301343 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301344 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1345 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001346 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001347 ALOGD("%s: init ec ref loopback", __func__);
1348 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1349 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001351 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001352err:
1353 adev->snd_dev_ref_cnt[snd_device]--;
1354 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001355}
1356
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001357int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001358 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001359{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301360 int i, num_devices = 0;
1361 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001362 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1363
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001364 if (snd_device < SND_DEVICE_MIN ||
1365 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001366 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001367 return -EINVAL;
1368 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001369
1370 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1371 ALOGE("%s: Invalid sound device returned", __func__);
1372 return -EINVAL;
1373 }
1374
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001375 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1376 ALOGE("%s: device ref cnt is already 0", __func__);
1377 return -EINVAL;
1378 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001379
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001380 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001381
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001382
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001384 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301385
Aalique Grahame22e49102018-12-18 14:23:57 -08001386 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1387
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001388 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1389 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001390 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001391
1392 // when speaker device is disabled, reset swap.
1393 // will be renabled on usecase start
1394 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001395 } else if (platform_split_snd_device(adev->platform,
1396 snd_device,
1397 &num_devices,
1398 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301399 for (i = 0; i < num_devices; i++) {
1400 disable_snd_device(adev, new_snd_devices[i]);
1401 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001402 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001403 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001404 audio_route_reset_and_update_path(adev->audio_route, device_name);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05301405 amplifier_enable_devices(snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001406 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001407
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001408 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301409 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001410 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001411 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001412 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001413 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301414 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001415 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301416 adev->native_playback_enabled) {
1417 ALOGD("%s: %d: napb: disabling native mode in hardware",
1418 __func__, __LINE__);
1419 audio_route_reset_and_update_path(adev->audio_route,
1420 "true-native-mode");
1421 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301423 adev->asrc_mode_enabled) {
1424 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301425 disable_asrc_mode(adev);
1426 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001427 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301428 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001429 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001430 ALOGD("%s: deinit ec ref loopback", __func__);
1431 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1432 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001433
1434 audio_extn_utils_release_snd_device(snd_device);
1435 } else {
1436 if (platform_split_snd_device(adev->platform,
1437 snd_device,
1438 &num_devices,
1439 new_snd_devices) == 0) {
1440 for (i = 0; i < num_devices; i++) {
1441 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1442 }
1443 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446 return 0;
1447}
1448
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001449/*
1450 legend:
1451 uc - existing usecase
1452 new_uc - new usecase
1453 d1, d11, d2 - SND_DEVICE enums
1454 a1, a2 - corresponding ANDROID device enums
1455 B1, B2 - backend strings
1456
1457case 1
1458 uc->dev d1 (a1) B1
1459 new_uc->dev d1 (a1), d2 (a2) B1, B2
1460
1461 resolution: disable and enable uc->dev on d1
1462
1463case 2
1464 uc->dev d1 (a1) B1
1465 new_uc->dev d11 (a1) B1
1466
1467 resolution: need to switch uc since d1 and d11 are related
1468 (e.g. speaker and voice-speaker)
1469 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1470
1471case 3
1472 uc->dev d1 (a1) B1
1473 new_uc->dev d2 (a2) B2
1474
1475 resolution: no need to switch uc
1476
1477case 4
1478 uc->dev d1 (a1) B1
1479 new_uc->dev d2 (a2) B1
1480
1481 resolution: disable enable uc-dev on d2 since backends match
1482 we cannot enable two streams on two different devices if they
1483 share the same backend. e.g. if offload is on speaker device using
1484 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1485 using the same backend, offload must also be switched to voice-handset.
1486
1487case 5
1488 uc->dev d1 (a1) B1
1489 new_uc->dev d1 (a1), d2 (a2) B1
1490
1491 resolution: disable enable uc-dev on d2 since backends match
1492 we cannot enable two streams on two different devices if they
1493 share the same backend.
1494
1495case 6
1496 uc->dev d1 (a1) B1
1497 new_uc->dev d2 (a1) B2
1498
1499 resolution: no need to switch
1500
1501case 7
1502 uc->dev d1 (a1), d2 (a2) B1, B2
1503 new_uc->dev d1 (a1) B1
1504
1505 resolution: no need to switch
1506
Zhou Song4ba65882018-07-09 14:48:07 +08001507case 8
1508 uc->dev d1 (a1) B1
1509 new_uc->dev d11 (a1), d2 (a2) B1, B2
1510 resolution: compared to case 1, for this case, d1 and d11 are related
1511 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001512*/
1513static snd_device_t derive_playback_snd_device(void * platform,
1514 struct audio_usecase *uc,
1515 struct audio_usecase *new_uc,
1516 snd_device_t new_snd_device)
1517{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301518 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001519
1520 snd_device_t d1 = uc->out_snd_device;
1521 snd_device_t d2 = new_snd_device;
1522
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301523 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301524 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301525 a1 = uc->stream.inout->out_config.devices;
1526 a2 = new_uc->stream.inout->out_config.devices;
1527 break;
1528 default :
1529 a1 = uc->stream.out->devices;
1530 a2 = new_uc->stream.out->devices;
1531 break;
1532 }
1533
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001534 // Treat as a special case when a1 and a2 are not disjoint
1535 if ((a1 != a2) && (a1 & a2)) {
1536 snd_device_t d3[2];
1537 int num_devices = 0;
1538 int ret = platform_split_snd_device(platform,
1539 popcount(a1) > 1 ? d1 : d2,
1540 &num_devices,
1541 d3);
1542 if (ret < 0) {
1543 if (ret != -ENOSYS) {
1544 ALOGW("%s failed to split snd_device %d",
1545 __func__,
1546 popcount(a1) > 1 ? d1 : d2);
1547 }
1548 goto end;
1549 }
1550
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001551 if (platform_check_backends_match(d3[0], d3[1])) {
1552 return d2; // case 5
1553 } else {
Samyak Jaind826b502019-07-17 16:16:42 +05301554 if (popcount(a1) > 1)
1555 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001556 // check if d1 is related to any of d3's
1557 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001558 return d1; // case 1
1559 else
1560 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001561 }
1562 } else {
1563 if (platform_check_backends_match(d1, d2)) {
1564 return d2; // case 2, 4
1565 } else {
1566 return d1; // case 6, 3
1567 }
1568 }
1569
1570end:
1571 return d2; // return whatever was calculated before.
1572}
1573
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301575 struct audio_usecase *uc_info,
1576 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577{
1578 struct listnode *node;
1579 struct audio_usecase *usecase;
1580 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301581 snd_device_t uc_derive_snd_device;
1582 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001583 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1584 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001585 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301586 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 /*
1588 * This function is to make sure that all the usecases that are active on
1589 * the hardware codec backend are always routed to any one device that is
1590 * handled by the hardware codec.
1591 * For example, if low-latency and deep-buffer usecases are currently active
1592 * on speaker and out_set_parameters(headset) is received on low-latency
1593 * output, then we have to make sure deep-buffer is also switched to headset,
1594 * because of the limitation that both the devices cannot be enabled
1595 * at the same time as they share the same backend.
1596 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001597 /*
1598 * This call is to check if we need to force routing for a particular stream
1599 * If there is a backend configuration change for the device when a
1600 * new stream starts, then ADM needs to be closed and re-opened with the new
1601 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001602 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001603 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001604 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1605 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301606 /* For a2dp device reconfigure all active sessions
1607 * with new AFE encoder format based on a2dp state
1608 */
1609 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1610 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1611 audio_extn_a2dp_is_force_device_switch()) {
1612 force_routing = true;
1613 force_restart_session = true;
1614 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301615 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1616
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001617 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001618 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001619 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1621 switch_device[i] = false;
1622
1623 list_for_each(node, &adev->usecase_list) {
1624 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001625
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301626 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1627 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301628 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301629 platform_get_snd_device_name(usecase->out_snd_device),
1630 platform_check_backends_match(snd_device, usecase->out_snd_device));
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001631
1632#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1633 if (usecase->id == USECASE_AUDIO_ULTRASOUND_RX)
1634 continue;
1635#endif
1636
Rahul Sharma99770982019-03-06 17:05:26 +05301637 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1638 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301639 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1640 usecase, uc_info, snd_device);
1641 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1642 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1643 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1644 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001645 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301646 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1647 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1648 ((force_restart_session) ||
1649 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301650 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1651 __func__, use_case_table[usecase->id],
1652 platform_get_snd_device_name(usecase->out_snd_device));
1653 disable_audio_route(adev, usecase);
1654 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301655 /* Enable existing usecase on derived playback device */
1656 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301657 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301658 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659 }
1660 }
1661
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301662 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1663 num_uc_to_switch);
1664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001666 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301668 /* Make sure the previous devices to be disabled first and then enable the
1669 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 list_for_each(node, &adev->usecase_list) {
1671 usecase = node_to_item(node, struct audio_usecase, list);
1672 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001673 /* Check if output sound device to be switched can be split and if any
1674 of the split devices match with derived sound device */
1675 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1676 &num_devices, split_snd_devices) == 0) {
1677 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1678 for (i = 0; i < num_devices; i++) {
1679 /* Disable devices that do not match with derived sound device */
1680 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1681 disable_snd_device(adev, split_snd_devices[i]);
1682 }
1683 } else {
1684 disable_snd_device(adev, usecase->out_snd_device);
1685 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001686 }
1687 }
1688
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001689 list_for_each(node, &adev->usecase_list) {
1690 usecase = node_to_item(node, struct audio_usecase, list);
1691 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001692 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1693 &num_devices, split_snd_devices) == 0) {
1694 /* Enable derived sound device only if it does not match with
1695 one of the split sound devices. This is because the matching
1696 sound device was not disabled */
1697 bool should_enable = true;
1698 for (i = 0; i < num_devices; i++) {
1699 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1700 should_enable = false;
1701 break;
1702 }
1703 }
1704 if (should_enable)
1705 enable_snd_device(adev, derive_snd_device[usecase->id]);
1706 } else {
1707 enable_snd_device(adev, derive_snd_device[usecase->id]);
1708 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001709 }
1710 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 /* Re-route all the usecases on the shared backend other than the
1713 specified usecase to new snd devices */
1714 list_for_each(node, &adev->usecase_list) {
1715 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301716 /* Update the out_snd_device only before enabling the audio route */
1717 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301718 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301719 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301720 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301721 use_case_table[usecase->id],
1722 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001723 /* Update voc calibration before enabling VoIP route */
1724 if (usecase->type == VOIP_CALL)
1725 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001726 usecase->out_snd_device,
1727 platform_get_input_snd_device(
1728 adev->platform, NULL,
1729 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301730 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301731 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001732 out_set_voip_volume(&usecase->stream.out->stream,
1733 usecase->stream.out->volume_l,
1734 usecase->stream.out->volume_r);
1735 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301736 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001737 }
1738 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739 }
1740}
1741
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301742static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001743 struct audio_usecase *uc_info,
1744 snd_device_t snd_device)
1745{
1746 struct listnode *node;
1747 struct audio_usecase *usecase;
1748 bool switch_device[AUDIO_USECASE_MAX];
1749 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301750 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001751 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001752
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301753 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1754 snd_device);
1755 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301756
1757 /*
1758 * Make sure out devices is checked against out codec backend device and
1759 * also in devices against in codec backend. Checking out device against in
1760 * codec backend or vice versa causes issues.
1761 */
1762 if (uc_info->type == PCM_CAPTURE)
1763 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001764 /*
1765 * This function is to make sure that all the active capture usecases
1766 * are always routed to the same input sound device.
1767 * For example, if audio-record and voice-call usecases are currently
1768 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1769 * is received for voice call then we have to make sure that audio-record
1770 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1771 * because of the limitation that two devices cannot be enabled
1772 * at the same time if they share the same backend.
1773 */
1774 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1775 switch_device[i] = false;
1776
1777 list_for_each(node, &adev->usecase_list) {
1778 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301779 /*
1780 * TODO: Enhance below condition to handle BT sco/USB multi recording
1781 */
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001782
1783#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1784 if (usecase->id == USECASE_AUDIO_ULTRASOUND_TX)
1785 continue;
1786#endif
1787
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001788 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001789 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301790 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301791 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301792 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301793 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001794 ((uc_info->type == VOICE_CALL &&
1795 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1796 platform_check_backends_match(snd_device,\
1797 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001798 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001799 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1800 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001801 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001802 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001803 switch_device[usecase->id] = true;
1804 num_uc_to_switch++;
1805 }
1806 }
1807
1808 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001809 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001810
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301811 /* Make sure the previous devices to be disabled first and then enable the
1812 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001813 list_for_each(node, &adev->usecase_list) {
1814 usecase = node_to_item(node, struct audio_usecase, list);
1815 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001816 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001817 }
1818 }
1819
1820 list_for_each(node, &adev->usecase_list) {
1821 usecase = node_to_item(node, struct audio_usecase, list);
1822 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001823 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001824 }
1825 }
1826
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001827 /* Re-route all the usecases on the shared backend other than the
1828 specified usecase to new snd devices */
1829 list_for_each(node, &adev->usecase_list) {
1830 usecase = node_to_item(node, struct audio_usecase, list);
1831 /* Update the in_snd_device only before enabling the audio route */
1832 if (switch_device[usecase->id] ) {
1833 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001834 if (usecase->type != VOICE_CALL) {
1835 /* Update voc calibration before enabling VoIP route */
1836 if (usecase->type == VOIP_CALL)
1837 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001838 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001839 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301840 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001841 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001842 }
1843 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001844 }
1845}
1846
Mingming Yin3a941d42016-02-17 18:08:05 -08001847static void reset_hdmi_sink_caps(struct stream_out *out) {
1848 int i = 0;
1849
1850 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1851 out->supported_channel_masks[i] = 0;
1852 }
1853 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1854 out->supported_formats[i] = 0;
1855 }
1856 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1857 out->supported_sample_rates[i] = 0;
1858 }
1859}
1860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001862static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863{
Mingming Yin3a941d42016-02-17 18:08:05 -08001864 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001865 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
Mingming Yin3a941d42016-02-17 18:08:05 -08001867 reset_hdmi_sink_caps(out);
1868
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001869 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001870 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001871 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001872 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001873 }
1874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001877 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001878 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001879 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1880 case 6:
1881 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1882 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1883 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1884 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1885 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1886 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 break;
1888 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001889 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001890 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 break;
1892 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001893
1894 // check channel format caps
1895 i = 0;
1896 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1897 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1898 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1899 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1900 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1901 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1902 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1903 }
1904
Ben Romberger1aaaf862017-04-06 17:49:46 -07001905 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1906 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1907 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1908 }
1909
Mingming Yin3a941d42016-02-17 18:08:05 -08001910 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1911 ALOGV(":%s HDMI supports DTS format", __func__);
1912 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1913 }
1914
1915 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1916 ALOGV(":%s HDMI supports DTS HD format", __func__);
1917 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1918 }
1919
Naresh Tanniru928f0862017-04-07 16:44:23 -07001920 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1921 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1922 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1923 }
1924
Mingming Yin3a941d42016-02-17 18:08:05 -08001925
1926 // check sample rate caps
1927 i = 0;
1928 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1929 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1930 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1931 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1932 }
1933 }
1934
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001935 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936}
1937
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001938static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1939 uint32_t *supported_sample_rates __unused,
1940 uint32_t max_rates __unused)
1941{
1942 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1943 supported_sample_rates,
1944 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301945 ssize_t i = 0;
1946
1947 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001948 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1949 supported_sample_rates[i]);
1950 }
1951 return count;
1952}
1953
1954static inline int read_usb_sup_channel_masks(bool is_playback,
1955 audio_channel_mask_t *supported_channel_masks,
1956 uint32_t max_masks)
1957{
1958 int channels = audio_extn_usb_get_max_channels(is_playback);
1959 int channel_count;
1960 uint32_t num_masks = 0;
1961 if (channels > MAX_HIFI_CHANNEL_COUNT)
1962 channels = MAX_HIFI_CHANNEL_COUNT;
1963
1964 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001965 // start from 2 channels as framework currently doesn't support mono.
1966 if (channels >= FCC_2) {
1967 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1968 }
1969 for (channel_count = FCC_2;
1970 channel_count <= channels && num_masks < max_masks;
1971 ++channel_count) {
1972 supported_channel_masks[num_masks++] =
1973 audio_channel_mask_for_index_assignment_from_count(channel_count);
1974 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001975 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001976 // For capture we report all supported channel masks from 1 channel up.
1977 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001978 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1979 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001980 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1981 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1982 if (channel_count <= FCC_2) {
1983 mask = audio_channel_in_mask_from_count(channel_count);
1984 supported_channel_masks[num_masks++] = mask;
1985 }
1986 const audio_channel_mask_t index_mask =
1987 audio_channel_mask_for_index_assignment_from_count(channel_count);
1988 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1989 supported_channel_masks[num_masks++] = index_mask;
1990 }
1991 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001992 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301993
vincenttewf51c94e2019-05-07 10:28:53 +08001994 for (size_t i = 0; i < num_masks; ++i) {
1995 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1996 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301997 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001998 return num_masks;
1999}
2000
2001static inline int read_usb_sup_formats(bool is_playback __unused,
2002 audio_format_t *supported_formats,
2003 uint32_t max_formats __unused)
2004{
2005 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2006 switch (bitwidth) {
2007 case 24:
2008 // XXX : usb.c returns 24 for s24 and s24_le?
2009 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2010 break;
2011 case 32:
2012 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2013 break;
2014 case 16:
2015 default :
2016 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2017 break;
2018 }
2019 ALOGV("%s: %s supported format %d", __func__,
2020 is_playback ? "P" : "C", bitwidth);
2021 return 1;
2022}
2023
2024static inline int read_usb_sup_params_and_compare(bool is_playback,
2025 audio_format_t *format,
2026 audio_format_t *supported_formats,
2027 uint32_t max_formats,
2028 audio_channel_mask_t *mask,
2029 audio_channel_mask_t *supported_channel_masks,
2030 uint32_t max_masks,
2031 uint32_t *rate,
2032 uint32_t *supported_sample_rates,
2033 uint32_t max_rates) {
2034 int ret = 0;
2035 int num_formats;
2036 int num_masks;
2037 int num_rates;
2038 int i;
2039
2040 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2041 max_formats);
2042 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2043 max_masks);
2044
2045 num_rates = read_usb_sup_sample_rates(is_playback,
2046 supported_sample_rates, max_rates);
2047
2048#define LUT(table, len, what, dflt) \
2049 for (i=0; i<len && (table[i] != what); i++); \
2050 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2051
2052 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2053 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2054 LUT(supported_sample_rates, num_rates, *rate, 0);
2055
2056#undef LUT
2057 return ret < 0 ? -EINVAL : 0; // HACK TBD
2058}
2059
Alexy Josephb1379942016-01-29 15:49:38 -08002060audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002061 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002062{
2063 struct audio_usecase *usecase;
2064 struct listnode *node;
2065
2066 list_for_each(node, &adev->usecase_list) {
2067 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002068 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002069 ALOGV("%s: usecase id %d", __func__, usecase->id);
2070 return usecase->id;
2071 }
2072 }
2073 return USECASE_INVALID;
2074}
2075
Alexy Josephb1379942016-01-29 15:49:38 -08002076struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002077 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078{
2079 struct audio_usecase *usecase;
2080 struct listnode *node;
2081
2082 list_for_each(node, &adev->usecase_list) {
2083 usecase = node_to_item(node, struct audio_usecase, list);
2084 if (usecase->id == uc_id)
2085 return usecase;
2086 }
2087 return NULL;
2088}
2089
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302090/*
2091 * is a true native playback active
2092 */
2093bool audio_is_true_native_stream_active(struct audio_device *adev)
2094{
2095 bool active = false;
2096 int i = 0;
2097 struct listnode *node;
2098
2099 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2100 ALOGV("%s:napb: not in true mode or non hdphones device",
2101 __func__);
2102 active = false;
2103 goto exit;
2104 }
2105
2106 list_for_each(node, &adev->usecase_list) {
2107 struct audio_usecase *uc;
2108 uc = node_to_item(node, struct audio_usecase, list);
2109 struct stream_out *curr_out =
2110 (struct stream_out*) uc->stream.out;
2111
2112 if (curr_out && PCM_PLAYBACK == uc->type) {
2113 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2114 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2115 uc->id, curr_out->sample_rate,
2116 curr_out->bit_width,
2117 platform_get_snd_device_name(uc->out_snd_device));
2118
2119 if (is_offload_usecase(uc->id) &&
2120 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2121 active = true;
2122 ALOGD("%s:napb:native stream detected", __func__);
2123 }
2124 }
2125 }
2126exit:
2127 return active;
2128}
2129
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002130uint32_t adev_get_dsp_bit_width_enforce_mode()
2131{
2132 if (adev == NULL) {
2133 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2134 return 0;
2135 }
2136 return adev->dsp_bit_width_enforce_mode;
2137}
2138
2139static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2140{
2141 char value[PROPERTY_VALUE_MAX];
2142 int trial;
2143 uint32_t dsp_bit_width_enforce_mode = 0;
2144
2145 if (!mixer) {
2146 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2147 __func__);
2148 return 0;
2149 }
2150
2151 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2152 value, NULL) > 0) {
2153 trial = atoi(value);
2154 switch (trial) {
2155 case 16:
2156 dsp_bit_width_enforce_mode = 16;
2157 break;
2158 case 24:
2159 dsp_bit_width_enforce_mode = 24;
2160 break;
2161 case 32:
2162 dsp_bit_width_enforce_mode = 32;
2163 break;
2164 default:
2165 dsp_bit_width_enforce_mode = 0;
2166 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2167 break;
2168 }
2169 }
2170
2171 return dsp_bit_width_enforce_mode;
2172}
2173
2174static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2175 uint32_t enforce_mode,
2176 bool enable)
2177{
2178 struct mixer_ctl *ctl = NULL;
2179 const char *mixer_ctl_name = "ASM Bit Width";
2180 uint32_t asm_bit_width_mode = 0;
2181
2182 if (enforce_mode == 0) {
2183 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2184 return;
2185 }
2186
2187 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2188 if (!ctl) {
2189 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2190 __func__, mixer_ctl_name);
2191 return;
2192 }
2193
2194 if (enable)
2195 asm_bit_width_mode = enforce_mode;
2196 else
2197 asm_bit_width_mode = 0;
2198
2199 ALOGV("%s DSP bit width feature status is %d width=%d",
2200 __func__, enable, asm_bit_width_mode);
2201 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2202 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2203 asm_bit_width_mode);
2204
2205 return;
2206}
2207
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302208/*
2209 * if native DSD playback active
2210 */
2211bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2212{
2213 bool active = false;
2214 struct listnode *node = NULL;
2215 struct audio_usecase *uc = NULL;
2216 struct stream_out *curr_out = NULL;
2217
2218 list_for_each(node, &adev->usecase_list) {
2219 uc = node_to_item(node, struct audio_usecase, list);
2220 curr_out = (struct stream_out*) uc->stream.out;
2221
2222 if (curr_out && PCM_PLAYBACK == uc->type &&
2223 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2224 active = true;
2225 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302226 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302227 }
2228 }
2229 return active;
2230}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302231
2232static bool force_device_switch(struct audio_usecase *usecase)
2233{
2234 bool ret = false;
2235 bool is_it_true_mode = false;
2236
Zhou Song30f2c3e2018-02-08 14:02:15 +08002237 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302238 usecase->type == TRANSCODE_LOOPBACK_RX ||
2239 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002240 return false;
2241 }
2242
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002243 if(usecase->stream.out == NULL) {
2244 ALOGE("%s: stream.out is NULL", __func__);
2245 return false;
2246 }
2247
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302248 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002249 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2250 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2251 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302252 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2253 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2254 (!is_it_true_mode && adev->native_playback_enabled)){
2255 ret = true;
2256 ALOGD("napb: time to toggle native mode");
2257 }
2258 }
2259
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302260 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302261 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2262 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002263 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302264 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302265 ALOGD("Force a2dp device switch to update new encoder config");
2266 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002267 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302268
Florian Pfister1a84f312018-07-19 14:38:18 +02002269 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302270 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2271 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002272 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302273 return ret;
2274}
2275
Aalique Grahame22e49102018-12-18 14:23:57 -08002276static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2277{
2278 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2279}
2280
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302281bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2282{
2283 bool ret=false;
2284 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2285 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2286 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2287 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2288 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2289 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2290 ret = true;
2291
2292 return ret;
2293}
2294
2295bool is_a2dp_device(snd_device_t out_snd_device)
2296{
2297 bool ret=false;
2298 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2299 ret = true;
2300
2301 return ret;
2302}
2303
2304bool is_bt_soc_on(struct audio_device *adev)
2305{
2306 struct mixer_ctl *ctl;
2307 char *mixer_ctl_name = "BT SOC status";
2308 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2309 bool bt_soc_status = true;
2310 if (!ctl) {
2311 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2312 __func__, mixer_ctl_name);
2313 /*This is to ensure we dont break targets which dont have the kernel change*/
2314 return true;
2315 }
2316 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2317 ALOGD("BT SOC status: %d",bt_soc_status);
2318 return bt_soc_status;
2319}
2320
2321int out_standby_l(struct audio_stream *stream);
2322
Eric Laurent637e2d42018-11-15 12:24:31 -08002323struct stream_in *adev_get_active_input(const struct audio_device *adev)
2324{
2325 struct listnode *node;
2326 struct stream_in *last_active_in = NULL;
2327
2328 /* Get last added active input.
2329 * TODO: We may use a priority mechanism to pick highest priority active source */
2330 list_for_each(node, &adev->usecase_list)
2331 {
2332 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2333 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2334 last_active_in = usecase->stream.in;
2335 }
2336
2337 return last_active_in;
2338}
2339
2340struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2341{
2342 struct listnode *node;
2343
2344 /* First check active inputs with voice communication source and then
2345 * any input if audio mode is in communication */
2346 list_for_each(node, &adev->usecase_list)
2347 {
2348 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2349 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2350 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2351 return usecase->stream.in;
2352 }
2353 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2354 return adev_get_active_input(adev);
2355
2356 return NULL;
2357}
2358
Carter Hsu2e429db2019-05-14 18:50:52 +08002359/*
2360 * Aligned with policy.h
2361 */
2362static inline int source_priority(int inputSource)
2363{
2364 switch (inputSource) {
2365 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2366 return 9;
2367 case AUDIO_SOURCE_CAMCORDER:
2368 return 8;
2369 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2370 return 7;
2371 case AUDIO_SOURCE_UNPROCESSED:
2372 return 6;
2373 case AUDIO_SOURCE_MIC:
2374 return 5;
2375 case AUDIO_SOURCE_ECHO_REFERENCE:
2376 return 4;
2377 case AUDIO_SOURCE_FM_TUNER:
2378 return 3;
2379 case AUDIO_SOURCE_VOICE_RECOGNITION:
2380 return 2;
2381 case AUDIO_SOURCE_HOTWORD:
2382 return 1;
2383 default:
2384 break;
2385 }
2386 return 0;
2387}
2388
2389static struct stream_in *get_priority_input(struct audio_device *adev)
2390{
2391 struct listnode *node;
2392 struct audio_usecase *usecase;
2393 int last_priority = 0, priority;
2394 struct stream_in *priority_in = NULL;
2395 struct stream_in *in;
2396
2397 list_for_each(node, &adev->usecase_list) {
2398 usecase = node_to_item(node, struct audio_usecase, list);
2399 if (usecase->type == PCM_CAPTURE) {
2400 in = usecase->stream.in;
2401 if (!in)
2402 continue;
2403 priority = source_priority(in->source);
2404
2405 if (priority > last_priority) {
2406 last_priority = priority;
2407 priority_in = in;
2408 }
2409 }
2410 }
2411 return priority_in;
2412}
2413
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002414int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002416 snd_device_t out_snd_device = SND_DEVICE_NONE;
2417 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002418 struct audio_usecase *usecase = NULL;
2419 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002420 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002421 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302422 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002423 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002424 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302426 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2427
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002428 usecase = get_usecase_from_list(adev, uc_id);
2429 if (usecase == NULL) {
2430 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2431 return -EINVAL;
2432 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002434 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002435 (usecase->type == VOIP_CALL) ||
2436 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302437 if(usecase->stream.out == NULL) {
2438 ALOGE("%s: stream.out is NULL", __func__);
2439 return -EINVAL;
2440 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002441 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002442 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002443 in_snd_device = platform_get_input_snd_device(adev->platform,
2444 NULL,
2445 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002446 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302447 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302448 if (usecase->stream.inout == NULL) {
2449 ALOGE("%s: stream.inout is NULL", __func__);
2450 return -EINVAL;
2451 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302452 stream_out.devices = usecase->stream.inout->out_config.devices;
2453 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2454 stream_out.format = usecase->stream.inout->out_config.format;
2455 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2456 out_snd_device = platform_get_output_snd_device(adev->platform,
2457 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302458 usecase->devices = out_snd_device;
2459 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2460 if (usecase->stream.inout == NULL) {
2461 ALOGE("%s: stream.inout is NULL", __func__);
2462 return -EINVAL;
2463 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002464 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302465 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002466 } else {
2467 /*
2468 * If the voice call is active, use the sound devices of voice call usecase
2469 * so that it would not result any device switch. All the usecases will
2470 * be switched to new device when select_devices() is called for voice call
2471 * usecase. This is to avoid switching devices for voice call when
2472 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002473 * choose voice call device only if the use case device is
2474 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002475 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002476 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002477 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002478 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002479 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2480 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302481 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2482 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002483 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2484 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002485 in_snd_device = vc_usecase->in_snd_device;
2486 out_snd_device = vc_usecase->out_snd_device;
2487 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002488 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002489 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002490 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002491 if ((voip_usecase != NULL) &&
2492 (usecase->type == PCM_PLAYBACK) &&
2493 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002494 out_snd_device_backend_match = platform_check_backends_match(
2495 voip_usecase->out_snd_device,
2496 platform_get_output_snd_device(
2497 adev->platform,
2498 usecase->stream.out));
2499 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002500 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002501 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2502 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002503 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002504 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002505 in_snd_device = voip_usecase->in_snd_device;
2506 out_snd_device = voip_usecase->out_snd_device;
2507 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002508 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002509 hfp_ucid = audio_extn_hfp_get_usecase();
2510 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002511 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002512 in_snd_device = hfp_usecase->in_snd_device;
2513 out_snd_device = hfp_usecase->out_snd_device;
2514 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002515 }
2516 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302517 if (usecase->stream.out == NULL) {
2518 ALOGE("%s: stream.out is NULL", __func__);
2519 return -EINVAL;
2520 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002521 usecase->devices = usecase->stream.out->devices;
2522 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002523 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002524 struct stream_out *voip_out = adev->primary_output;
2525 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002526 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002527 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002528 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002529
Eric Laurent637e2d42018-11-15 12:24:31 -08002530 if (voip_usecase)
2531 voip_out = voip_usecase->stream.out;
2532
2533 if (usecase->stream.out == voip_out && voip_in != NULL)
2534 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002536 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302537 if (usecase->stream.in == NULL) {
2538 ALOGE("%s: stream.in is NULL", __func__);
2539 return -EINVAL;
2540 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002541 usecase->devices = usecase->stream.in->device;
2542 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002543 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002544 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002545 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002546 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002547
2548 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002549 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2550 USECASE_AUDIO_PLAYBACK_VOIP);
2551
Carter Hsu2e429db2019-05-14 18:50:52 +08002552 usecase->stream.in->enable_ec_port = false;
2553
Eric Laurent637e2d42018-11-15 12:24:31 -08002554 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2555 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2556 } else if (voip_usecase) {
2557 out_device = voip_usecase->stream.out->devices;
2558 } else if (adev->primary_output &&
2559 !adev->primary_output->standby) {
2560 out_device = adev->primary_output->devices;
2561 } else {
2562 /* forcing speaker o/p device to get matching i/p pair
2563 in case o/p is not routed from same primary HAL */
2564 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2565 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002566 priority_in = voip_in;
2567 } else {
2568 /* get the input with the highest priority source*/
2569 priority_in = get_priority_input(adev);
2570
2571 if (!priority_in)
2572 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002573 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002574
Eric Laurent637e2d42018-11-15 12:24:31 -08002575 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002576 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002577 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002578 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002579 }
2580 }
2581
2582 if (out_snd_device == usecase->out_snd_device &&
2583 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302584
2585 if (!force_device_switch(usecase))
2586 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 }
2588
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302589 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002590 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302591 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2592 return 0;
2593 }
2594
Aalique Grahame22e49102018-12-18 14:23:57 -08002595 if (out_snd_device != SND_DEVICE_NONE &&
2596 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2597 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2598 __func__,
2599 use_case_table[uc_id],
2600 adev->last_logged_snd_device[uc_id][0],
2601 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2602 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2603 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2604 -1,
2605 out_snd_device,
2606 platform_get_snd_device_name(out_snd_device),
2607 platform_get_snd_device_acdb_id(out_snd_device));
2608 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2609 }
2610 if (in_snd_device != SND_DEVICE_NONE &&
2611 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2612 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2613 __func__,
2614 use_case_table[uc_id],
2615 adev->last_logged_snd_device[uc_id][1],
2616 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2617 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2618 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2619 -1,
2620 in_snd_device,
2621 platform_get_snd_device_name(in_snd_device),
2622 platform_get_snd_device_acdb_id(in_snd_device));
2623 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2624 }
2625
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 /*
2628 * Limitation: While in call, to do a device switch we need to disable
2629 * and enable both RX and TX devices though one of them is same as current
2630 * device.
2631 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002632 if ((usecase->type == VOICE_CALL) &&
2633 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2634 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002635 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002636 }
2637
2638 if (((usecase->type == VOICE_CALL) ||
2639 (usecase->type == VOIP_CALL)) &&
2640 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2641 /* Disable sidetone only if voice/voip call already exists */
2642 if (voice_is_call_state_active(adev) ||
2643 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002644 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002645
2646 /* Disable aanc only if voice call exists */
2647 if (voice_is_call_state_active(adev))
2648 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002649 }
2650
Aalique Grahame22e49102018-12-18 14:23:57 -08002651 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2652 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002653 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302654 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002655 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2656 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2657 else
2658 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302659 }
2660
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002661 /* Disable current sound devices */
2662 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002663 disable_audio_route(adev, usecase);
2664 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 }
2666
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002667 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002668 disable_audio_route(adev, usecase);
2669 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 }
2671
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002672 /* Applicable only on the targets that has external modem.
2673 * New device information should be sent to modem before enabling
2674 * the devices to reduce in-call device switch time.
2675 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002676 if ((usecase->type == VOICE_CALL) &&
2677 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2678 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002679 status = platform_switch_voice_call_enable_device_config(adev->platform,
2680 out_snd_device,
2681 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002682 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002683
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002684 /* Enable new sound devices */
2685 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002686 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302687 if (platform_check_codec_asrc_support(adev->platform))
2688 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002689 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 }
2691
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002692 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302693 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002694 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002695 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002696
Avinash Vaish71a8b972014-07-24 15:36:33 +05302697 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002698 status = platform_switch_voice_call_device_post(adev->platform,
2699 out_snd_device,
2700 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302701 enable_audio_route_for_voice_usecases(adev, usecase);
2702 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002703
sangwoo170731f2013-06-08 15:36:36 +09002704 usecase->in_snd_device = in_snd_device;
2705 usecase->out_snd_device = out_snd_device;
2706
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302707 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2708 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302709 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002710 if ((24 == usecase->stream.out->bit_width) &&
2711 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2712 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2713 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2714 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2715 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2716 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2717 /*
2718 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2719 * configured device sample rate, if not update the COPP rate to be equal to the
2720 * device sample rate, else open COPP at stream sample rate
2721 */
2722 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2723 usecase->stream.out->sample_rate,
2724 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302725 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2726 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002727 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2728 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2729 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2730 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002731 }
2732 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002733
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002734 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002735
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002736 /* If input stream is already running then effect needs to be
2737 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002738 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002739 check_and_enable_effect(adev);
2740
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002741 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002742 /* Enable aanc only if voice call exists */
2743 if (voice_is_call_state_active(adev))
2744 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2745
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002746 /* Enable sidetone only if other voice/voip call already exists */
2747 if (voice_is_call_state_active(adev) ||
2748 voice_extn_compress_voip_is_started(adev))
2749 voice_set_sidetone(adev, out_snd_device, true);
2750 }
2751
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05302752 /* Rely on amplifier_set_devices to distinguish between in/out devices */
2753 amplifier_set_input_devices(in_snd_device);
2754 amplifier_set_output_devices(out_snd_device);
2755
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002756 /* Applicable only on the targets that has external modem.
2757 * Enable device command should be sent to modem only after
2758 * enabling voice call mixer controls
2759 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002760 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002761 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2762 out_snd_device,
2763 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302764
2765 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002766 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302767 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002768 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302769 if (is_bt_soc_on(adev) == false){
2770 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002771 if (in->pcm != NULL)
2772 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302773 }
2774 }
2775 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2776 && usecase->stream.out->started) {
2777 if (is_bt_soc_on(adev) == false) {
2778 ALOGD("BT SCO/A2DP disconnected while in connection");
2779 out_standby_l(&usecase->stream.out->stream.common);
2780 }
2781 }
2782 } else if ((usecase->stream.out != NULL) &&
2783 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302784 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2785 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302786 usecase->stream.out->started) {
2787 if (is_bt_soc_on(adev) == false) {
2788 ALOGD("BT SCO/A2dp disconnected while in connection");
2789 out_standby_l(&usecase->stream.out->stream.common);
2790 }
2791 }
2792 }
2793
Yung Ti Su70cb8242018-06-22 17:38:47 +08002794 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002795 struct stream_out *voip_out = voip_usecase->stream.out;
2796 audio_extn_utils_send_app_type_gain(adev,
2797 voip_out->app_type_cfg.app_type,
2798 &voip_out->app_type_cfg.gain[0]);
2799 }
2800
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302801 ALOGD("%s: done",__func__);
2802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 return status;
2804}
2805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806static int stop_input_stream(struct stream_in *in)
2807{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302808 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302810
2811 if (in == NULL) {
2812 ALOGE("%s: stream_in ptr is NULL", __func__);
2813 return -EINVAL;
2814 }
2815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002817 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818
Eric Laurent994a6932013-07-17 11:51:42 -07002819 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002820 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821 uc_info = get_usecase_from_list(adev, in->usecase);
2822 if (uc_info == NULL) {
2823 ALOGE("%s: Could not find the usecase (%d) in the list",
2824 __func__, in->usecase);
2825 return -EINVAL;
2826 }
2827
Carter Hsu2e429db2019-05-14 18:50:52 +08002828 priority_in = get_priority_input(adev);
2829
Derek Chenea197282019-01-07 17:35:01 -08002830 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2831 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002832
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002833 /* Close in-call recording streams */
2834 voice_check_and_stop_incall_rec_usecase(adev, in);
2835
Eric Laurent150dbfe2013-02-27 14:31:02 -08002836 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002837 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002838
2839 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002840 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302842 if (is_loopback_input_device(in->device))
2843 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2844
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002845 list_remove(&uc_info->list);
2846 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847
Carter Hsu2e429db2019-05-14 18:50:52 +08002848 if (priority_in == in) {
2849 priority_in = get_priority_input(adev);
2850 if (priority_in)
2851 select_devices(adev, priority_in->usecase);
2852 }
2853
Vatsal Buchac09ae062018-11-14 13:25:08 +05302854 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002855 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 return ret;
2857}
2858
2859int start_input_stream(struct stream_in *in)
2860{
2861 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002862 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302864
2865 if (in == NULL) {
2866 ALOGE("%s: stream_in ptr is NULL", __func__);
2867 return -EINVAL;
2868 }
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002871 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002872 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873
Mingming Yin2664a5b2015-09-03 10:53:11 -07002874 if (get_usecase_from_list(adev, usecase) == NULL)
2875 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302876 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2877 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002878
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302879 if (CARD_STATUS_OFFLINE == in->card_status||
2880 CARD_STATUS_OFFLINE == adev->card_status) {
2881 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302882 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302883 goto error_config;
2884 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302885
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302886 if (audio_is_bluetooth_sco_device(in->device)) {
2887 if (!adev->bt_sco_on) {
2888 ALOGE("%s: SCO profile is not ready, return error", __func__);
2889 ret = -EIO;
2890 goto error_config;
2891 }
2892 }
2893
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002894 /* Check if source matches incall recording usecase criteria */
2895 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2896 if (ret)
2897 goto error_config;
2898 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002899 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2900
2901 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2902 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2903 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002904 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002905 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002906
Eric Laurentb23d5282013-05-14 15:27:20 -07002907 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 if (in->pcm_device_id < 0) {
2909 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2910 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002911 ret = -EINVAL;
2912 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002916
2917 if (!uc_info) {
2918 ret = -ENOMEM;
2919 goto error_config;
2920 }
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 uc_info->id = in->usecase;
2923 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002924 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002925 uc_info->devices = in->device;
2926 uc_info->in_snd_device = SND_DEVICE_NONE;
2927 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002929 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002930 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302931 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2932 adev->perf_lock_opts,
2933 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002934 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935
Derek Chenea197282019-01-07 17:35:01 -08002936 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2937 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002938
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302939 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2940
Haynes Mathew George16081042017-05-31 17:16:49 -07002941 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302942 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302943 if (ret)
2944 goto error_open;
2945 else
2946 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002947 }
2948
Haynes Mathew George16081042017-05-31 17:16:49 -07002949 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002950 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002951 ALOGE("%s: pcm stream not ready", __func__);
2952 goto error_open;
2953 }
2954 ret = pcm_start(in->pcm);
2955 if (ret < 0) {
2956 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2957 goto error_open;
2958 }
2959 } else {
2960 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2961 unsigned int pcm_open_retry_count = 0;
2962
2963 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2964 flags |= PCM_MMAP | PCM_NOIRQ;
2965 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2966 } else if (in->realtime) {
2967 flags |= PCM_MMAP | PCM_NOIRQ;
2968 }
2969
Garmond Leunge2433c32017-09-28 21:51:22 -07002970 if (audio_extn_ffv_get_stream() == in) {
2971 ALOGD("%s: ffv stream, update pcm config", __func__);
2972 audio_extn_ffv_update_pcm_config(&config);
2973 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002974 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2975 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2976
2977 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002978 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002979 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002980 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002981 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302982 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302983 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2984 adev->card_status = CARD_STATUS_OFFLINE;
2985 in->card_status = CARD_STATUS_OFFLINE;
2986 ret = -EIO;
2987 goto error_open;
2988 }
2989
Haynes Mathew George16081042017-05-31 17:16:49 -07002990 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2991 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2992 if (in->pcm != NULL) {
2993 pcm_close(in->pcm);
2994 in->pcm = NULL;
2995 }
2996 if (pcm_open_retry_count-- == 0) {
2997 ret = -EIO;
2998 goto error_open;
2999 }
3000 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3001 continue;
3002 }
3003 break;
3004 }
3005
3006 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003007 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003008 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003009 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003010 if (ret < 0) {
3011 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3012 pcm_close(in->pcm);
3013 in->pcm = NULL;
3014 goto error_open;
3015 }
3016 register_in_stream(in);
3017 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003018 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003019 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003020 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003021 if (ret < 0) {
3022 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003023 pcm_close(in->pcm);
3024 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003025 goto error_open;
3026 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003027 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003028 }
3029
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003030 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003031 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3032 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003033
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303034 if (is_loopback_input_device(in->device))
3035 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3036
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303037done_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 Alamandac7d9bef2015-09-30 22:27:26 -07003040 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303041 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003042 return ret;
3043
3044error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003045 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303046 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003048
Eric Laurentc8400632013-02-14 19:04:54 -08003049error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303050 /*
3051 * sleep 50ms to allow sufficient time for kernel
3052 * drivers to recover incases like SSR.
3053 */
3054 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003055 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303056 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003057 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058}
3059
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003060void lock_input_stream(struct stream_in *in)
3061{
3062 pthread_mutex_lock(&in->pre_lock);
3063 pthread_mutex_lock(&in->lock);
3064 pthread_mutex_unlock(&in->pre_lock);
3065}
3066
3067void lock_output_stream(struct stream_out *out)
3068{
3069 pthread_mutex_lock(&out->pre_lock);
3070 pthread_mutex_lock(&out->lock);
3071 pthread_mutex_unlock(&out->pre_lock);
3072}
3073
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074/* must be called with out->lock locked */
3075static int send_offload_cmd_l(struct stream_out* out, int command)
3076{
3077 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3078
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003079 if (!cmd) {
3080 ALOGE("failed to allocate mem for command 0x%x", command);
3081 return -ENOMEM;
3082 }
3083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084 ALOGVV("%s %d", __func__, command);
3085
3086 cmd->cmd = command;
3087 list_add_tail(&out->offload_cmd_list, &cmd->node);
3088 pthread_cond_signal(&out->offload_cond);
3089 return 0;
3090}
3091
3092/* must be called iwth out->lock locked */
3093static void stop_compressed_output_l(struct stream_out *out)
3094{
3095 out->offload_state = OFFLOAD_STATE_IDLE;
3096 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003097 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 if (out->compr != NULL) {
3099 compress_stop(out->compr);
3100 while (out->offload_thread_blocked) {
3101 pthread_cond_wait(&out->cond, &out->lock);
3102 }
3103 }
3104}
3105
Varun Balaraje49253e2017-07-06 19:48:56 +05303106bool is_interactive_usecase(audio_usecase_t uc_id)
3107{
3108 unsigned int i;
3109 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3110 if (uc_id == interactive_usecases[i])
3111 return true;
3112 }
3113 return false;
3114}
3115
3116static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3117{
3118 audio_usecase_t ret_uc = USECASE_INVALID;
3119 unsigned int intract_uc_index;
3120 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3121
3122 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3123 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3124 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3125 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3126 ret_uc = interactive_usecases[intract_uc_index];
3127 break;
3128 }
3129 }
3130
3131 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3132 return ret_uc;
3133}
3134
3135static void free_interactive_usecase(struct audio_device *adev,
3136 audio_usecase_t uc_id)
3137{
3138 unsigned int interact_uc_index;
3139 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3140
3141 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3142 if (interactive_usecases[interact_uc_index] == uc_id) {
3143 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3144 break;
3145 }
3146 }
3147 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3148}
3149
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003150bool is_offload_usecase(audio_usecase_t uc_id)
3151{
3152 unsigned int i;
3153 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3154 if (uc_id == offload_usecases[i])
3155 return true;
3156 }
3157 return false;
3158}
3159
Dhananjay Kumarac341582017-02-23 23:42:25 +05303160static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003161{
vivek mehta446c3962015-09-14 10:57:35 -07003162 audio_usecase_t ret_uc = USECASE_INVALID;
3163 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003164 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003165 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303166 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003167 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3168 else
3169 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003170
vivek mehta446c3962015-09-14 10:57:35 -07003171 pthread_mutex_lock(&adev->lock);
3172 if (get_usecase_from_list(adev, ret_uc) != NULL)
3173 ret_uc = USECASE_INVALID;
3174 pthread_mutex_unlock(&adev->lock);
3175
3176 return ret_uc;
3177 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003178
3179 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003180 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3181 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3182 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3183 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003184 break;
3185 }
3186 }
vivek mehta446c3962015-09-14 10:57:35 -07003187
3188 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3189 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003190}
3191
3192static void free_offload_usecase(struct audio_device *adev,
3193 audio_usecase_t uc_id)
3194{
vivek mehta446c3962015-09-14 10:57:35 -07003195 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003196 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003197
3198 if (!adev->multi_offload_enable)
3199 return;
3200
3201 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3202 if (offload_usecases[offload_uc_index] == uc_id) {
3203 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003204 break;
3205 }
3206 }
3207 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3208}
3209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003210static void *offload_thread_loop(void *context)
3211{
3212 struct stream_out *out = (struct stream_out *) context;
3213 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003214 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003216 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003217 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003218 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3219
3220 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003221 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003222 out->offload_state = OFFLOAD_STATE_IDLE;
3223 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 for (;;) {
3225 struct offload_cmd *cmd = NULL;
3226 stream_callback_event_t event;
3227 bool send_callback = false;
3228
3229 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3230 __func__, list_empty(&out->offload_cmd_list),
3231 out->offload_state);
3232 if (list_empty(&out->offload_cmd_list)) {
3233 ALOGV("%s SLEEPING", __func__);
3234 pthread_cond_wait(&out->offload_cond, &out->lock);
3235 ALOGV("%s RUNNING", __func__);
3236 continue;
3237 }
3238
3239 item = list_head(&out->offload_cmd_list);
3240 cmd = node_to_item(item, struct offload_cmd, node);
3241 list_remove(item);
3242
3243 ALOGVV("%s STATE %d CMD %d out->compr %p",
3244 __func__, out->offload_state, cmd->cmd, out->compr);
3245
3246 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3247 free(cmd);
3248 break;
3249 }
3250
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003251 // allow OFFLOAD_CMD_ERROR reporting during standby
3252 // this is needed to handle failures during compress_open
3253 // Note however that on a pause timeout, the stream is closed
3254 // and no offload usecase will be active. Therefore this
3255 // special case is needed for compress_open failures alone
3256 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3257 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003258 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003259 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003260 pthread_cond_signal(&out->cond);
3261 continue;
3262 }
3263 out->offload_thread_blocked = true;
3264 pthread_mutex_unlock(&out->lock);
3265 send_callback = false;
3266 switch(cmd->cmd) {
3267 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003268 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003269 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003270 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003271 send_callback = true;
3272 event = STREAM_CBK_EVENT_WRITE_READY;
3273 break;
3274 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003275 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303276 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003277 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303278 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003279 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303280 if (ret < 0)
3281 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303282 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303283 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003284 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003285 else
3286 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003287 if (-ENETRESET != ret && !(-EINTR == ret &&
3288 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303289 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303290 pthread_mutex_lock(&out->lock);
3291 out->send_new_metadata = 1;
3292 out->send_next_track_params = true;
3293 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303294 event = STREAM_CBK_EVENT_DRAIN_READY;
3295 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3296 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303297 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003298 break;
3299 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003300 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003301 ret = compress_drain(out->compr);
3302 ALOGD("copl(%p):out of compress_drain", out);
3303 // EINTR check avoids drain interruption due to SSR
3304 if (-ENETRESET != ret && !(-EINTR == ret &&
3305 CARD_STATUS_OFFLINE == out->card_status)) {
3306 send_callback = true;
3307 event = STREAM_CBK_EVENT_DRAIN_READY;
3308 } else
3309 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003310 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303311 case OFFLOAD_CMD_ERROR:
3312 ALOGD("copl(%p): sending error callback to AF", out);
3313 send_callback = true;
3314 event = STREAM_CBK_EVENT_ERROR;
3315 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003316 default:
3317 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3318 break;
3319 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003320 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003321 out->offload_thread_blocked = false;
3322 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003323 if (send_callback && out->client_callback) {
3324 ALOGVV("%s: sending client_callback event %d", __func__, event);
3325 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003326 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 free(cmd);
3328 }
3329
3330 pthread_cond_signal(&out->cond);
3331 while (!list_empty(&out->offload_cmd_list)) {
3332 item = list_head(&out->offload_cmd_list);
3333 list_remove(item);
3334 free(node_to_item(item, struct offload_cmd, node));
3335 }
3336 pthread_mutex_unlock(&out->lock);
3337
3338 return NULL;
3339}
3340
3341static int create_offload_callback_thread(struct stream_out *out)
3342{
3343 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3344 list_init(&out->offload_cmd_list);
3345 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3346 offload_thread_loop, out);
3347 return 0;
3348}
3349
3350static int destroy_offload_callback_thread(struct stream_out *out)
3351{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003352 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 stop_compressed_output_l(out);
3354 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3355
3356 pthread_mutex_unlock(&out->lock);
3357 pthread_join(out->offload_thread, (void **) NULL);
3358 pthread_cond_destroy(&out->offload_cond);
3359
3360 return 0;
3361}
3362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363static int stop_output_stream(struct stream_out *out)
3364{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303365 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 struct audio_usecase *uc_info;
3367 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003368 bool has_voip_usecase =
3369 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370
Eric Laurent994a6932013-07-17 11:51:42 -07003371 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003372 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 uc_info = get_usecase_from_list(adev, out->usecase);
3374 if (uc_info == NULL) {
3375 ALOGE("%s: Could not find the usecase (%d) in the list",
3376 __func__, out->usecase);
3377 return -EINVAL;
3378 }
3379
Derek Chenea197282019-01-07 17:35:01 -08003380 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3381 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003382
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003383 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303384 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003385 if (adev->visualizer_stop_output != NULL)
3386 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003387
3388 audio_extn_dts_remove_state_notifier_node(out->usecase);
3389
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003390 if (adev->offload_effects_stop_output != NULL)
3391 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003392 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3393 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3394 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003395 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003396
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003397 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3398 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003399 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003400 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003401
Eric Laurent150dbfe2013-02-27 14:31:02 -08003402 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003403 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003404
3405 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003406 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407
Aalique Grahame22e49102018-12-18 14:23:57 -08003408 audio_extn_extspk_update(adev->extspk);
3409
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003410 if (is_offload_usecase(out->usecase)) {
3411 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3412 adev->dsp_bit_width_enforce_mode,
3413 false);
3414 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003415 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3416 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3417 false);
3418
3419 if (ret != 0)
3420 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3421 /* default service interval was successfully updated,
3422 reopen USB backend with new service interval */
3423 ret = 0;
3424 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003425
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003426 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303427 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003428 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303429 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003430 ALOGV("Disable passthrough , reset mixer to pcm");
3431 /* NO_PASSTHROUGH */
3432 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003433 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003434 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3435 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003436
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303437 /* Must be called after removing the usecase from list */
3438 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303439 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303440
Manish Dewangan21a850a2017-08-14 12:03:55 +05303441 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003442 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3443 if (ret < 0)
3444 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3445 }
3446
juyuchen2d415992018-11-16 14:15:16 +08003447 /* 1) media + voip output routing to handset must route media back to
3448 speaker when voip stops.
3449 2) trigger voip input to reroute when voip output changes to
3450 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003451 if (has_voip_usecase ||
3452 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3453 struct listnode *node;
3454 struct audio_usecase *usecase;
3455 list_for_each(node, &adev->usecase_list) {
3456 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003457 if ((usecase->type == PCM_CAPTURE &&
3458 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3459 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003460 continue;
3461
3462 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3463 __func__, usecase->id, use_case_table[usecase->id],
3464 out->usecase, use_case_table[out->usecase]);
3465 select_devices(adev, usecase->id);
3466 }
3467 }
3468
Garmond Leung5fd0b552018-04-17 11:56:12 -07003469 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003470 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 return ret;
3472}
3473
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003474struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3475 unsigned int flags, unsigned int pcm_open_retry_count,
3476 struct pcm_config *config)
3477{
3478 struct pcm* pcm = NULL;
3479
3480 while (1) {
3481 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3482 if (pcm == NULL || !pcm_is_ready(pcm)) {
3483 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3484 if (pcm != NULL) {
3485 pcm_close(pcm);
3486 pcm = NULL;
3487 }
3488 if (pcm_open_retry_count-- == 0)
3489 return NULL;
3490
3491 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3492 continue;
3493 }
3494 break;
3495 }
3496
3497 if (pcm_is_ready(pcm)) {
3498 int ret = pcm_prepare(pcm);
3499 if (ret < 0) {
3500 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3501 pcm_close(pcm);
3502 pcm = NULL;
3503 }
3504 }
3505
3506 return pcm;
3507}
3508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509int start_output_stream(struct stream_out *out)
3510{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 struct audio_usecase *uc_info;
3513 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003514 char mixer_ctl_name[128];
3515 struct mixer_ctl *ctl = NULL;
3516 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303517 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003518 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
Haynes Mathew George380745d2017-10-04 15:27:45 -07003520 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003521 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3522 ret = -EINVAL;
3523 goto error_config;
3524 }
3525
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003526 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303527 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003528 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303529
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303530 if (CARD_STATUS_OFFLINE == out->card_status ||
3531 CARD_STATUS_OFFLINE == adev->card_status) {
3532 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303533 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303534 goto error_config;
3535 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303536
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003537 //Update incall music usecase to reflect correct voice session
3538 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3539 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3540 if (ret != 0) {
3541 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3542 __func__, ret);
3543 goto error_config;
3544 }
3545 }
3546
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303547 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003548 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003549 if (out->devices &
3550 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303551 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303552 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303553 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3554 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3555 ret = -EAGAIN;
3556 goto error_config;
3557 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303558 }
3559 }
3560 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303561 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3562 if (!adev->bt_sco_on) {
3563 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3564 //combo usecase just by pass a2dp
3565 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3566 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3567 } else {
3568 ALOGE("%s: SCO profile is not ready, return error", __func__);
3569 ret = -EAGAIN;
3570 goto error_config;
3571 }
3572 }
3573 }
3574
Eric Laurentb23d5282013-05-14 15:27:20 -07003575 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 if (out->pcm_device_id < 0) {
3577 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3578 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003579 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003580 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 }
3582
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003583 if (is_haptic_usecase) {
3584 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3585 if (adev->haptic_pcm_device_id < 0) {
3586 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3587 __func__, adev->haptic_pcm_device_id, out->usecase);
3588 ret = -EINVAL;
3589 goto error_config;
3590 }
3591 }
3592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003594
3595 if (!uc_info) {
3596 ret = -ENOMEM;
3597 goto error_config;
3598 }
3599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 uc_info->id = out->usecase;
3601 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003602 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003603 uc_info->devices = out->devices;
3604 uc_info->in_snd_device = SND_DEVICE_NONE;
3605 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003606
3607 /* This must be called before adding this usecase to the list */
3608 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3609 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3610 /* USB backend is not reopened immediately.
3611 This is eventually done as part of select_devices */
3612 }
3613
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003614 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615
Wei Wangf7ca6c92017-11-21 14:51:20 -08003616 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303617 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3618 adev->perf_lock_opts,
3619 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303620
3621 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303622 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303623 if (audio_extn_passthru_is_enabled() &&
3624 audio_extn_passthru_is_passthrough_stream(out)) {
3625 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303626 }
3627 }
3628
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303629 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003630 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303631 if (!a2dp_combo) {
3632 check_a2dp_restore_l(adev, out, false);
3633 } else {
3634 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003635 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3636 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3637 else
3638 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303639 select_devices(adev, out->usecase);
3640 out->devices = dev;
3641 }
3642 } else {
3643 select_devices(adev, out->usecase);
3644 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003645
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003646 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3647 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003648 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003649 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003650
Derek Chenea197282019-01-07 17:35:01 -08003651 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3652 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003653
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003654 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3655 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003656
3657 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003658 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003659 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3660 ALOGE("%s: pcm stream not ready", __func__);
3661 goto error_open;
3662 }
3663 ret = pcm_start(out->pcm);
3664 if (ret < 0) {
3665 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3666 goto error_open;
3667 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003668 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003669 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003670 unsigned int flags = PCM_OUT;
3671 unsigned int pcm_open_retry_count = 0;
3672 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3673 flags |= PCM_MMAP | PCM_NOIRQ;
3674 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003675 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003676 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003677 } else
3678 flags |= PCM_MONOTONIC;
3679
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003680 if ((adev->vr_audio_mode_enabled) &&
3681 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3682 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3683 "PCM_Dev %d Topology", out->pcm_device_id);
3684 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3685 if (!ctl) {
3686 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3687 __func__, mixer_ctl_name);
3688 } else {
3689 //if success use ULLPP
3690 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3691 __func__, mixer_ctl_name, out->pcm_device_id);
3692 //There is a still a possibility that some sessions
3693 // that request for FAST|RAW when 3D audio is active
3694 //can go through ULLPP. Ideally we expects apps to
3695 //listen to audio focus and stop concurrent playback
3696 //Also, we will look for mode flag (voice_in_communication)
3697 //before enabling the realtime flag.
3698 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3699 }
3700 }
3701
Surendar Karka91fa3682018-07-02 18:12:12 +05303702 if (out->realtime)
3703 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3704 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3705
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003706 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3707 flags, pcm_open_retry_count,
3708 &(out->config));
3709 if (out->pcm == NULL) {
3710 ret = -EIO;
3711 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003713
3714 if (is_haptic_usecase) {
3715 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3716 adev->haptic_pcm_device_id,
3717 flags, pcm_open_retry_count,
3718 &(adev->haptics_config));
3719 // failure to open haptics pcm shouldnt stop audio,
3720 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003721
3722 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3723 ALOGD("%s: enable haptic audio synchronization", __func__);
3724 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3725 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003726 }
3727
Surendar Karka91fa3682018-07-02 18:12:12 +05303728 if (!out->realtime)
3729 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303730 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003731
Zhou Song2b8f28f2017-09-11 10:51:38 +08003732 // apply volume for voip playback after path is set up
3733 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3734 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303735 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3736 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303737 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3738 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003739 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3740 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303741 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003742 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003743 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303744 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003745 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3746 adev->dsp_bit_width_enforce_mode,
3747 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003749 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003750 out->compr = compress_open(adev->snd_card,
3751 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003752 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003753 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303754 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303755 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3756 adev->card_status = CARD_STATUS_OFFLINE;
3757 out->card_status = CARD_STATUS_OFFLINE;
3758 ret = -EIO;
3759 goto error_open;
3760 }
3761
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003763 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003764 compress_close(out->compr);
3765 out->compr = NULL;
3766 ret = -EIO;
3767 goto error_open;
3768 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303769 /* compress_open sends params of the track, so reset the flag here */
3770 out->is_compr_metadata_avail = false;
3771
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003772 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003773 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003774
Fred Oh3f43e742015-03-04 18:42:34 -08003775 /* Since small bufs uses blocking writes, a write will be blocked
3776 for the default max poll time (20s) in the event of an SSR.
3777 Reduce the poll time to observe and deal with SSR faster.
3778 */
Ashish Jain5106d362016-05-11 19:23:33 +05303779 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003780 compress_set_max_poll_wait(out->compr, 1000);
3781 }
3782
Manish Dewangan69426c82017-01-30 17:35:36 +05303783 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303784 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303785
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003786 audio_extn_dts_create_state_notifier_node(out->usecase);
3787 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3788 popcount(out->channel_mask),
3789 out->playback_started);
3790
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003791#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303792 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003793 audio_extn_dolby_send_ddp_endp_params(adev);
3794#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303795 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3796 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003797 if (adev->visualizer_start_output != NULL)
3798 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3799 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303800 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003801 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003802 }
Derek Chenf13dd492018-11-13 14:53:51 -08003803
3804 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3805 /* Update cached volume from media to offload/direct stream */
3806 struct listnode *node = NULL;
3807 list_for_each(node, &adev->active_outputs_list) {
3808 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3809 streams_output_ctxt_t,
3810 list);
3811 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3812 out->volume_l = out_ctxt->output->volume_l;
3813 out->volume_r = out_ctxt->output->volume_r;
3814 }
3815 }
3816 out_set_compr_volume(&out->stream,
3817 out->volume_l, out->volume_r);
3818 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003820
3821 if (ret == 0) {
3822 register_out_stream(out);
3823 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003824 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3825 ALOGE("%s: pcm stream not ready", __func__);
3826 goto error_open;
3827 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003828 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003829 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003830 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003831 if (ret < 0)
3832 goto error_open;
3833 }
3834 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003835 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303836 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003837 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003838
vivek mehtad15d2bf2019-05-17 13:35:10 -07003839 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3840 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3841 audio_low_latency_hint_start();
3842 }
3843
Manish Dewangan21a850a2017-08-14 12:03:55 +05303844 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003845 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003846 if (ret < 0)
3847 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3848 }
3849
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003850 // consider a scenario where on pause lower layers are tear down.
3851 // so on resume, swap mixer control need to be sent only when
3852 // backend is active, hence rather than sending from enable device
3853 // sending it from start of streamtream
3854
3855 platform_set_swap_channels(adev, true);
3856
Haynes Mathew George380745d2017-10-04 15:27:45 -07003857 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303858 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003859 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003860error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003861 if (adev->haptic_pcm) {
3862 pcm_close(adev->haptic_pcm);
3863 adev->haptic_pcm = NULL;
3864 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003865 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303866 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003868error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303869 /*
3870 * sleep 50ms to allow sufficient time for kernel
3871 * drivers to recover incases like SSR.
3872 */
3873 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003874 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303875 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003876 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877}
3878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879static int check_input_parameters(uint32_t sample_rate,
3880 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003881 int channel_count,
3882 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003884 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303886 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3887 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3888 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003889 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003890 !audio_extn_compr_cap_format_supported(format) &&
3891 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003892 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003893
Aalique Grahame22e49102018-12-18 14:23:57 -08003894 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3895 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3896 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3897 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3898 return -EINVAL;
3899 }
3900
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003901 switch (channel_count) {
3902 case 1:
3903 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303904 case 3:
3905 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003906 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003907 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303908 case 10:
3909 case 12:
3910 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003911 break;
3912 default:
3913 ret = -EINVAL;
3914 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915
3916 switch (sample_rate) {
3917 case 8000:
3918 case 11025:
3919 case 12000:
3920 case 16000:
3921 case 22050:
3922 case 24000:
3923 case 32000:
3924 case 44100:
3925 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003926 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303927 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003928 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303929 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 break;
3931 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003932 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 }
3934
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003935 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936}
3937
Naresh Tanniru04f71882018-06-26 17:46:22 +05303938
3939/** Add a value in a list if not already present.
3940 * @return true if value was successfully inserted or already present,
3941 * false if the list is full and does not contain the value.
3942 */
3943static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3944 for (size_t i = 0; i < list_length; i++) {
3945 if (list[i] == value) return true; // value is already present
3946 if (list[i] == 0) { // no values in this slot
3947 list[i] = value;
3948 return true; // value inserted
3949 }
3950 }
3951 return false; // could not insert value
3952}
3953
3954/** Add channel_mask in supported_channel_masks if not already present.
3955 * @return true if channel_mask was successfully inserted or already present,
3956 * false if supported_channel_masks is full and does not contain channel_mask.
3957 */
3958static void register_channel_mask(audio_channel_mask_t channel_mask,
3959 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3960 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3961 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3962}
3963
3964/** Add format in supported_formats if not already present.
3965 * @return true if format was successfully inserted or already present,
3966 * false if supported_formats is full and does not contain format.
3967 */
3968static void register_format(audio_format_t format,
3969 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3970 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3971 "%s: stream can not declare supporting its format %x", __func__, format);
3972}
3973/** Add sample_rate in supported_sample_rates if not already present.
3974 * @return true if sample_rate was successfully inserted or already present,
3975 * false if supported_sample_rates is full and does not contain sample_rate.
3976 */
3977static void register_sample_rate(uint32_t sample_rate,
3978 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3979 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3980 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3981}
3982
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003983static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3984{
3985 uint32_t high = num1, low = num2, temp = 0;
3986
3987 if (!num1 || !num2)
3988 return 0;
3989
3990 if (num1 < num2) {
3991 high = num2;
3992 low = num1;
3993 }
3994
3995 while (low != 0) {
3996 temp = low;
3997 low = high % low;
3998 high = temp;
3999 }
4000 return (num1 * num2)/high;
4001}
4002
4003static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4004{
4005 uint32_t remainder = 0;
4006
4007 if (!multiplier)
4008 return num;
4009
4010 remainder = num % multiplier;
4011 if (remainder)
4012 num += (multiplier - remainder);
4013
4014 return num;
4015}
4016
Aalique Grahame22e49102018-12-18 14:23:57 -08004017static size_t get_stream_buffer_size(size_t duration_ms,
4018 uint32_t sample_rate,
4019 audio_format_t format,
4020 int channel_count,
4021 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022{
4023 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004024 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025
Aalique Grahame22e49102018-12-18 14:23:57 -08004026 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004027 if (is_low_latency)
4028 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304029
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004030 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004031 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032
Ralf Herzbd08d632018-09-28 15:50:49 +02004033 /* make sure the size is multiple of 32 bytes and additionally multiple of
4034 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004035 * At 48 kHz mono 16-bit PCM:
4036 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4037 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004038 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004039 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004040 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004041
4042 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043}
4044
Aalique Grahame22e49102018-12-18 14:23:57 -08004045static size_t get_input_buffer_size(uint32_t sample_rate,
4046 audio_format_t format,
4047 int channel_count,
4048 bool is_low_latency)
4049{
4050 /* Don't know if USB HIFI in this context so use true to be conservative */
4051 if (check_input_parameters(sample_rate, format, channel_count,
4052 true /*is_usb_hifi */) != 0)
4053 return 0;
4054
4055 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4056 sample_rate,
4057 format,
4058 channel_count,
4059 is_low_latency);
4060}
4061
Derek Chenf6318be2017-06-12 17:16:24 -04004062size_t get_output_period_size(uint32_t sample_rate,
4063 audio_format_t format,
4064 int channel_count,
4065 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304066{
4067 size_t size = 0;
4068 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4069
4070 if ((duration == 0) || (sample_rate == 0) ||
4071 (bytes_per_sample == 0) || (channel_count == 0)) {
4072 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4073 bytes_per_sample, channel_count);
4074 return -EINVAL;
4075 }
4076
4077 size = (sample_rate *
4078 duration *
4079 bytes_per_sample *
4080 channel_count) / 1000;
4081 /*
4082 * To have same PCM samples for all channels, the buffer size requires to
4083 * be multiple of (number of channels * bytes per sample)
4084 * For writes to succeed, the buffer must be written at address which is multiple of 32
4085 */
4086 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4087
4088 return (size/(channel_count * bytes_per_sample));
4089}
4090
Zhou Song48453a02018-01-10 17:50:59 +08004091static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304092{
4093 uint64_t actual_frames_rendered = 0;
4094 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4095
4096 /* This adjustment accounts for buffering after app processor.
4097 * It is based on estimated DSP latency per use case, rather than exact.
4098 */
4099 int64_t platform_latency = platform_render_latency(out->usecase) *
4100 out->sample_rate / 1000000LL;
4101
Zhou Song48453a02018-01-10 17:50:59 +08004102 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304103 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4104 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4105 * hence only estimate.
4106 */
4107 int64_t signed_frames = out->written - kernel_buffer_size;
4108
4109 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4110
Zhou Song48453a02018-01-10 17:50:59 +08004111 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304112 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004113 if (timestamp != NULL )
4114 *timestamp = out->writeAt;
4115 } else if (timestamp != NULL) {
4116 clock_gettime(CLOCK_MONOTONIC, timestamp);
4117 }
4118 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304119
4120 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4121 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4122 (long long int)out->written, (int)kernel_buffer_size,
4123 audio_bytes_per_sample(out->compr_config.codec->format),
4124 popcount(out->channel_mask));
4125
4126 return actual_frames_rendered;
4127}
4128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4130{
4131 struct stream_out *out = (struct stream_out *)stream;
4132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004133 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134}
4135
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004136static int out_set_sample_rate(struct audio_stream *stream __unused,
4137 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138{
4139 return -ENOSYS;
4140}
4141
4142static size_t out_get_buffer_size(const struct audio_stream *stream)
4143{
4144 struct stream_out *out = (struct stream_out *)stream;
4145
Varun Balaraje49253e2017-07-06 19:48:56 +05304146 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304147 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304148 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304149 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4150 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4151 else
4152 return out->compr_config.fragment_size;
4153 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004154 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304155 else if (is_offload_usecase(out->usecase) &&
4156 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304157 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004158
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004159 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004160 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161}
4162
4163static uint32_t out_get_channels(const struct audio_stream *stream)
4164{
4165 struct stream_out *out = (struct stream_out *)stream;
4166
4167 return out->channel_mask;
4168}
4169
4170static audio_format_t out_get_format(const struct audio_stream *stream)
4171{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004172 struct stream_out *out = (struct stream_out *)stream;
4173
4174 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175}
4176
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004177static int out_set_format(struct audio_stream *stream __unused,
4178 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179{
4180 return -ENOSYS;
4181}
4182
4183static int out_standby(struct audio_stream *stream)
4184{
4185 struct stream_out *out = (struct stream_out *)stream;
4186 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004187 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004188
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304189 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4190 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004192 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004194 if (adev->adm_deregister_stream)
4195 adev->adm_deregister_stream(adev->adm_data, out->handle);
4196
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004197 if (is_offload_usecase(out->usecase))
4198 stop_compressed_output_l(out);
4199
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004200 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05304201
4202 amplifier_output_stream_standby((struct audio_stream_out *) stream);
4203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004205 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4206 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304207 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004208 pthread_mutex_unlock(&adev->lock);
4209 pthread_mutex_unlock(&out->lock);
4210 ALOGD("VOIP output entered standby");
4211 return 0;
4212 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004213 if (out->pcm) {
4214 pcm_close(out->pcm);
4215 out->pcm = NULL;
4216 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004217 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4218 do_stop = out->playback_started;
4219 out->playback_started = false;
4220 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004221 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004222 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304223 out->send_next_track_params = false;
4224 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004225 out->gapless_mdata.encoder_delay = 0;
4226 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004227 if (out->compr != NULL) {
4228 compress_close(out->compr);
4229 out->compr = NULL;
4230 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004231 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004232 if (do_stop) {
4233 stop_output_stream(out);
4234 }
Lakshman Chaluvaraju40459022019-06-24 10:04:52 +05304235 // if fm is active route on selected device in UI
4236 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004237 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 }
4239 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304240 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241 return 0;
4242}
4243
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304244static int out_on_error(struct audio_stream *stream)
4245{
4246 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004247 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304248
4249 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004250 // always send CMD_ERROR for offload streams, this
4251 // is needed e.g. when SSR happens within compress_open
4252 // since the stream is active, offload_callback_thread is also active.
4253 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4254 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004255 }
4256 pthread_mutex_unlock(&out->lock);
4257
4258 status = out_standby(&out->stream.common);
4259
4260 lock_output_stream(out);
4261 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004262 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304263 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304264
4265 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4266 ALOGD("Setting previous card status if offline");
4267 out->prev_card_status_offline = true;
4268 }
4269
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304270 pthread_mutex_unlock(&out->lock);
4271
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004272 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304273}
4274
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304275/*
4276 *standby implementation without locks, assumes that the callee already
4277 *has taken adev and out lock.
4278 */
4279int out_standby_l(struct audio_stream *stream)
4280{
4281 struct stream_out *out = (struct stream_out *)stream;
4282 struct audio_device *adev = out->dev;
4283
4284 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4285 stream, out->usecase, use_case_table[out->usecase]);
4286
4287 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004288 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304289 if (adev->adm_deregister_stream)
4290 adev->adm_deregister_stream(adev->adm_data, out->handle);
4291
4292 if (is_offload_usecase(out->usecase))
4293 stop_compressed_output_l(out);
4294
4295 out->standby = true;
4296 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4297 voice_extn_compress_voip_close_output_stream(stream);
4298 out->started = 0;
4299 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004300 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304301 return 0;
4302 } else if (!is_offload_usecase(out->usecase)) {
4303 if (out->pcm) {
4304 pcm_close(out->pcm);
4305 out->pcm = NULL;
4306 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004307 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4308 if (adev->haptic_pcm) {
4309 pcm_close(adev->haptic_pcm);
4310 adev->haptic_pcm = NULL;
4311 }
4312
4313 if (adev->haptic_buffer != NULL) {
4314 free(adev->haptic_buffer);
4315 adev->haptic_buffer = NULL;
4316 adev->haptic_buffer_size = 0;
4317 }
4318 adev->haptic_pcm_device_id = 0;
4319 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304320 } else {
4321 ALOGD("copl(%p):standby", out);
4322 out->send_next_track_params = false;
4323 out->is_compr_metadata_avail = false;
4324 out->gapless_mdata.encoder_delay = 0;
4325 out->gapless_mdata.encoder_padding = 0;
4326 if (out->compr != NULL) {
4327 compress_close(out->compr);
4328 out->compr = NULL;
4329 }
4330 }
4331 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004332 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304333 }
4334 ALOGD("%s: exit", __func__);
4335 return 0;
4336}
4337
Aalique Grahame22e49102018-12-18 14:23:57 -08004338static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339{
Aalique Grahame22e49102018-12-18 14:23:57 -08004340 struct stream_out *out = (struct stream_out *)stream;
4341
4342 // We try to get the lock for consistency,
4343 // but it isn't necessary for these variables.
4344 // If we're not in standby, we may be blocked on a write.
4345 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4346 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4347 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4348
4349 if (locked) {
4350 pthread_mutex_unlock(&out->lock);
4351 }
4352
4353 // dump error info
4354 (void)error_log_dump(
4355 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357 return 0;
4358}
4359
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004360static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4361{
4362 int ret = 0;
4363 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004364
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004365 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004366 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004367 return -EINVAL;
4368 }
4369
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304370 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004371
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004372 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4373 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304374 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004375 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004376 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4377 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304378 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004379 }
4380
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004381 ALOGV("%s new encoder delay %u and padding %u", __func__,
4382 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4383
4384 return 0;
4385}
4386
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004387static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4388{
4389 return out == adev->primary_output || out == adev->voice_tx_output;
4390}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004391
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304392// note: this call is safe only if the stream_cb is
4393// removed first in close_output_stream (as is done now).
4394static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4395{
4396 if (!stream || !parms)
4397 return;
4398
4399 struct stream_out *out = (struct stream_out *)stream;
4400 struct audio_device *adev = out->dev;
4401
4402 card_status_t status;
4403 int card;
4404 if (parse_snd_card_status(parms, &card, &status) < 0)
4405 return;
4406
4407 pthread_mutex_lock(&adev->lock);
4408 bool valid_cb = (card == adev->snd_card);
4409 pthread_mutex_unlock(&adev->lock);
4410
4411 if (!valid_cb)
4412 return;
4413
4414 lock_output_stream(out);
4415 if (out->card_status != status)
4416 out->card_status = status;
4417 pthread_mutex_unlock(&out->lock);
4418
4419 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4420 use_case_table[out->usecase],
4421 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4422
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304423 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304424 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304425 if (voice_is_call_state_active(adev) &&
4426 out == adev->primary_output) {
4427 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4428 pthread_mutex_lock(&adev->lock);
4429 voice_stop_call(adev);
4430 adev->mode = AUDIO_MODE_NORMAL;
4431 pthread_mutex_unlock(&adev->lock);
4432 }
4433 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304434 return;
4435}
4436
Kevin Rocardfce19002017-08-07 19:21:36 -07004437static int get_alive_usb_card(struct str_parms* parms) {
4438 int card;
4439 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4440 !audio_extn_usb_alive(card)) {
4441 return card;
4442 }
4443 return -ENODEV;
4444}
4445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4447{
4448 struct stream_out *out = (struct stream_out *)stream;
4449 struct audio_device *adev = out->dev;
4450 struct str_parms *parms;
4451 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004452 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304453 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004454 bool reconfig = false;
4455 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456
sangwoobc677242013-08-08 16:53:43 +09004457 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004458 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304460 if (!parms)
4461 goto error;
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05304462
4463 amplifier_out_set_parameters(parms);
4464
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004465 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4466 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004468 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004469 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004471 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004472 * When HDMI cable is unplugged the music playback is paused and
4473 * the policy manager sends routing=0. But the audioflinger continues
4474 * to write data until standby time (3sec). As the HDMI core is
4475 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004476 * Avoid this by routing audio to speaker until standby.
4477 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004478 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4479 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304480 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004481 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4482 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004483 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304484 /*
4485 * When A2DP is disconnected the
4486 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004487 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304488 * (3sec). As BT is turned off, the write gets blocked.
4489 * Avoid this by routing audio to speaker until standby.
4490 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004491 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004492 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004493 !audio_extn_a2dp_source_is_ready() &&
4494 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304495 val = AUDIO_DEVICE_OUT_SPEAKER;
4496 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304497 /*
4498 * When USB headset is disconnected the music platback paused
4499 * and the policy manager send routing=0. But if the USB is connected
4500 * back before the standby time, AFE is not closed and opened
4501 * when USB is connected back. So routing to speker will guarantee
4502 * AFE reconfiguration and AFE will be opend once USB is connected again
4503 */
4504 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4505 (val == AUDIO_DEVICE_NONE) &&
4506 !audio_extn_usb_connected(parms)) {
4507 val = AUDIO_DEVICE_OUT_SPEAKER;
4508 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304509 /* To avoid a2dp to sco overlapping / BT device improper state
4510 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304511 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304512 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004513 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004514 if (val &
4515 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304516 //combo usecase just by pass a2dp
4517 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304518 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304519 } else {
4520 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4521 /* update device to a2dp and don't route as BT returned error
4522 * However it is still possible a2dp routing called because
4523 * of current active device disconnection (like wired headset)
4524 */
4525 out->devices = val;
4526 pthread_mutex_unlock(&out->lock);
4527 pthread_mutex_unlock(&adev->lock);
4528 goto error;
4529 }
4530 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304531 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004532
4533 audio_devices_t new_dev = val;
4534
4535 // Workaround: If routing to an non existing usb device, fail gracefully
4536 // The routing request will otherwise block during 10 second
4537 int card;
4538 if (audio_is_usb_out_device(new_dev) &&
4539 (card = get_alive_usb_card(parms)) >= 0) {
4540
4541 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4542 pthread_mutex_unlock(&adev->lock);
4543 pthread_mutex_unlock(&out->lock);
4544 ret = -ENOSYS;
4545 goto routing_fail;
4546 }
4547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004548 /*
4549 * select_devices() call below switches all the usecases on the same
4550 * backend to the new device. Refer to check_usecases_codec_backend() in
4551 * the select_devices(). But how do we undo this?
4552 *
4553 * For example, music playback is active on headset (deep-buffer usecase)
4554 * and if we go to ringtones and select a ringtone, low-latency usecase
4555 * will be started on headset+speaker. As we can't enable headset+speaker
4556 * and headset devices at the same time, select_devices() switches the music
4557 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4558 * So when the ringtone playback is completed, how do we undo the same?
4559 *
4560 * We are relying on the out_set_parameters() call on deep-buffer output,
4561 * once the ringtone playback is ended.
4562 * NOTE: We should not check if the current devices are same as new devices.
4563 * Because select_devices() must be called to switch back the music
4564 * playback to headset.
4565 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004566 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004567 audio_devices_t new_dev = val;
4568 bool same_dev = out->devices == new_dev;
4569 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004570
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004571 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004572 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004573 if (adev->mode == AUDIO_MODE_IN_CALL) {
4574 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004575 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4576 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4577 audio_extn_usb_set_service_interval(true /*playback*/,
4578 service_interval,
4579 &reconfig);
4580 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4581 }
4582 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004583 }
4584 } else {
4585 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004586 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004587 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004588 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004589
4590 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004591 if (!same_dev) {
4592 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304593 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4594 adev->perf_lock_opts,
4595 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004596 if (adev->adm_on_routing_change)
4597 adev->adm_on_routing_change(adev->adm_data,
4598 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004599 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304600 if (!bypass_a2dp) {
4601 select_devices(adev, out->usecase);
4602 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004603 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4604 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4605 else
4606 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304607 select_devices(adev, out->usecase);
4608 out->devices = new_dev;
4609 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004610
4611 if (!same_dev) {
4612 // on device switch force swap, lower functions will make sure
4613 // to check if swap is allowed or not.
4614 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304615 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004616 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304617 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4618 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004619 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304620 pthread_mutex_lock(&out->compr_mute_lock);
4621 out->a2dp_compress_mute = false;
4622 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4623 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004624 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4625 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304626 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004627 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004628 }
4629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004631 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004632
4633 /*handles device and call state changes*/
4634 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004636 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004637
4638 if (out == adev->primary_output) {
4639 pthread_mutex_lock(&adev->lock);
4640 audio_extn_set_parameters(adev, parms);
4641 pthread_mutex_unlock(&adev->lock);
4642 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004643 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004644 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004645 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004646
4647 audio_extn_dts_create_state_notifier_node(out->usecase);
4648 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4649 popcount(out->channel_mask),
4650 out->playback_started);
4651
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004652 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004653 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004654
Surendar Karkaf51b5842018-04-26 11:28:38 +05304655 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4656 sizeof(value));
4657 if (err >= 0) {
4658 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4659 audio_extn_send_dual_mono_mixing_coefficients(out);
4660 }
4661
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304662 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4663 if (err >= 0) {
4664 strlcpy(out->profile, value, sizeof(out->profile));
4665 ALOGV("updating stream profile with value '%s'", out->profile);
4666 lock_output_stream(out);
4667 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4668 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004669 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304670 out->sample_rate, out->bit_width,
4671 out->channel_mask, out->profile,
4672 &out->app_type_cfg);
4673 pthread_mutex_unlock(&out->lock);
4674 }
4675
Alexy Joseph98988832017-01-13 14:56:59 -08004676 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004677 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4678 // and vendor.audio.hal.output.suspend.supported is set to true
4679 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004680 //check suspend parameter only for low latency and if the property
4681 //is enabled
4682 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4683 ALOGI("%s: got suspend_playback %s", __func__, value);
4684 lock_output_stream(out);
4685 if (!strncmp(value, "false", 5)) {
4686 //suspend_playback=false is supposed to set QOS value back to 75%
4687 //the mixer control sent with value Enable will achieve that
4688 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4689 } else if (!strncmp (value, "true", 4)) {
4690 //suspend_playback=true is supposed to remove QOS value
4691 //resetting the mixer control will set the default value
4692 //for the mixer control which is Disable and this removes the QOS vote
4693 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4694 } else {
4695 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4696 " got %s", __func__, value);
4697 ret = -1;
4698 }
4699
4700 if (ret != 0) {
4701 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4702 __func__, out->pm_qos_mixer_path, ret);
4703 }
4704
4705 pthread_mutex_unlock(&out->lock);
4706 }
4707 }
4708 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304710error:
Eric Laurent994a6932013-07-17 11:51:42 -07004711 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712 return ret;
4713}
4714
Paul McLeana50b7332018-12-17 08:24:21 -07004715static int in_set_microphone_direction(const struct audio_stream_in *stream,
4716 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004717 struct stream_in *in = (struct stream_in *)stream;
4718
4719 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4720
4721 in->direction = dir;
4722
4723 if (in->standby)
4724 return 0;
4725
4726 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004727}
4728
4729static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004730 struct stream_in *in = (struct stream_in *)stream;
4731
4732 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4733
4734 if (zoom > 1.0 || zoom < -1.0)
4735 return -EINVAL;
4736
4737 in->zoom = zoom;
4738
4739 if (in->standby)
4740 return 0;
4741
4742 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004743}
4744
4745
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004746static bool stream_get_parameter_channels(struct str_parms *query,
4747 struct str_parms *reply,
4748 audio_channel_mask_t *supported_channel_masks) {
4749 int ret = -1;
4750 char value[512];
4751 bool first = true;
4752 size_t i, j;
4753
4754 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4755 ret = 0;
4756 value[0] = '\0';
4757 i = 0;
4758 while (supported_channel_masks[i] != 0) {
4759 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4760 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4761 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304762 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004763
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304764 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004765 first = false;
4766 break;
4767 }
4768 }
4769 i++;
4770 }
4771 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4772 }
4773 return ret == 0;
4774}
4775
4776static bool stream_get_parameter_formats(struct str_parms *query,
4777 struct str_parms *reply,
4778 audio_format_t *supported_formats) {
4779 int ret = -1;
4780 char value[256];
4781 size_t i, j;
4782 bool first = true;
4783
4784 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4785 ret = 0;
4786 value[0] = '\0';
4787 i = 0;
4788 while (supported_formats[i] != 0) {
4789 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4790 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4791 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304792 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004793 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304794 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004795 first = false;
4796 break;
4797 }
4798 }
4799 i++;
4800 }
4801 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4802 }
4803 return ret == 0;
4804}
4805
4806static bool stream_get_parameter_rates(struct str_parms *query,
4807 struct str_parms *reply,
4808 uint32_t *supported_sample_rates) {
4809
4810 int i;
4811 char value[256];
4812 int ret = -1;
4813 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4814 ret = 0;
4815 value[0] = '\0';
4816 i=0;
4817 int cursor = 0;
4818 while (supported_sample_rates[i]) {
4819 int avail = sizeof(value) - cursor;
4820 ret = snprintf(value + cursor, avail, "%s%d",
4821 cursor > 0 ? "|" : "",
4822 supported_sample_rates[i]);
4823 if (ret < 0 || ret >= avail) {
4824 // if cursor is at the last element of the array
4825 // overwrite with \0 is duplicate work as
4826 // snprintf already put a \0 in place.
4827 // else
4828 // we had space to write the '|' at value[cursor]
4829 // (which will be overwritten) or no space to fill
4830 // the first element (=> cursor == 0)
4831 value[cursor] = '\0';
4832 break;
4833 }
4834 cursor += ret;
4835 ++i;
4836 }
4837 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4838 value);
4839 }
4840 return ret >= 0;
4841}
4842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4844{
4845 struct stream_out *out = (struct stream_out *)stream;
4846 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004847 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848 char value[256];
4849 struct str_parms *reply = str_parms_create();
4850 size_t i, j;
4851 int ret;
4852 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004853
4854 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004855 if (reply) {
4856 str_parms_destroy(reply);
4857 }
4858 if (query) {
4859 str_parms_destroy(query);
4860 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004861 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4862 return NULL;
4863 }
4864
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004865 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4867 if (ret >= 0) {
4868 value[0] = '\0';
4869 i = 0;
4870 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004871 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4872 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004874 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004876 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 first = false;
4878 break;
4879 }
4880 }
4881 i++;
4882 }
4883 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4884 str = str_parms_to_str(reply);
4885 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004886 voice_extn_out_get_parameters(out, query, reply);
4887 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004889
Alexy Joseph62142aa2015-11-16 15:10:34 -08004890
4891 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4892 if (ret >= 0) {
4893 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304894 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4895 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004896 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304897 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004898 } else {
4899 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304900 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004901 }
4902 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004903 if (str)
4904 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004905 str = str_parms_to_str(reply);
4906 }
4907
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004908 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4909 if (ret >= 0) {
4910 value[0] = '\0';
4911 i = 0;
4912 first = true;
4913 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004914 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4915 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004916 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004917 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004918 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004919 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004920 first = false;
4921 break;
4922 }
4923 }
4924 i++;
4925 }
4926 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004927 if (str)
4928 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004929 str = str_parms_to_str(reply);
4930 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004931
4932 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4933 if (ret >= 0) {
4934 value[0] = '\0';
4935 i = 0;
4936 first = true;
4937 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004938 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4939 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004940 if (!first) {
4941 strlcat(value, "|", sizeof(value));
4942 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004943 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004944 first = false;
4945 break;
4946 }
4947 }
4948 i++;
4949 }
4950 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4951 if (str)
4952 free(str);
4953 str = str_parms_to_str(reply);
4954 }
4955
Alexy Joseph98988832017-01-13 14:56:59 -08004956 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4957 //only low latency track supports suspend_resume
4958 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004959 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004960 if (str)
4961 free(str);
4962 str = str_parms_to_str(reply);
4963 }
4964
4965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966 str_parms_destroy(query);
4967 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004968 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004969 return str;
4970}
4971
4972static uint32_t out_get_latency(const struct audio_stream_out *stream)
4973{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004974 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004976 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977
Alexy Josephaa54c872014-12-03 02:46:47 -08004978 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304979 lock_output_stream(out);
4980 latency = audio_extn_utils_compress_get_dsp_latency(out);
4981 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004982 } else if ((out->realtime) ||
4983 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004984 // since the buffer won't be filled up faster than realtime,
4985 // return a smaller number
4986 if (out->config.rate)
4987 period_ms = (out->af_period_multiplier * out->config.period_size *
4988 1000) / (out->config.rate);
4989 else
4990 period_ms = 0;
4991 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004992 } else {
4993 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004994 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004995 }
4996
yidongh0515e042017-07-06 15:00:34 +08004997 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004998 latency += audio_extn_a2dp_get_encoder_latency();
4999
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305000 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005001 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002}
5003
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305004static float AmpToDb(float amplification)
5005{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305006 float db = DSD_VOLUME_MIN_DB;
5007 if (amplification > 0) {
5008 db = 20 * log10(amplification);
5009 if(db < DSD_VOLUME_MIN_DB)
5010 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305011 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305012 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305013}
5014
Arun Mirpuri5d170872019-03-26 13:21:31 -07005015static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5016 float right)
5017{
5018 struct stream_out *out = (struct stream_out *)stream;
5019 long volume = 0;
5020 char mixer_ctl_name[128] = "";
5021 struct audio_device *adev = out->dev;
5022 struct mixer_ctl *ctl = NULL;
5023 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5024 PCM_PLAYBACK);
5025
5026 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5027 "Playback %d Volume", pcm_device_id);
5028 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5029 if (!ctl) {
5030 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5031 __func__, mixer_ctl_name);
5032 return -EINVAL;
5033 }
5034 if (left != right)
5035 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5036 __func__, left, right);
5037 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5038 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5039 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5040 __func__, mixer_ctl_name, volume);
5041 return -EINVAL;
5042 }
5043 return 0;
5044}
5045
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305046static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5047 float right)
5048{
5049 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305050 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305051 char mixer_ctl_name[128];
5052 struct audio_device *adev = out->dev;
5053 struct mixer_ctl *ctl;
5054 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5055 PCM_PLAYBACK);
5056
5057 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5058 "Compress Playback %d Volume", pcm_device_id);
5059 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5060 if (!ctl) {
5061 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5062 __func__, mixer_ctl_name);
5063 return -EINVAL;
5064 }
5065 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5066 __func__, mixer_ctl_name, left, right);
5067 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5068 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5069 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5070
5071 return 0;
5072}
5073
Zhou Song2b8f28f2017-09-11 10:51:38 +08005074static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5075 float right)
5076{
5077 struct stream_out *out = (struct stream_out *)stream;
5078 char mixer_ctl_name[] = "App Type Gain";
5079 struct audio_device *adev = out->dev;
5080 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305081 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005082
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005083 if (!is_valid_volume(left, right)) {
5084 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5085 __func__, left, right);
5086 return -EINVAL;
5087 }
5088
Zhou Song2b8f28f2017-09-11 10:51:38 +08005089 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5090 if (!ctl) {
5091 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5092 __func__, mixer_ctl_name);
5093 return -EINVAL;
5094 }
5095
5096 set_values[0] = 0; //0: Rx Session 1:Tx Session
5097 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305098 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5099 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005100
5101 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5102 return 0;
5103}
5104
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305105static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5106 float right)
5107{
5108 struct stream_out *out = (struct stream_out *)stream;
5109 /* Volume control for pcm playback */
5110 if (left != right) {
5111 return -EINVAL;
5112 } else {
5113 char mixer_ctl_name[128];
5114 struct audio_device *adev = out->dev;
5115 struct mixer_ctl *ctl;
5116 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5117 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5118 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5119 if (!ctl) {
5120 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5121 return -EINVAL;
5122 }
5123
5124 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5125 int ret = mixer_ctl_set_value(ctl, 0, volume);
5126 if (ret < 0) {
5127 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5128 return -EINVAL;
5129 }
5130
5131 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5132
5133 return 0;
5134 }
5135}
5136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137static int out_set_volume(struct audio_stream_out *stream, float left,
5138 float right)
5139{
Eric Laurenta9024de2013-04-04 09:19:12 -07005140 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005141 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305142 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005143
Arun Mirpuri5d170872019-03-26 13:21:31 -07005144 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005145 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5146 /* only take left channel into account: the API is for stereo anyway */
5147 out->muted = (left == 0.0f);
5148 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005149 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305150 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005151 /*
5152 * Set mute or umute on HDMI passthrough stream.
5153 * Only take left channel into account.
5154 * Mute is 0 and unmute 1
5155 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305156 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305157 } else if (out->format == AUDIO_FORMAT_DSD){
5158 char mixer_ctl_name[128] = "DSD Volume";
5159 struct audio_device *adev = out->dev;
5160 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5161
5162 if (!ctl) {
5163 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5164 __func__, mixer_ctl_name);
5165 return -EINVAL;
5166 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305167 volume[0] = (long)(AmpToDb(left));
5168 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305169 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5170 return 0;
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005171 } else if ((out->devices & AUDIO_DEVICE_OUT_BUS) &&
5172 (audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) ==
5173 SND_DEVICE_OUT_BUS_MEDIA)) {
5174 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5175 struct listnode *node = NULL;
5176 list_for_each(node, &adev->active_outputs_list) {
5177 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5178 streams_output_ctxt_t,
5179 list);
5180 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5181 out->volume_l = out_ctxt->output->volume_l;
5182 out->volume_r = out_ctxt->output->volume_r;
5183 }
5184 }
5185 if (!out->a2dp_compress_mute) {
5186 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5187 }
5188 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005189 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305190 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005191 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305192 if (!out->a2dp_compress_mute)
5193 ret = out_set_compr_volume(stream, left, right);
5194 out->volume_l = left;
5195 out->volume_r = right;
5196 pthread_mutex_unlock(&out->compr_mute_lock);
5197 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005198 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005199 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005200 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5201 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5202 if (!out->standby) {
5203 audio_extn_utils_send_app_type_gain(out->dev,
5204 out->app_type_cfg.app_type,
5205 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005206 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005207 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005208 out->volume_l = left;
5209 out->volume_r = right;
5210 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005211 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5212 ALOGV("%s: MMAP set volume called", __func__);
5213 if (!out->standby)
5214 ret = out_set_mmap_volume(stream, left, right);
5215 out->volume_l = left;
5216 out->volume_r = right;
5217 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305218 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305219 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5220 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305221 /* Volume control for pcm playback */
5222 if (!out->standby)
5223 ret = out_set_pcm_volume(stream, left, right);
5224 else
5225 out->apply_volume = true;
5226
5227 out->volume_l = left;
5228 out->volume_r = right;
5229 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005230 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5231 ALOGV("%s: bus device set volume called", __func__);
5232 if (!out->standby)
5233 ret = out_set_pcm_volume(stream, left, right);
5234 out->volume_l = left;
5235 out->volume_r = right;
5236 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005237 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005239 return -ENOSYS;
5240}
5241
Zhou Songc9672822017-08-16 16:01:39 +08005242static void update_frames_written(struct stream_out *out, size_t bytes)
5243{
5244 size_t bpf = 0;
5245
5246 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5247 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5248 bpf = 1;
5249 else if (!is_offload_usecase(out->usecase))
5250 bpf = audio_bytes_per_sample(out->format) *
5251 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005252
5253 pthread_mutex_lock(&out->position_query_lock);
5254 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005255 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005256 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5257 }
5258 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005259}
5260
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005261int split_and_write_audio_haptic_data(struct stream_out *out,
5262 const void *buffer, size_t bytes_to_write)
5263{
5264 struct audio_device *adev = out->dev;
5265
5266 int ret = 0;
5267 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5268 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5269 size_t frame_size = channel_count * bytes_per_sample;
5270 size_t frame_count = bytes_to_write / frame_size;
5271
5272 bool force_haptic_path =
5273 property_get_bool("vendor.audio.test_haptic", false);
5274
5275 // extract Haptics data from Audio buffer
5276 bool alloc_haptic_buffer = false;
5277 int haptic_channel_count = adev->haptics_config.channels;
5278 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5279 size_t audio_frame_size = frame_size - haptic_frame_size;
5280 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5281
5282 if (adev->haptic_buffer == NULL) {
5283 alloc_haptic_buffer = true;
5284 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5285 free(adev->haptic_buffer);
5286 adev->haptic_buffer_size = 0;
5287 alloc_haptic_buffer = true;
5288 }
5289
5290 if (alloc_haptic_buffer) {
5291 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005292 if(adev->haptic_buffer == NULL) {
5293 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5294 return -ENOMEM;
5295 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005296 adev->haptic_buffer_size = total_haptic_buffer_size;
5297 }
5298
5299 size_t src_index = 0, aud_index = 0, hap_index = 0;
5300 uint8_t *audio_buffer = (uint8_t *)buffer;
5301 uint8_t *haptic_buffer = adev->haptic_buffer;
5302
5303 // This is required for testing only. This works for stereo data only.
5304 // One channel is fed to audio stream and other to haptic stream for testing.
5305 if (force_haptic_path)
5306 audio_frame_size = haptic_frame_size = bytes_per_sample;
5307
5308 for (size_t i = 0; i < frame_count; i++) {
5309 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5310 audio_frame_size);
5311 aud_index += audio_frame_size;
5312 src_index += audio_frame_size;
5313
5314 if (adev->haptic_pcm)
5315 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5316 haptic_frame_size);
5317 hap_index += haptic_frame_size;
5318 src_index += haptic_frame_size;
5319
5320 // This is required for testing only.
5321 // Discard haptic channel data.
5322 if (force_haptic_path)
5323 src_index += haptic_frame_size;
5324 }
5325
5326 // write to audio pipeline
5327 ret = pcm_write(out->pcm, (void *)audio_buffer,
5328 frame_count * audio_frame_size);
5329
5330 // write to haptics pipeline
5331 if (adev->haptic_pcm)
5332 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5333 frame_count * haptic_frame_size);
5334
5335 return ret;
5336}
5337
Aalique Grahame22e49102018-12-18 14:23:57 -08005338#ifdef NO_AUDIO_OUT
5339static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5340 const void *buffer __unused, size_t bytes)
5341{
5342 struct stream_out *out = (struct stream_out *)stream;
5343
5344 /* No Output device supported other than BT for playback.
5345 * Sleep for the amount of buffer duration
5346 */
5347 lock_output_stream(out);
5348 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5349 (const struct audio_stream_out *)&out->stream) /
5350 out_get_sample_rate(&out->stream.common));
5351 pthread_mutex_unlock(&out->lock);
5352 return bytes;
5353}
5354#endif
5355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5357 size_t bytes)
5358{
5359 struct stream_out *out = (struct stream_out *)stream;
5360 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005361 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305362 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005363 const size_t frame_size = audio_stream_out_frame_size(stream);
5364 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305365 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005366
Haynes Mathew George380745d2017-10-04 15:27:45 -07005367 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005368 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305369
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305370 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005371
Dhananjay Kumarac341582017-02-23 23:42:25 +05305372 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305373 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305374 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5375 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005376 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305377 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305378 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305379 ALOGD(" %s: sound card is not active/SSR state", __func__);
5380 ret= -EIO;
5381 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305382 }
5383 }
5384
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305385 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305386 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305387 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305388 goto exit;
5389 }
5390
Haynes Mathew George16081042017-05-31 17:16:49 -07005391 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5392 ret = -EINVAL;
5393 goto exit;
5394 }
5395
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305396 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5397 !out->is_iec61937_info_available) {
5398
5399 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5400 out->is_iec61937_info_available = true;
5401 } else if (audio_extn_passthru_is_enabled()) {
5402 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305403 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305404
5405 if((out->format == AUDIO_FORMAT_DTS) ||
5406 (out->format == AUDIO_FORMAT_DTS_HD)) {
5407 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5408 buffer, bytes);
5409 if (ret) {
5410 if (ret != -ENOSYS) {
5411 out->is_iec61937_info_available = false;
5412 ALOGD("iec61937 transmission info not yet updated retry");
5413 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305414 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305415 /* if stream has started and after that there is
5416 * stream config change (iec transmission config)
5417 * then trigger select_device to update backend configuration.
5418 */
5419 out->stream_config_changed = true;
5420 pthread_mutex_lock(&adev->lock);
5421 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305422 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005423 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305424 ret = -EINVAL;
5425 goto exit;
5426 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305427 pthread_mutex_unlock(&adev->lock);
5428 out->stream_config_changed = false;
5429 out->is_iec61937_info_available = true;
5430 }
5431 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305432
Garmond Leung317cbf12017-09-13 16:20:50 -07005433 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305434 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5435 (out->is_iec61937_info_available == true)) {
5436 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5437 ret = -EINVAL;
5438 goto exit;
5439 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305440 }
5441 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305442
5443 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005444 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005445 if (!(out->devices &
5446 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305447 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305448 ret = -EIO;
5449 goto exit;
5450 }
5451 }
5452 }
5453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005455 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005456 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005457 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5458 ret = voice_extn_compress_voip_start_output_stream(out);
5459 else
5460 ret = start_output_stream(out);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05305461
5462 if (ret == 0)
5463 amplifier_output_stream_start(stream,
5464 is_offload_usecase(out->usecase));
5465
Eric Laurent150dbfe2013-02-27 14:31:02 -08005466 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005467 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005469 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005470 goto exit;
5471 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305472 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005473 if (last_known_cal_step != -1) {
5474 ALOGD("%s: retry previous failed cal level set", __func__);
5475 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305476 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005477 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305478
5479 if ((out->is_iec61937_info_available == true) &&
5480 (audio_extn_passthru_is_passthrough_stream(out))&&
5481 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5482 ret = -EINVAL;
5483 goto exit;
5484 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305485 if (out->set_dual_mono)
5486 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488
Ashish Jain81eb2a82015-05-13 10:52:34 +05305489 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005490 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305491 adev->is_channel_status_set = true;
5492 }
5493
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305494 if ((adev->use_old_pspd_mix_ctrl == true) &&
5495 (out->pspd_coeff_sent == false)) {
5496 /*
5497 * Need to resend pspd coefficients after stream started for
5498 * older kernel version as it does not save the coefficients
5499 * and also stream has to be started for coeff to apply.
5500 */
5501 usecase = get_usecase_from_list(adev, out->usecase);
5502 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305503 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305504 out->pspd_coeff_sent = true;
5505 }
5506 }
5507
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005508 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005509 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005510 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005511 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005512 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5513 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305514 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5515 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005516 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305517 out->send_next_track_params = false;
5518 out->is_compr_metadata_avail = false;
5519 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005520 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305521 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305522 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005523
Ashish Jain83a6cc22016-06-28 14:34:17 +05305524 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305525 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305526 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305527 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005528 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305529 return -EINVAL;
5530 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305531 audio_format_t dst_format = out->hal_op_format;
5532 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305533
Dieter Luecking5d57def2018-09-07 14:23:37 +02005534 /* prevent division-by-zero */
5535 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5536 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5537 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5538 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305539 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005540 ATRACE_END();
5541 return -EINVAL;
5542 }
5543
Ashish Jainf1eaa582016-05-23 20:54:24 +05305544 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5545 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5546
Ashish Jain83a6cc22016-06-28 14:34:17 +05305547 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305548 dst_format,
5549 buffer,
5550 src_format,
5551 frames);
5552
Ashish Jain83a6cc22016-06-28 14:34:17 +05305553 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305554 bytes_to_write);
5555
5556 /*Convert written bytes in audio flinger format*/
5557 if (ret > 0)
5558 ret = ((ret * format_to_bitwidth_table[out->format]) /
5559 format_to_bitwidth_table[dst_format]);
5560 }
5561 } else
5562 ret = compress_write(out->compr, buffer, bytes);
5563
Zhou Songc9672822017-08-16 16:01:39 +08005564 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5565 update_frames_written(out, bytes);
5566
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305567 if (ret < 0)
5568 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005569 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305570 /*msg to cb thread only if non blocking write is enabled*/
5571 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305572 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005573 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305574 } else if (-ENETRESET == ret) {
5575 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305576 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305577 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305578 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005579 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305580 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005581 }
Ashish Jain5106d362016-05-11 19:23:33 +05305582
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305583 /* Call compr start only when non-zero bytes of data is there to be rendered */
5584 if (!out->playback_started && ret > 0) {
5585 int status = compress_start(out->compr);
5586 if (status < 0) {
5587 ret = status;
5588 ALOGE("%s: compr start failed with err %d", __func__, errno);
5589 goto exit;
5590 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005591 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005592 out->playback_started = 1;
5593 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005594
5595 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5596 popcount(out->channel_mask),
5597 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005598 }
5599 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005600 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005601 return ret;
5602 } else {
5603 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005604 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005605 if (out->muted)
5606 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005607 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5608 __func__, frames, frame_size, bytes_to_write);
5609
Aalique Grahame22e49102018-12-18 14:23:57 -08005610 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005611 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5612 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5613 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005614 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5615 int16_t *src = (int16_t *)buffer;
5616 int16_t *dst = (int16_t *)buffer;
5617
5618 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5619 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005620 "out_write called for %s use case with wrong properties",
5621 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005622
5623 /*
5624 * FIXME: this can be removed once audio flinger mixer supports
5625 * mono output
5626 */
5627
5628 /*
5629 * Code below goes over each frame in the buffer and adds both
5630 * L and R samples and then divides by 2 to convert to mono
5631 */
5632 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5633 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5634 }
5635 bytes_to_write /= 2;
5636 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005637
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305638 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005639
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005640 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005641
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005642 if (out->config.rate)
5643 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5644 out->config.rate;
5645
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005646 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005647 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5648
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005649 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005650 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005651 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305652 out->convert_buffer != NULL) {
5653
5654 memcpy_by_audio_format(out->convert_buffer,
5655 out->hal_op_format,
5656 buffer,
5657 out->hal_ip_format,
5658 out->config.period_size * out->config.channels);
5659
5660 ret = pcm_write(out->pcm, out->convert_buffer,
5661 (out->config.period_size *
5662 out->config.channels *
5663 format_to_bitwidth_table[out->hal_op_format]));
5664 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305665 /*
5666 * To avoid underrun in DSP when the application is not pumping
5667 * data at required rate, check for the no. of bytes and ignore
5668 * pcm_write if it is less than actual buffer size.
5669 * It is a work around to a change in compress VOIP driver.
5670 */
5671 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5672 bytes < (out->config.period_size * out->config.channels *
5673 audio_bytes_per_sample(out->format))) {
5674 size_t voip_buf_size =
5675 out->config.period_size * out->config.channels *
5676 audio_bytes_per_sample(out->format);
5677 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5678 __func__, bytes, voip_buf_size);
5679 usleep(((uint64_t)voip_buf_size - bytes) *
5680 1000000 / audio_stream_out_frame_size(stream) /
5681 out_get_sample_rate(&out->stream.common));
5682 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005683 } else {
5684 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5685 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5686 else
5687 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5688 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305689 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005690
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005691 release_out_focus(out);
5692
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305693 if (ret < 0)
5694 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005695 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305696 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005698 }
5699
5700exit:
Zhou Songc9672822017-08-16 16:01:39 +08005701 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305702 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305703 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705 pthread_mutex_unlock(&out->lock);
5706
5707 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005708 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005709 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305710 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305711 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305712 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305713 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305714 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305715 out->standby = true;
5716 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305717 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005718 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5719 /* prevent division-by-zero */
5720 uint32_t stream_size = audio_stream_out_frame_size(stream);
5721 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005722
Dieter Luecking5d57def2018-09-07 14:23:37 +02005723 if ((stream_size == 0) || (srate == 0)) {
5724 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5725 ATRACE_END();
5726 return -EINVAL;
5727 }
5728 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5729 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005730 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305731 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005732 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005733 return ret;
5734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005735 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005736 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005737 return bytes;
5738}
5739
5740static int out_get_render_position(const struct audio_stream_out *stream,
5741 uint32_t *dsp_frames)
5742{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005743 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005744
5745 if (dsp_frames == NULL)
5746 return -EINVAL;
5747
5748 *dsp_frames = 0;
5749 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005750 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305751
5752 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5753 * this operation and adev_close_output_stream(where out gets reset).
5754 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305755 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005756 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305757 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005758 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305759 return 0;
5760 }
5761
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005762 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305763 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305764 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005765 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305766 if (ret < 0)
5767 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005768 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305769 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005770 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305771 if (-ENETRESET == ret) {
5772 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305773 out->card_status = CARD_STATUS_OFFLINE;
5774 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305775 } else if(ret < 0) {
5776 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305777 ret = -EINVAL;
5778 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305779 /*
5780 * Handle corner case where compress session is closed during SSR
5781 * and timestamp is queried
5782 */
5783 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305784 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305785 } else if (out->prev_card_status_offline) {
5786 ALOGE("ERROR: previously sound card was offline,return error");
5787 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305788 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305789 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005790 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305791 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305792 pthread_mutex_unlock(&out->lock);
5793 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005794 } else if (audio_is_linear_pcm(out->format)) {
5795 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005796 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005797 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005798 } else
5799 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005800}
5801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005802static int out_add_audio_effect(const struct audio_stream *stream __unused,
5803 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804{
5805 return 0;
5806}
5807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005808static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5809 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005810{
5811 return 0;
5812}
5813
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005814static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5815 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005816{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305817 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005818}
5819
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005820static int out_get_presentation_position(const struct audio_stream_out *stream,
5821 uint64_t *frames, struct timespec *timestamp)
5822{
5823 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305824 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005825 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005826
Ashish Jain5106d362016-05-11 19:23:33 +05305827 /* below piece of code is not guarded against any lock because audioFliner serializes
5828 * this operation and adev_close_output_stream( where out gets reset).
5829 */
5830 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305831 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005832 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305833 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5834 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5835 return 0;
5836 }
5837
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005838 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005839
Ashish Jain5106d362016-05-11 19:23:33 +05305840 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5841 ret = compress_get_tstamp(out->compr, &dsp_frames,
5842 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005843 // Adjustment accounts for A2dp encoder latency with offload usecases
5844 // Note: Encoder latency is returned in ms.
5845 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5846 unsigned long offset =
5847 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5848 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5849 }
Ashish Jain5106d362016-05-11 19:23:33 +05305850 ALOGVV("%s rendered frames %ld sample_rate %d",
5851 __func__, dsp_frames, out->sample_rate);
5852 *frames = dsp_frames;
5853 if (ret < 0)
5854 ret = -errno;
5855 if (-ENETRESET == ret) {
5856 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305857 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305858 ret = -EINVAL;
5859 } else
5860 ret = 0;
5861 /* this is the best we can do */
5862 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005863 } else {
5864 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005865 unsigned int avail;
5866 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5867 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5868 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5869 // This adjustment accounts for buffering after app processor.
5870 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005871 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005872 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005873
Weiyin Jiangd4633762018-03-16 12:05:03 +08005874 // Adjustment accounts for A2dp encoder latency with non offload usecases
5875 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5876 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5877 signed_frames -=
5878 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5879 }
5880
5881 // It would be unusual for this value to be negative, but check just in case ...
5882 if (signed_frames >= 0) {
5883 *frames = signed_frames;
5884 ret = 0;
5885 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005886 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305887 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305888 *frames = out->written;
5889 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305890 if (is_offload_usecase(out->usecase))
5891 ret = -EINVAL;
5892 else
5893 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005894 }
5895 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005896 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005897 return ret;
5898}
5899
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005900static int out_set_callback(struct audio_stream_out *stream,
5901 stream_callback_t callback, void *cookie)
5902{
5903 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005904 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005905
5906 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005907 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005908 out->client_callback = callback;
5909 out->client_cookie = cookie;
5910 if (out->adsp_hdlr_stream_handle) {
5911 ret = audio_extn_adsp_hdlr_stream_set_callback(
5912 out->adsp_hdlr_stream_handle,
5913 callback,
5914 cookie);
5915 if (ret)
5916 ALOGW("%s:adsp hdlr callback registration failed %d",
5917 __func__, ret);
5918 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005919 pthread_mutex_unlock(&out->lock);
5920 return 0;
5921}
5922
5923static int out_pause(struct audio_stream_out* stream)
5924{
5925 struct stream_out *out = (struct stream_out *)stream;
5926 int status = -ENOSYS;
5927 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005928 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005929 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005930 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005931 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305932 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305933 status = compress_pause(out->compr);
5934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005935 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005936
Mingming Yin21854652016-04-13 11:54:02 -07005937 if (audio_extn_passthru_is_active()) {
5938 ALOGV("offload use case, pause passthru");
5939 audio_extn_passthru_on_pause(out);
5940 }
5941
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305942 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005943 audio_extn_dts_notify_playback_state(out->usecase, 0,
5944 out->sample_rate, popcount(out->channel_mask),
5945 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005946 }
5947 pthread_mutex_unlock(&out->lock);
5948 }
5949 return status;
5950}
5951
5952static int out_resume(struct audio_stream_out* stream)
5953{
5954 struct stream_out *out = (struct stream_out *)stream;
5955 int status = -ENOSYS;
5956 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005957 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005958 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005959 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005960 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005961 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305962 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305963 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005964 }
5965 if (!status) {
5966 out->offload_state = OFFLOAD_STATE_PLAYING;
5967 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305968 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005969 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5970 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005971 }
5972 pthread_mutex_unlock(&out->lock);
5973 }
5974 return status;
5975}
5976
5977static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5978{
5979 struct stream_out *out = (struct stream_out *)stream;
5980 int status = -ENOSYS;
5981 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005982 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005983 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005984 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5985 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5986 else
5987 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5988 pthread_mutex_unlock(&out->lock);
5989 }
5990 return status;
5991}
5992
5993static int out_flush(struct audio_stream_out* stream)
5994{
5995 struct stream_out *out = (struct stream_out *)stream;
5996 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005997 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005998 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005999 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006000 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6001 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006002 } else {
6003 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6004 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006005 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006006 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006007 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 return 0;
6009 }
6010 return -ENOSYS;
6011}
6012
Haynes Mathew George16081042017-05-31 17:16:49 -07006013static int out_stop(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 pcm_stop(out->pcm);
6024 ret = stop_output_stream(out);
6025 out->playback_started = false;
6026 }
6027 pthread_mutex_unlock(&adev->lock);
6028 return ret;
6029}
6030
6031static int out_start(const struct audio_stream_out* stream)
6032{
6033 struct stream_out *out = (struct stream_out *)stream;
6034 struct audio_device *adev = out->dev;
6035 int ret = -ENOSYS;
6036
6037 ALOGV("%s", __func__);
6038 pthread_mutex_lock(&adev->lock);
6039 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6040 !out->playback_started && out->pcm != NULL) {
6041 ret = start_output_stream(out);
6042 if (ret == 0) {
6043 out->playback_started = true;
6044 }
6045 }
6046 pthread_mutex_unlock(&adev->lock);
6047 return ret;
6048}
6049
6050/*
6051 * Modify config->period_count based on min_size_frames
6052 */
6053static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6054{
6055 int periodCountRequested = (min_size_frames + config->period_size - 1)
6056 / config->period_size;
6057 int periodCount = MMAP_PERIOD_COUNT_MIN;
6058
6059 ALOGV("%s original config.period_size = %d config.period_count = %d",
6060 __func__, config->period_size, config->period_count);
6061
6062 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6063 periodCount *= 2;
6064 }
6065 config->period_count = periodCount;
6066
6067 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6068}
6069
Phil Burkfe17efd2019-03-25 10:23:35 -07006070// Read offset for the positional timestamp from a persistent vendor property.
6071// This is to workaround apparent inaccuracies in the timing information that
6072// is used by the AAudio timing model. The inaccuracies can cause glitches.
6073static int64_t get_mmap_out_time_offset() {
6074 const int32_t kDefaultOffsetMicros = 0;
6075 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006076 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006077 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6078 return mmap_time_offset_micros * (int64_t)1000;
6079}
6080
Haynes Mathew George16081042017-05-31 17:16:49 -07006081static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6082 int32_t min_size_frames,
6083 struct audio_mmap_buffer_info *info)
6084{
6085 struct stream_out *out = (struct stream_out *)stream;
6086 struct audio_device *adev = out->dev;
6087 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006088 unsigned int offset1 = 0;
6089 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006090 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006091 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006092 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006093
Arun Mirpuri5d170872019-03-26 13:21:31 -07006094 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306095 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006096 pthread_mutex_lock(&adev->lock);
6097
Sharad Sanglec6f32552018-05-04 16:15:38 +05306098 if (CARD_STATUS_OFFLINE == out->card_status ||
6099 CARD_STATUS_OFFLINE == adev->card_status) {
6100 ALOGW("out->card_status or adev->card_status offline, try again");
6101 ret = -EIO;
6102 goto exit;
6103 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006104 if (info == NULL || min_size_frames == 0) {
6105 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6106 ret = -EINVAL;
6107 goto exit;
6108 }
6109 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6110 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6111 ret = -ENOSYS;
6112 goto exit;
6113 }
6114 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6115 if (out->pcm_device_id < 0) {
6116 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6117 __func__, out->pcm_device_id, out->usecase);
6118 ret = -EINVAL;
6119 goto exit;
6120 }
6121
6122 adjust_mmap_period_count(&out->config, min_size_frames);
6123
Arun Mirpuri5d170872019-03-26 13:21:31 -07006124 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006125 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6126 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6127 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306128 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306129 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6130 out->card_status = CARD_STATUS_OFFLINE;
6131 adev->card_status = CARD_STATUS_OFFLINE;
6132 ret = -EIO;
6133 goto exit;
6134 }
6135
Haynes Mathew George16081042017-05-31 17:16:49 -07006136 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6137 step = "open";
6138 ret = -ENODEV;
6139 goto exit;
6140 }
6141 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6142 if (ret < 0) {
6143 step = "begin";
6144 goto exit;
6145 }
6146 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006147 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006148 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006149 ret = platform_get_mmap_data_fd(adev->platform,
6150 out->pcm_device_id, 0 /*playback*/,
6151 &info->shared_memory_fd,
6152 &mmap_size);
6153 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006154 // Fall back to non exclusive mode
6155 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6156 } else {
6157 if (mmap_size < buffer_size) {
6158 step = "mmap";
6159 goto exit;
6160 }
6161 // FIXME: indicate exclusive mode support by returning a negative buffer size
6162 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006163 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006164 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006165 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006166
6167 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6168 if (ret < 0) {
6169 step = "commit";
6170 goto exit;
6171 }
6172
Phil Burkfe17efd2019-03-25 10:23:35 -07006173 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6174
Haynes Mathew George16081042017-05-31 17:16:49 -07006175 out->standby = false;
6176 ret = 0;
6177
Arun Mirpuri5d170872019-03-26 13:21:31 -07006178 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006179 __func__, info->shared_memory_address, info->buffer_size_frames);
6180
6181exit:
6182 if (ret != 0) {
6183 if (out->pcm == NULL) {
6184 ALOGE("%s: %s - %d", __func__, step, ret);
6185 } else {
6186 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6187 pcm_close(out->pcm);
6188 out->pcm = NULL;
6189 }
6190 }
6191 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306192 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006193 return ret;
6194}
6195
6196static int out_get_mmap_position(const struct audio_stream_out *stream,
6197 struct audio_mmap_position *position)
6198{
6199 struct stream_out *out = (struct stream_out *)stream;
6200 ALOGVV("%s", __func__);
6201 if (position == NULL) {
6202 return -EINVAL;
6203 }
6204 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006205 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006206 return -ENOSYS;
6207 }
6208 if (out->pcm == NULL) {
6209 return -ENOSYS;
6210 }
6211
6212 struct timespec ts = { 0, 0 };
6213 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6214 if (ret < 0) {
6215 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6216 return ret;
6217 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006218 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6219 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006220 return 0;
6221}
6222
6223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006224/** audio_stream_in implementation **/
6225static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6226{
6227 struct stream_in *in = (struct stream_in *)stream;
6228
6229 return in->config.rate;
6230}
6231
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006232static int in_set_sample_rate(struct audio_stream *stream __unused,
6233 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006234{
6235 return -ENOSYS;
6236}
6237
6238static size_t in_get_buffer_size(const struct audio_stream *stream)
6239{
6240 struct stream_in *in = (struct stream_in *)stream;
6241
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006242 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6243 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006244 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6245 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306246 else if(audio_extn_cin_attached_usecase(in->usecase))
6247 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006248
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006249 return in->config.period_size * in->af_period_multiplier *
6250 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251}
6252
6253static uint32_t in_get_channels(const struct audio_stream *stream)
6254{
6255 struct stream_in *in = (struct stream_in *)stream;
6256
6257 return in->channel_mask;
6258}
6259
6260static audio_format_t in_get_format(const struct audio_stream *stream)
6261{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006262 struct stream_in *in = (struct stream_in *)stream;
6263
6264 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006265}
6266
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006267static int in_set_format(struct audio_stream *stream __unused,
6268 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006269{
6270 return -ENOSYS;
6271}
6272
6273static int in_standby(struct audio_stream *stream)
6274{
6275 struct stream_in *in = (struct stream_in *)stream;
6276 struct audio_device *adev = in->dev;
6277 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306278 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6279 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006280 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306281
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006282 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006283 if (!in->standby && in->is_st_session) {
6284 ALOGD("%s: sound trigger pcm stop lab", __func__);
6285 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006286 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006287 in->standby = 1;
6288 }
6289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006291 if (adev->adm_deregister_stream)
6292 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6293
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006294 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05306295
6296 amplifier_input_stream_standby((struct audio_stream_in *) stream);
6297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006299 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006300 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006301 voice_extn_compress_voip_close_input_stream(stream);
6302 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006303 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6304 do_stop = in->capture_started;
6305 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006306 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306307 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306308 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006309 }
6310
Arun Mirpuri5d170872019-03-26 13:21:31 -07006311 if (in->pcm) {
6312 ATRACE_BEGIN("pcm_in_close");
6313 pcm_close(in->pcm);
6314 ATRACE_END();
6315 in->pcm = NULL;
6316 }
6317
Carter Hsu2e429db2019-05-14 18:50:52 +08006318 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006319 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006320
6321 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006322 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006323
6324 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6325 adev->num_va_sessions--;
6326
Eric Laurent150dbfe2013-02-27 14:31:02 -08006327 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006328 }
6329 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006330 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006331 return status;
6332}
6333
Aalique Grahame22e49102018-12-18 14:23:57 -08006334static int in_dump(const struct audio_stream *stream,
6335 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006336{
Aalique Grahame22e49102018-12-18 14:23:57 -08006337 struct stream_in *in = (struct stream_in *)stream;
6338
6339 // We try to get the lock for consistency,
6340 // but it isn't necessary for these variables.
6341 // If we're not in standby, we may be blocked on a read.
6342 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6343 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6344 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6345 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6346
6347 if (locked) {
6348 pthread_mutex_unlock(&in->lock);
6349 }
6350
6351 // dump error info
6352 (void)error_log_dump(
6353 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006355 return 0;
6356}
6357
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306358static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6359{
6360 if (!stream || !parms)
6361 return;
6362
6363 struct stream_in *in = (struct stream_in *)stream;
6364 struct audio_device *adev = in->dev;
6365
6366 card_status_t status;
6367 int card;
6368 if (parse_snd_card_status(parms, &card, &status) < 0)
6369 return;
6370
6371 pthread_mutex_lock(&adev->lock);
6372 bool valid_cb = (card == adev->snd_card);
6373 pthread_mutex_unlock(&adev->lock);
6374
6375 if (!valid_cb)
6376 return;
6377
6378 lock_input_stream(in);
6379 if (in->card_status != status)
6380 in->card_status = status;
6381 pthread_mutex_unlock(&in->lock);
6382
6383 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6384 use_case_table[in->usecase],
6385 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6386
6387 // a better solution would be to report error back to AF and let
6388 // it put the stream to standby
6389 if (status == CARD_STATUS_OFFLINE)
6390 in_standby(&in->stream.common);
6391
6392 return;
6393}
6394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006395static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6396{
6397 struct stream_in *in = (struct stream_in *)stream;
6398 struct audio_device *adev = in->dev;
6399 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006400 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006401 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306403 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006404 parms = str_parms_create_str(kvpairs);
6405
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306406 if (!parms)
6407 goto error;
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05306408
6409 amplifier_in_set_parameters(parms);
6410
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006411 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006412 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006413
6414 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6415 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006416 val = atoi(value);
6417 /* no audio source uses val == 0 */
6418 if ((in->source != val) && (val != 0)) {
6419 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006420 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6421 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6422 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006423 (in->config.rate == 8000 || in->config.rate == 16000 ||
6424 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006425 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006426 err = voice_extn_compress_voip_open_input_stream(in);
6427 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006428 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006429 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006430 }
6431 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006432 }
6433 }
6434
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006435 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6436 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006437 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006438 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6439
6440 // Workaround: If routing to an non existing usb device, fail gracefully
6441 // The routing request will otherwise block during 10 second
6442 int card;
6443 if (audio_is_usb_in_device(val) &&
6444 (card = get_alive_usb_card(parms)) >= 0) {
6445
6446 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6447 ret = -ENOSYS;
6448 } else {
6449
6450 in->device = val;
6451 /* If recording is in progress, change the tx device to new device */
6452 if (!in->standby && !in->is_st_session) {
6453 ALOGV("update input routing change");
6454 // inform adm before actual routing to prevent glitches.
6455 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006456 adev->adm_on_routing_change(adev->adm_data,
6457 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006458 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006459 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6460 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006461 }
6462 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006464 }
6465 }
6466
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306467 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6468 if (err >= 0) {
6469 strlcpy(in->profile, value, sizeof(in->profile));
6470 ALOGV("updating stream profile with value '%s'", in->profile);
6471 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6472 &adev->streams_input_cfg_list,
6473 in->device, in->flags, in->format,
6474 in->sample_rate, in->bit_width,
6475 in->profile, &in->app_type_cfg);
6476 }
6477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006478 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006479 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006480
6481 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306482error:
Eric Laurent994a6932013-07-17 11:51:42 -07006483 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006484 return ret;
6485}
6486
6487static char* in_get_parameters(const struct audio_stream *stream,
6488 const char *keys)
6489{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006490 struct stream_in *in = (struct stream_in *)stream;
6491 struct str_parms *query = str_parms_create_str(keys);
6492 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006493 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006494
6495 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006496 if (reply) {
6497 str_parms_destroy(reply);
6498 }
6499 if (query) {
6500 str_parms_destroy(query);
6501 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006502 ALOGE("in_get_parameters: failed to create query or reply");
6503 return NULL;
6504 }
6505
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006506 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006507
6508 voice_extn_in_get_parameters(in, query, reply);
6509
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006510 stream_get_parameter_channels(query, reply,
6511 &in->supported_channel_masks[0]);
6512 stream_get_parameter_formats(query, reply,
6513 &in->supported_formats[0]);
6514 stream_get_parameter_rates(query, reply,
6515 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006516 str = str_parms_to_str(reply);
6517 str_parms_destroy(query);
6518 str_parms_destroy(reply);
6519
6520 ALOGV("%s: exit: returns - %s", __func__, str);
6521 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006522}
6523
Aalique Grahame22e49102018-12-18 14:23:57 -08006524static int in_set_gain(struct audio_stream_in *stream,
6525 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006526{
Aalique Grahame22e49102018-12-18 14:23:57 -08006527 struct stream_in *in = (struct stream_in *)stream;
6528 char mixer_ctl_name[128];
6529 struct mixer_ctl *ctl;
6530 int ctl_value;
6531
6532 ALOGV("%s: gain %f", __func__, gain);
6533
6534 if (stream == NULL)
6535 return -EINVAL;
6536
6537 /* in_set_gain() only used to silence MMAP capture for now */
6538 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6539 return -ENOSYS;
6540
6541 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6542
6543 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6544 if (!ctl) {
6545 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6546 __func__, mixer_ctl_name);
6547 return -ENOSYS;
6548 }
6549
6550 if (gain < RECORD_GAIN_MIN)
6551 gain = RECORD_GAIN_MIN;
6552 else if (gain > RECORD_GAIN_MAX)
6553 gain = RECORD_GAIN_MAX;
6554 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6555
6556 mixer_ctl_set_value(ctl, 0, ctl_value);
6557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006558 return 0;
6559}
6560
6561static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6562 size_t bytes)
6563{
6564 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306565
6566 if (in == NULL) {
6567 ALOGE("%s: stream_in ptr is NULL", __func__);
6568 return -EINVAL;
6569 }
6570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006571 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306572 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306573 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006574
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006575 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306576
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006577 if (in->is_st_session) {
6578 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6579 /* Read from sound trigger HAL */
6580 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006581 if (in->standby) {
6582 adev->num_va_sessions++;
6583 in->standby = 0;
6584 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006585 pthread_mutex_unlock(&in->lock);
6586 return bytes;
6587 }
6588
Haynes Mathew George16081042017-05-31 17:16:49 -07006589 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6590 ret = -ENOSYS;
6591 goto exit;
6592 }
6593
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006594 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6595 !in->standby && adev->adm_routing_changed) {
6596 ret = -ENOSYS;
6597 goto exit;
6598 }
6599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006600 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006601 pthread_mutex_lock(&adev->lock);
6602 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6603 ret = voice_extn_compress_voip_start_input_stream(in);
6604 else
6605 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006606 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6607 adev->num_va_sessions++;
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05306608
6609 if (ret == 0)
6610 amplifier_input_stream_start(stream);
6611
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006612 pthread_mutex_unlock(&adev->lock);
6613 if (ret != 0) {
6614 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006615 }
6616 in->standby = 0;
6617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306619 /* Avoid read if capture_stopped is set */
6620 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6621 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6622 ret = -EINVAL;
6623 goto exit;
6624 }
6625
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006626 // what's the duration requested by the client?
6627 long ns = 0;
6628
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306629 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006630 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6631 in->config.rate;
6632
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006633 ret = request_in_focus(in, ns);
6634 if (ret != 0)
6635 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006636 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006637
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306638 if (audio_extn_cin_attached_usecase(in->usecase)) {
6639 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6640 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306641 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006642 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306643 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006644 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006645 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006646 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006647 } else if (audio_extn_ffv_get_stream() == in) {
6648 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306649 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006650 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306651 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6652 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6653 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6654 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306655 ret = -EINVAL;
6656 goto exit;
6657 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306658 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306659 ret = -errno;
6660 }
6661 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306662 /* bytes read is always set to bytes for non compress usecases */
6663 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006664 }
6665
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006666 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006668 /*
Quinn Malef6050362019-01-30 15:55:40 -08006669 * Instead of writing zeroes here, we could trust the hardware to always
6670 * provide zeroes when muted. This is also muted with voice recognition
6671 * usecases so that other clients do not have access to voice recognition
6672 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006673 */
Quinn Malef6050362019-01-30 15:55:40 -08006674 if ((ret == 0 && voice_get_mic_mute(adev) &&
6675 !voice_is_in_call_rec_stream(in) &&
6676 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6677 (adev->num_va_sessions &&
6678 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6679 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6680 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006681 memset(buffer, 0, bytes);
6682
6683exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306684 frame_size = audio_stream_in_frame_size(stream);
6685 if (frame_size > 0)
6686 in->frames_read += bytes_read/frame_size;
6687
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006688 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306689 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006690 pthread_mutex_unlock(&in->lock);
6691
6692 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306693 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306694 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306695 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306696 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306697 in->standby = true;
6698 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306699 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6700 bytes_read = bytes;
6701 memset(buffer, 0, bytes);
6702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006704 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6705 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006706 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306707 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306708 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306710 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711}
6712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006713static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714{
6715 return 0;
6716}
6717
Aalique Grahame22e49102018-12-18 14:23:57 -08006718static int in_get_capture_position(const struct audio_stream_in *stream,
6719 int64_t *frames, int64_t *time)
6720{
6721 if (stream == NULL || frames == NULL || time == NULL) {
6722 return -EINVAL;
6723 }
6724 struct stream_in *in = (struct stream_in *)stream;
6725 int ret = -ENOSYS;
6726
6727 lock_input_stream(in);
6728 // note: ST sessions do not close the alsa pcm driver synchronously
6729 // on standby. Therefore, we may return an error even though the
6730 // pcm stream is still opened.
6731 if (in->standby) {
6732 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6733 "%s stream in standby but pcm not NULL for non ST session", __func__);
6734 goto exit;
6735 }
6736 if (in->pcm) {
6737 struct timespec timestamp;
6738 unsigned int avail;
6739 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6740 *frames = in->frames_read + avail;
6741 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6742 ret = 0;
6743 }
6744 }
6745exit:
6746 pthread_mutex_unlock(&in->lock);
6747 return ret;
6748}
6749
Carter Hsu2e429db2019-05-14 18:50:52 +08006750static int in_update_effect_list(bool add, effect_handle_t effect,
6751 struct listnode *head)
6752{
6753 struct listnode *node;
6754 struct in_effect_list *elist = NULL;
6755 struct in_effect_list *target = NULL;
6756 int ret = 0;
6757
6758 if (!head)
6759 return ret;
6760
6761 list_for_each(node, head) {
6762 elist = node_to_item(node, struct in_effect_list, list);
6763 if (elist->handle == effect) {
6764 target = elist;
6765 break;
6766 }
6767 }
6768
6769 if (add) {
6770 if (target) {
6771 ALOGD("effect %p already exist", effect);
6772 return ret;
6773 }
6774
6775 target = (struct in_effect_list *)
6776 calloc(1, sizeof(struct in_effect_list));
6777
6778 if (!target) {
6779 ALOGE("%s:fail to allocate memory", __func__);
6780 return -ENOMEM;
6781 }
6782
6783 target->handle = effect;
6784 list_add_tail(head, &target->list);
6785 } else {
6786 if (target) {
6787 list_remove(&target->list);
6788 free(target);
6789 }
6790 }
6791
6792 return ret;
6793}
6794
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006795static int add_remove_audio_effect(const struct audio_stream *stream,
6796 effect_handle_t effect,
6797 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006799 struct stream_in *in = (struct stream_in *)stream;
6800 int status = 0;
6801 effect_descriptor_t desc;
6802
6803 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006804 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6805
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006806 if (status != 0)
6807 return status;
6808
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006809 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006810 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006811 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006812 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6813 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006814 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006815
6816 in_update_effect_list(enable, effect, &in->aec_list);
6817 enable = !list_empty(&in->aec_list);
6818 if (enable == in->enable_aec)
6819 goto exit;
6820
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006821 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006822 ALOGD("AEC enable %d", enable);
6823
Aalique Grahame22e49102018-12-18 14:23:57 -08006824 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6825 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6826 in->dev->enable_voicerx = enable;
6827 struct audio_usecase *usecase;
6828 struct listnode *node;
6829 list_for_each(node, &in->dev->usecase_list) {
6830 usecase = node_to_item(node, struct audio_usecase, list);
6831 if (usecase->type == PCM_PLAYBACK)
6832 select_devices(in->dev, usecase->id);
6833 }
6834 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006835 if (!in->standby) {
6836 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6837 select_devices(in->dev, in->usecase);
6838 }
6839
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006840 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006841 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6842
6843 in_update_effect_list(enable, effect, &in->ns_list);
6844 enable = !list_empty(&in->ns_list);
6845 if (enable == in->enable_ns)
6846 goto exit;
6847
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006848 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006849 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006850 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006851 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6852 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006853 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6854 select_devices(in->dev, in->usecase);
6855 } else
6856 select_devices(in->dev, in->usecase);
6857 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006858 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006859exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006860 pthread_mutex_unlock(&in->dev->lock);
6861 pthread_mutex_unlock(&in->lock);
6862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006863 return 0;
6864}
6865
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006866static int in_add_audio_effect(const struct audio_stream *stream,
6867 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868{
Eric Laurent994a6932013-07-17 11:51:42 -07006869 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006870 return add_remove_audio_effect(stream, effect, true);
6871}
6872
6873static int in_remove_audio_effect(const struct audio_stream *stream,
6874 effect_handle_t effect)
6875{
Eric Laurent994a6932013-07-17 11:51:42 -07006876 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006877 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878}
6879
Derek Chenf939fb72018-11-13 13:34:41 -08006880streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6881 audio_io_handle_t input)
6882{
6883 struct listnode *node;
6884
6885 list_for_each(node, &dev->active_inputs_list) {
6886 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6887 streams_input_ctxt_t,
6888 list);
6889 if (in_ctxt->input->capture_handle == input) {
6890 return in_ctxt;
6891 }
6892 }
6893 return NULL;
6894}
6895
6896streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6897 audio_io_handle_t output)
6898{
6899 struct listnode *node;
6900
6901 list_for_each(node, &dev->active_outputs_list) {
6902 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6903 streams_output_ctxt_t,
6904 list);
6905 if (out_ctxt->output->handle == output) {
6906 return out_ctxt;
6907 }
6908 }
6909 return NULL;
6910}
6911
Haynes Mathew George16081042017-05-31 17:16:49 -07006912static int in_stop(const struct audio_stream_in* stream)
6913{
6914 struct stream_in *in = (struct stream_in *)stream;
6915 struct audio_device *adev = in->dev;
6916
6917 int ret = -ENOSYS;
6918 ALOGV("%s", __func__);
6919 pthread_mutex_lock(&adev->lock);
6920 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6921 in->capture_started && in->pcm != NULL) {
6922 pcm_stop(in->pcm);
6923 ret = stop_input_stream(in);
6924 in->capture_started = false;
6925 }
6926 pthread_mutex_unlock(&adev->lock);
6927 return ret;
6928}
6929
6930static int in_start(const struct audio_stream_in* stream)
6931{
6932 struct stream_in *in = (struct stream_in *)stream;
6933 struct audio_device *adev = in->dev;
6934 int ret = -ENOSYS;
6935
6936 ALOGV("%s in %p", __func__, in);
6937 pthread_mutex_lock(&adev->lock);
6938 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6939 !in->capture_started && in->pcm != NULL) {
6940 if (!in->capture_started) {
6941 ret = start_input_stream(in);
6942 if (ret == 0) {
6943 in->capture_started = true;
6944 }
6945 }
6946 }
6947 pthread_mutex_unlock(&adev->lock);
6948 return ret;
6949}
6950
Phil Burke0a86d12019-02-16 22:28:11 -08006951// Read offset for the positional timestamp from a persistent vendor property.
6952// This is to workaround apparent inaccuracies in the timing information that
6953// is used by the AAudio timing model. The inaccuracies can cause glitches.
6954static int64_t in_get_mmap_time_offset() {
6955 const int32_t kDefaultOffsetMicros = 0;
6956 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006957 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006958 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6959 return mmap_time_offset_micros * (int64_t)1000;
6960}
6961
Haynes Mathew George16081042017-05-31 17:16:49 -07006962static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6963 int32_t min_size_frames,
6964 struct audio_mmap_buffer_info *info)
6965{
6966 struct stream_in *in = (struct stream_in *)stream;
6967 struct audio_device *adev = in->dev;
6968 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006969 unsigned int offset1 = 0;
6970 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006971 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006972 uint32_t mmap_size = 0;
6973 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006974
6975 pthread_mutex_lock(&adev->lock);
6976 ALOGV("%s in %p", __func__, in);
6977
Sharad Sanglec6f32552018-05-04 16:15:38 +05306978 if (CARD_STATUS_OFFLINE == in->card_status||
6979 CARD_STATUS_OFFLINE == adev->card_status) {
6980 ALOGW("in->card_status or adev->card_status offline, try again");
6981 ret = -EIO;
6982 goto exit;
6983 }
6984
Haynes Mathew George16081042017-05-31 17:16:49 -07006985 if (info == NULL || min_size_frames == 0) {
6986 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6987 ret = -EINVAL;
6988 goto exit;
6989 }
6990 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6991 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6992 ALOGV("%s in %p", __func__, in);
6993 ret = -ENOSYS;
6994 goto exit;
6995 }
6996 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6997 if (in->pcm_device_id < 0) {
6998 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6999 __func__, in->pcm_device_id, in->usecase);
7000 ret = -EINVAL;
7001 goto exit;
7002 }
7003
7004 adjust_mmap_period_count(&in->config, min_size_frames);
7005
7006 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7007 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7008 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7009 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307010 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307011 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7012 in->card_status = CARD_STATUS_OFFLINE;
7013 adev->card_status = CARD_STATUS_OFFLINE;
7014 ret = -EIO;
7015 goto exit;
7016 }
7017
Haynes Mathew George16081042017-05-31 17:16:49 -07007018 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7019 step = "open";
7020 ret = -ENODEV;
7021 goto exit;
7022 }
7023
7024 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7025 if (ret < 0) {
7026 step = "begin";
7027 goto exit;
7028 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007029
Arun Mirpuri5d170872019-03-26 13:21:31 -07007030 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7031 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7032 info->burst_size_frames = in->config.period_size;
7033 ret = platform_get_mmap_data_fd(adev->platform,
7034 in->pcm_device_id, 1 /*capture*/,
7035 &info->shared_memory_fd,
7036 &mmap_size);
7037 if (ret < 0) {
7038 // Fall back to non exclusive mode
7039 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7040 } else {
7041 if (mmap_size < buffer_size) {
7042 step = "mmap";
7043 goto exit;
7044 }
7045 // FIXME: indicate exclusive mode support by returning a negative buffer size
7046 info->buffer_size_frames *= -1;
7047 }
7048
7049 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007050
7051 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7052 if (ret < 0) {
7053 step = "commit";
7054 goto exit;
7055 }
7056
Phil Burke0a86d12019-02-16 22:28:11 -08007057 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7058
Haynes Mathew George16081042017-05-31 17:16:49 -07007059 in->standby = false;
7060 ret = 0;
7061
7062 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7063 __func__, info->shared_memory_address, info->buffer_size_frames);
7064
7065exit:
7066 if (ret != 0) {
7067 if (in->pcm == NULL) {
7068 ALOGE("%s: %s - %d", __func__, step, ret);
7069 } else {
7070 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7071 pcm_close(in->pcm);
7072 in->pcm = NULL;
7073 }
7074 }
7075 pthread_mutex_unlock(&adev->lock);
7076 return ret;
7077}
7078
7079static int in_get_mmap_position(const struct audio_stream_in *stream,
7080 struct audio_mmap_position *position)
7081{
7082 struct stream_in *in = (struct stream_in *)stream;
7083 ALOGVV("%s", __func__);
7084 if (position == NULL) {
7085 return -EINVAL;
7086 }
7087 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7088 return -ENOSYS;
7089 }
7090 if (in->pcm == NULL) {
7091 return -ENOSYS;
7092 }
7093 struct timespec ts = { 0, 0 };
7094 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7095 if (ret < 0) {
7096 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7097 return ret;
7098 }
Phil Burke0a86d12019-02-16 22:28:11 -08007099 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7100 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007101 return 0;
7102}
7103
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307104static int in_get_active_microphones(const struct audio_stream_in *stream,
7105 struct audio_microphone_characteristic_t *mic_array,
7106 size_t *mic_count) {
7107 struct stream_in *in = (struct stream_in *)stream;
7108 struct audio_device *adev = in->dev;
7109 ALOGVV("%s", __func__);
7110
7111 lock_input_stream(in);
7112 pthread_mutex_lock(&adev->lock);
7113 int ret = platform_get_active_microphones(adev->platform,
7114 audio_channel_count_from_in_mask(in->channel_mask),
7115 in->usecase, mic_array, mic_count);
7116 pthread_mutex_unlock(&adev->lock);
7117 pthread_mutex_unlock(&in->lock);
7118
7119 return ret;
7120}
7121
7122static int adev_get_microphones(const struct audio_hw_device *dev,
7123 struct audio_microphone_characteristic_t *mic_array,
7124 size_t *mic_count) {
7125 struct audio_device *adev = (struct audio_device *)dev;
7126 ALOGVV("%s", __func__);
7127
7128 pthread_mutex_lock(&adev->lock);
7129 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7130 pthread_mutex_unlock(&adev->lock);
7131
7132 return ret;
7133}
juyuchendb308c22019-01-21 11:57:17 -07007134
7135static void in_update_sink_metadata(struct audio_stream_in *stream,
7136 const struct sink_metadata *sink_metadata) {
7137
7138 if (stream == NULL
7139 || sink_metadata == NULL
7140 || sink_metadata->tracks == NULL) {
7141 return;
7142 }
7143
7144 int error = 0;
7145 struct stream_in *in = (struct stream_in *)stream;
7146 struct audio_device *adev = in->dev;
7147 audio_devices_t device = AUDIO_DEVICE_NONE;
7148
7149 if (sink_metadata->track_count != 0)
7150 device = sink_metadata->tracks->dest_device;
7151
7152 lock_input_stream(in);
7153 pthread_mutex_lock(&adev->lock);
7154 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7155
7156 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7157 && device != AUDIO_DEVICE_NONE
7158 && adev->voice_tx_output != NULL) {
7159 /* Use the rx device from afe-proxy record to route voice call because
7160 there is no routing if tx device is on primary hal and rx device
7161 is on other hal during voice call. */
7162 adev->voice_tx_output->devices = device;
7163
7164 if (!voice_is_call_state_active(adev)) {
7165 if (adev->mode == AUDIO_MODE_IN_CALL) {
7166 adev->current_call_output = adev->voice_tx_output;
7167 error = voice_start_call(adev);
7168 if (error != 0)
7169 ALOGE("%s: start voice call failed %d", __func__, error);
7170 }
7171 } else {
7172 adev->current_call_output = adev->voice_tx_output;
7173 voice_update_devices_for_all_voice_usecases(adev);
7174 }
7175 }
7176
7177 pthread_mutex_unlock(&adev->lock);
7178 pthread_mutex_unlock(&in->lock);
7179}
7180
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307181int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007182 audio_io_handle_t handle,
7183 audio_devices_t devices,
7184 audio_output_flags_t flags,
7185 struct audio_config *config,
7186 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007187 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188{
7189 struct audio_device *adev = (struct audio_device *)dev;
7190 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307191 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007192 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007193 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307194 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007195 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7196 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7197 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7198 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007199 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007200 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7201 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007202 bool force_haptic_path =
7203 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007204 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007205
kunleizdff872d2018-08-20 14:40:33 +08007206 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007207 is_usb_dev = false;
7208 devices = AUDIO_DEVICE_OUT_SPEAKER;
7209 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7210 __func__, devices);
7211 }
7212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307214
Rahul Sharma99770982019-03-06 17:05:26 +05307215 pthread_mutex_lock(&adev->lock);
7216 if (out_get_stream(adev, handle) != NULL) {
7217 ALOGW("%s, output stream already opened", __func__);
7218 ret = -EEXIST;
7219 }
7220 pthread_mutex_unlock(&adev->lock);
7221 if (ret)
7222 return ret;
7223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7225
Mingming Yin3a941d42016-02-17 18:08:05 -08007226 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007227 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7228 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307229
7230
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007231 if (!out) {
7232 return -ENOMEM;
7233 }
7234
Haynes Mathew George204045b2015-02-25 20:32:03 -08007235 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007236 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307237 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007238 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007239 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007241 if (devices == AUDIO_DEVICE_NONE)
7242 devices = AUDIO_DEVICE_OUT_SPEAKER;
7243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 out->flags = flags;
7245 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007246 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007247 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007248 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307249 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307250 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7251 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7252 else
7253 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007254 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007255 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007256 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307257 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307258 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307259 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007260 out->hal_output_suspend_supported = 0;
7261 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307262 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307263 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307264 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007265
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307266 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307267 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007268 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7269
Aalique Grahame22e49102018-12-18 14:23:57 -08007270 if (direct_dev &&
7271 (audio_is_linear_pcm(out->format) ||
7272 config->format == AUDIO_FORMAT_DEFAULT) &&
7273 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7274 audio_format_t req_format = config->format;
7275 audio_channel_mask_t req_channel_mask = config->channel_mask;
7276 uint32_t req_sample_rate = config->sample_rate;
7277
7278 pthread_mutex_lock(&adev->lock);
7279 if (is_hdmi) {
7280 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7281 ret = read_hdmi_sink_caps(out);
7282 if (config->sample_rate == 0)
7283 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7284 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7285 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7286 if (config->format == AUDIO_FORMAT_DEFAULT)
7287 config->format = AUDIO_FORMAT_PCM_16_BIT;
7288 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007289 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7290 &config->format,
7291 &out->supported_formats[0],
7292 MAX_SUPPORTED_FORMATS,
7293 &config->channel_mask,
7294 &out->supported_channel_masks[0],
7295 MAX_SUPPORTED_CHANNEL_MASKS,
7296 &config->sample_rate,
7297 &out->supported_sample_rates[0],
7298 MAX_SUPPORTED_SAMPLE_RATES);
7299 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007300 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007301
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007302 pthread_mutex_unlock(&adev->lock);
7303 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007304 if (ret == -ENOSYS) {
7305 /* ignore and go with default */
7306 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007307 }
7308 // For MMAP NO IRQ, allow conversions in ADSP
7309 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7310 goto error_open;
7311 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007312 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007313 goto error_open;
7314 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007315
7316 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7317 config->sample_rate = req_sample_rate;
7318 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7319 config->channel_mask = req_channel_mask;
7320 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7321 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007322 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007323
7324 out->sample_rate = config->sample_rate;
7325 out->channel_mask = config->channel_mask;
7326 out->format = config->format;
7327 if (is_hdmi) {
7328 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7329 out->config = pcm_config_hdmi_multi;
7330 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7331 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7332 out->config = pcm_config_mmap_playback;
7333 out->stream.start = out_start;
7334 out->stream.stop = out_stop;
7335 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7336 out->stream.get_mmap_position = out_get_mmap_position;
7337 } else {
7338 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7339 out->config = pcm_config_hifi;
7340 }
7341
7342 out->config.rate = out->sample_rate;
7343 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7344 if (is_hdmi) {
7345 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7346 audio_bytes_per_sample(out->format));
7347 }
7348 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007349 }
7350
Derek Chenf6318be2017-06-12 17:16:24 -04007351 /* validate bus device address */
7352 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7353 /* extract car audio stream index */
7354 out->car_audio_stream =
7355 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7356 if (out->car_audio_stream < 0) {
7357 ALOGE("%s: invalid car audio stream %x",
7358 __func__, out->car_audio_stream);
7359 ret = -EINVAL;
7360 goto error_open;
7361 }
7362 /* save car audio stream and address for bus device */
7363 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7364 ALOGV("%s: address %s, car_audio_stream %x",
7365 __func__, out->address, out->car_audio_stream);
7366 }
7367
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007368 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007369 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007370 if (!voice_extn_is_compress_voip_supported()) {
7371 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7372 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007373 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7374 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007375 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7376 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007377 out->volume_l = INVALID_OUT_VOLUME;
7378 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007379
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007380 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007381 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007382 uint32_t channel_count =
7383 audio_channel_count_from_out_mask(out->channel_mask);
7384 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7385 out->sample_rate, out->format,
7386 channel_count, false);
7387 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7388 if (frame_size != 0)
7389 out->config.period_size = buffer_size / frame_size;
7390 else
7391 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007392 }
7393 } else {
7394 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7395 voice_extn_compress_voip_is_active(out->dev)) &&
7396 (voice_extn_compress_voip_is_config_supported(config))) {
7397 ret = voice_extn_compress_voip_open_output_stream(out);
7398 if (ret != 0) {
7399 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7400 __func__, ret);
7401 goto error_open;
7402 }
Sujin Panickerabaf5ad2019-09-16 18:28:06 +05307403 } else {
7404 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7405 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007406 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007407 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007408 } else if (audio_is_linear_pcm(out->format) &&
7409 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7410 out->channel_mask = config->channel_mask;
7411 out->sample_rate = config->sample_rate;
7412 out->format = config->format;
7413 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7414 // does this change?
7415 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7416 out->config.rate = config->sample_rate;
7417 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7418 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7419 audio_bytes_per_sample(config->format));
7420 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007421 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307422 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307423 pthread_mutex_lock(&adev->lock);
7424 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7425 pthread_mutex_unlock(&adev->lock);
7426
7427 // reject offload during card offline to allow
7428 // fallback to s/w paths
7429 if (offline) {
7430 ret = -ENODEV;
7431 goto error_open;
7432 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007434 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7435 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7436 ALOGE("%s: Unsupported Offload information", __func__);
7437 ret = -EINVAL;
7438 goto error_open;
7439 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007440
Atul Khare3fa6e542017-08-09 00:56:17 +05307441 if (config->offload_info.format == 0)
7442 config->offload_info.format = config->format;
7443 if (config->offload_info.sample_rate == 0)
7444 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007445
Mingming Yin90310102013-11-13 16:57:00 -08007446 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307447 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007448 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007449 ret = -EINVAL;
7450 goto error_open;
7451 }
7452
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007453 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7454 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7455 (audio_extn_passthru_is_passthrough_stream(out)) &&
7456 !((config->sample_rate == 48000) ||
7457 (config->sample_rate == 96000) ||
7458 (config->sample_rate == 192000))) {
7459 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7460 __func__, config->sample_rate, config->offload_info.format);
7461 ret = -EINVAL;
7462 goto error_open;
7463 }
7464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007465 out->compr_config.codec = (struct snd_codec *)
7466 calloc(1, sizeof(struct snd_codec));
7467
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007468 if (!out->compr_config.codec) {
7469 ret = -ENOMEM;
7470 goto error_open;
7471 }
7472
Dhananjay Kumarac341582017-02-23 23:42:25 +05307473 out->stream.pause = out_pause;
7474 out->stream.resume = out_resume;
7475 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307476 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307477 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007478 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307479 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007480 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307481 } else {
7482 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7483 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007484 }
vivek mehta446c3962015-09-14 10:57:35 -07007485
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307486 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7487 ALOGD("%s: Setting latency mode to true", __func__);
7488 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7489 }
7490
vivek mehta446c3962015-09-14 10:57:35 -07007491 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007492 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7493 config->format == 0 && config->sample_rate == 0 &&
7494 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007495 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007496 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7497 } else {
7498 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7499 ret = -EEXIST;
7500 goto error_open;
7501 }
vivek mehta446c3962015-09-14 10:57:35 -07007502 }
7503
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007504 if (config->offload_info.channel_mask)
7505 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007506 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007507 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007508 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007509 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307510 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007511 ret = -EINVAL;
7512 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007513 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007514
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007515 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007516 out->sample_rate = config->offload_info.sample_rate;
7517
Mingming Yin3ee55c62014-08-04 14:23:35 -07007518 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007519
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307520 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307521 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307522 audio_extn_dolby_send_ddp_endp_params(adev);
7523 audio_extn_dolby_set_dmid(adev);
7524 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007525
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007526 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007527 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007528 out->compr_config.codec->bit_rate =
7529 config->offload_info.bit_rate;
7530 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307531 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007532 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307533 /* Update bit width only for non passthrough usecases.
7534 * For passthrough usecases, the output will always be opened @16 bit
7535 */
7536 if (!audio_extn_passthru_is_passthrough_stream(out))
7537 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307538
7539 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7540 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7541 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7542
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007543 /*TODO: Do we need to change it for passthrough */
7544 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007545
Manish Dewangana6fc5442015-08-24 20:30:31 +05307546 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7547 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307548 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307549 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307550 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7551 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307552
7553 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7554 AUDIO_FORMAT_PCM) {
7555
7556 /*Based on platform support, configure appropriate alsa format for corresponding
7557 *hal input format.
7558 */
7559 out->compr_config.codec->format = hal_format_to_alsa(
7560 config->offload_info.format);
7561
Ashish Jain83a6cc22016-06-28 14:34:17 +05307562 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307563 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307564 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307565
Dhananjay Kumarac341582017-02-23 23:42:25 +05307566 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307567 *hal input format and alsa format might differ based on platform support.
7568 */
7569 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307570 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307571
7572 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7573
Deeraj Soman65358ab2019-02-07 15:40:49 +05307574 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7575 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7576 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7577
Ashish Jainf1eaa582016-05-23 20:54:24 +05307578 /* Check if alsa session is configured with the same format as HAL input format,
7579 * if not then derive correct fragment size needed to accomodate the
7580 * conversion of HAL input format to alsa format.
7581 */
7582 audio_extn_utils_update_direct_pcm_fragment_size(out);
7583
7584 /*if hal input and output fragment size is different this indicates HAL input format is
7585 *not same as the alsa format
7586 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307587 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307588 /*Allocate a buffer to convert input data to the alsa configured format.
7589 *size of convert buffer is equal to the size required to hold one fragment size
7590 *worth of pcm data, this is because flinger does not write more than fragment_size
7591 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307592 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7593 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307594 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7595 ret = -ENOMEM;
7596 goto error_open;
7597 }
7598 }
7599 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7600 out->compr_config.fragment_size =
7601 audio_extn_passthru_get_buffer_size(&config->offload_info);
7602 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7603 } else {
7604 out->compr_config.fragment_size =
7605 platform_get_compress_offload_buffer_size(&config->offload_info);
7606 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7607 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007608
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307609 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7610 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7611 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007612 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307613 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007614
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307615 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7616 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7617 }
7618
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007619 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7620 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007621
Manish Dewangan69426c82017-01-30 17:35:36 +05307622 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7623 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7624 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7625 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7626 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7627 } else {
7628 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7629 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007630
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307631 memset(&out->channel_map_param, 0,
7632 sizeof(struct audio_out_channel_map_param));
7633
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007634 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307635 out->send_next_track_params = false;
7636 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007637 out->offload_state = OFFLOAD_STATE_IDLE;
7638 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007639 out->writeAt.tv_sec = 0;
7640 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007641
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007642 audio_extn_dts_create_state_notifier_node(out->usecase);
7643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007644 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7645 __func__, config->offload_info.version,
7646 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307647
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307648 /* Check if DSD audio format is supported in codec
7649 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307650 */
7651
7652 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307653 (!platform_check_codec_dsd_support(adev->platform) ||
7654 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307655 ret = -EINVAL;
7656 goto error_open;
7657 }
7658
Ashish Jain5106d362016-05-11 19:23:33 +05307659 /* Disable gapless if any of the following is true
7660 * passthrough playback
7661 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307662 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307663 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307664 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307665 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007666 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307667 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307668 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307669 check_and_set_gapless_mode(adev, false);
7670 } else
7671 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007672
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307673 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007674 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7675 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307676 if (config->format == AUDIO_FORMAT_DSD) {
7677 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7678 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7679 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007680
7681 create_offload_callback_thread(out);
7682
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007683 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007684 switch (config->sample_rate) {
7685 case 0:
7686 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7687 break;
7688 case 8000:
7689 case 16000:
7690 case 48000:
7691 out->sample_rate = config->sample_rate;
7692 break;
7693 default:
7694 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7695 config->sample_rate);
7696 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7697 ret = -EINVAL;
7698 goto error_open;
7699 }
7700 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7701 switch (config->channel_mask) {
7702 case AUDIO_CHANNEL_NONE:
7703 case AUDIO_CHANNEL_OUT_STEREO:
7704 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7705 break;
7706 default:
7707 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7708 config->channel_mask);
7709 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7710 ret = -EINVAL;
7711 goto error_open;
7712 }
7713 switch (config->format) {
7714 case AUDIO_FORMAT_DEFAULT:
7715 case AUDIO_FORMAT_PCM_16_BIT:
7716 out->format = AUDIO_FORMAT_PCM_16_BIT;
7717 break;
7718 default:
7719 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7720 config->format);
7721 config->format = AUDIO_FORMAT_PCM_16_BIT;
7722 ret = -EINVAL;
7723 goto error_open;
7724 }
7725
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307726 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007727 if (ret != 0) {
7728 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007729 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007730 goto error_open;
7731 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007732 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007733 switch (config->sample_rate) {
7734 case 0:
7735 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7736 break;
7737 case 8000:
7738 case 16000:
7739 case 48000:
7740 out->sample_rate = config->sample_rate;
7741 break;
7742 default:
7743 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7744 config->sample_rate);
7745 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7746 ret = -EINVAL;
7747 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007748 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007749 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7750 switch (config->channel_mask) {
7751 case AUDIO_CHANNEL_NONE:
7752 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7753 break;
7754 case AUDIO_CHANNEL_OUT_STEREO:
7755 out->channel_mask = config->channel_mask;
7756 break;
7757 default:
7758 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7759 config->channel_mask);
7760 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7761 ret = -EINVAL;
7762 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007763 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007764 switch (config->format) {
7765 case AUDIO_FORMAT_DEFAULT:
7766 out->format = AUDIO_FORMAT_PCM_16_BIT;
7767 break;
7768 case AUDIO_FORMAT_PCM_16_BIT:
7769 out->format = config->format;
7770 break;
7771 default:
7772 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7773 config->format);
7774 config->format = AUDIO_FORMAT_PCM_16_BIT;
7775 ret = -EINVAL;
7776 break;
7777 }
7778 if (ret != 0)
7779 goto error_open;
7780
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007781 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7782 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007783 out->config.rate = out->sample_rate;
7784 out->config.channels =
7785 audio_channel_count_from_out_mask(out->channel_mask);
7786 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007787 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007788 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307789 unsigned int channels = 0;
7790 /*Update config params to default if not set by the caller*/
7791 if (config->sample_rate == 0)
7792 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7793 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7794 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7795 if (config->format == AUDIO_FORMAT_DEFAULT)
7796 config->format = AUDIO_FORMAT_PCM_16_BIT;
7797
7798 channels = audio_channel_count_from_out_mask(out->channel_mask);
7799
Varun Balaraje49253e2017-07-06 19:48:56 +05307800 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7801 out->usecase = get_interactive_usecase(adev);
7802 out->config = pcm_config_low_latency;
7803 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307804 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007805 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7806 out->flags);
7807 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007808 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7809 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7810 out->config = pcm_config_mmap_playback;
7811 out->stream.start = out_start;
7812 out->stream.stop = out_stop;
7813 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7814 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307815 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7816 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007817 out->hal_output_suspend_supported =
7818 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7819 out->dynamic_pm_qos_config_supported =
7820 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7821 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007822 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7823 } else {
7824 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7825 //the mixer path will be a string similar to "low-latency-playback resume"
7826 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7827 strlcat(out->pm_qos_mixer_path,
7828 " resume", MAX_MIXER_PATH_LEN);
7829 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7830 out->pm_qos_mixer_path);
7831 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307832 out->config = pcm_config_low_latency;
7833 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7834 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7835 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307836 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7837 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7838 if (out->config.period_size <= 0) {
7839 ALOGE("Invalid configuration period size is not valid");
7840 ret = -EINVAL;
7841 goto error_open;
7842 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007843 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7844 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7845 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007846 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7847 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7848 out->config = pcm_config_haptics_audio;
7849 if (force_haptic_path)
7850 adev->haptics_config = pcm_config_haptics_audio;
7851 else
7852 adev->haptics_config = pcm_config_haptics;
7853
7854 out->config.channels =
7855 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7856
7857 if (force_haptic_path) {
7858 out->config.channels = 1;
7859 adev->haptics_config.channels = 1;
7860 } else
7861 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007862 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7863 ret = audio_extn_auto_hal_open_output_stream(out);
7864 if (ret) {
7865 ALOGE("%s: Failed to open output stream for bus device", __func__);
7866 ret = -EINVAL;
7867 goto error_open;
7868 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307869 } else {
7870 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007871 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7872 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307873 }
7874 out->hal_ip_format = format = out->format;
7875 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7876 out->hal_op_format = pcm_format_to_hal(out->config.format);
7877 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7878 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007879 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307880 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307881 if (out->hal_ip_format != out->hal_op_format) {
7882 uint32_t buffer_size = out->config.period_size *
7883 format_to_bitwidth_table[out->hal_op_format] *
7884 out->config.channels;
7885 out->convert_buffer = calloc(1, buffer_size);
7886 if (out->convert_buffer == NULL){
7887 ALOGE("Allocation failed for convert buffer for size %d",
7888 out->compr_config.fragment_size);
7889 ret = -ENOMEM;
7890 goto error_open;
7891 }
7892 ALOGD("Convert buffer allocated of size %d", buffer_size);
7893 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007894 }
7895
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007896 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7897 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307898
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007899 /* TODO remove this hardcoding and check why width is zero*/
7900 if (out->bit_width == 0)
7901 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307902 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007903 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007904 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307905 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307906 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007907 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007908 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7909 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007910 if(adev->primary_output == NULL)
7911 adev->primary_output = out;
7912 else {
7913 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007914 ret = -EEXIST;
7915 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007916 }
7917 }
7918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007919 /* Check if this usecase is already existing */
7920 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007921 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7922 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007923 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007924 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007925 ret = -EEXIST;
7926 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007927 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007929 pthread_mutex_unlock(&adev->lock);
7930
7931 out->stream.common.get_sample_rate = out_get_sample_rate;
7932 out->stream.common.set_sample_rate = out_set_sample_rate;
7933 out->stream.common.get_buffer_size = out_get_buffer_size;
7934 out->stream.common.get_channels = out_get_channels;
7935 out->stream.common.get_format = out_get_format;
7936 out->stream.common.set_format = out_set_format;
7937 out->stream.common.standby = out_standby;
7938 out->stream.common.dump = out_dump;
7939 out->stream.common.set_parameters = out_set_parameters;
7940 out->stream.common.get_parameters = out_get_parameters;
7941 out->stream.common.add_audio_effect = out_add_audio_effect;
7942 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7943 out->stream.get_latency = out_get_latency;
7944 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007945#ifdef NO_AUDIO_OUT
7946 out->stream.write = out_write_for_no_output;
7947#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007948 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007949#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007950 out->stream.get_render_position = out_get_render_position;
7951 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007952 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007953
Haynes Mathew George16081042017-05-31 17:16:49 -07007954 if (out->realtime)
7955 out->af_period_multiplier = af_period_multiplier;
7956 else
7957 out->af_period_multiplier = 1;
7958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007959 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007960 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007961 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007962
7963 config->format = out->stream.common.get_format(&out->stream.common);
7964 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7965 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307966 register_format(out->format, out->supported_formats);
7967 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7968 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007969
Aalique Grahame22e49102018-12-18 14:23:57 -08007970 out->error_log = error_log_create(
7971 ERROR_LOG_ENTRIES,
7972 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7973
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307974 /*
7975 By locking output stream before registering, we allow the callback
7976 to update stream's state only after stream's initial state is set to
7977 adev state.
7978 */
7979 lock_output_stream(out);
7980 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7981 pthread_mutex_lock(&adev->lock);
7982 out->card_status = adev->card_status;
7983 pthread_mutex_unlock(&adev->lock);
7984 pthread_mutex_unlock(&out->lock);
7985
Aalique Grahame22e49102018-12-18 14:23:57 -08007986 stream_app_type_cfg_init(&out->app_type_cfg);
7987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007988 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307989 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007990 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007991
7992 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7993 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7994 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007995 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307996 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007997 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007998 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307999 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8000 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008001 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8002 out->usecase, PCM_PLAYBACK);
8003 hdlr_stream_cfg.flags = out->flags;
8004 hdlr_stream_cfg.type = PCM_PLAYBACK;
8005 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8006 &hdlr_stream_cfg);
8007 if (ret) {
8008 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8009 out->adsp_hdlr_stream_handle = NULL;
8010 }
8011 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308012 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8013 is_direct_passthough, false);
8014 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8015 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008016 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008017 if (ret < 0) {
8018 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8019 out->ip_hdlr_handle = NULL;
8020 }
8021 }
Derek Chenf939fb72018-11-13 13:34:41 -08008022
8023 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8024 calloc(1, sizeof(streams_output_ctxt_t));
8025 if (out_ctxt == NULL) {
8026 ALOGE("%s fail to allocate output ctxt", __func__);
8027 ret = -ENOMEM;
8028 goto error_open;
8029 }
8030 out_ctxt->output = out;
8031
8032 pthread_mutex_lock(&adev->lock);
8033 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8034 pthread_mutex_unlock(&adev->lock);
8035
Eric Laurent994a6932013-07-17 11:51:42 -07008036 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008037 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008038
8039error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308040 if (out->convert_buffer)
8041 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008042 free(out);
8043 *stream_out = NULL;
8044 ALOGD("%s: exit: ret %d", __func__, ret);
8045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008046}
8047
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308048void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008049 struct audio_stream_out *stream)
8050{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008051 struct stream_out *out = (struct stream_out *)stream;
8052 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008053 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008055 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308056
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308057 // must deregister from sndmonitor first to prevent races
8058 // between the callback and close_stream
8059 audio_extn_snd_mon_unregister_listener(out);
8060
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008061 /* close adsp hdrl session before standby */
8062 if (out->adsp_hdlr_stream_handle) {
8063 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8064 if (ret)
8065 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8066 out->adsp_hdlr_stream_handle = NULL;
8067 }
8068
Manish Dewangan21a850a2017-08-14 12:03:55 +05308069 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008070 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8071 out->ip_hdlr_handle = NULL;
8072 }
8073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008074 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308075 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008076 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308077 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308078 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008079 if(ret != 0)
8080 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8081 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008082 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008083 out_standby(&stream->common);
8084
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008085 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008086 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008087 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008088 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008089 if (out->compr_config.codec != NULL)
8090 free(out->compr_config.codec);
8091 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008092
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308093 out->a2dp_compress_mute = false;
8094
Varun Balaraje49253e2017-07-06 19:48:56 +05308095 if (is_interactive_usecase(out->usecase))
8096 free_interactive_usecase(adev, out->usecase);
8097
Ashish Jain83a6cc22016-06-28 14:34:17 +05308098 if (out->convert_buffer != NULL) {
8099 free(out->convert_buffer);
8100 out->convert_buffer = NULL;
8101 }
8102
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008103 if (adev->voice_tx_output == out)
8104 adev->voice_tx_output = NULL;
8105
Aalique Grahame22e49102018-12-18 14:23:57 -08008106 error_log_destroy(out->error_log);
8107 out->error_log = NULL;
8108
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308109 if (adev->primary_output == out)
8110 adev->primary_output = NULL;
8111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008112 pthread_cond_destroy(&out->cond);
8113 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008114
8115 pthread_mutex_lock(&adev->lock);
8116 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8117 if (out_ctxt != NULL) {
8118 list_remove(&out_ctxt->list);
8119 free(out_ctxt);
8120 } else {
8121 ALOGW("%s, output stream already closed", __func__);
8122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008123 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008124 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008125 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008126}
8127
8128static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8129{
8130 struct audio_device *adev = (struct audio_device *)dev;
8131 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008132 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008133 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008134 int ret;
8135 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008136 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008137 struct listnode *node;
8138 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008139
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008140 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008141 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008142
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308143 if (!parms)
8144 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308145
Derek Chen6f293672019-04-01 01:40:24 -07008146 /* notify adev and input/output streams on the snd card status */
8147 adev_snd_mon_cb((void *)adev, parms);
8148
8149 list_for_each(node, &adev->active_outputs_list) {
8150 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8151 streams_output_ctxt_t,
8152 list);
8153 out_snd_mon_cb((void *)out_ctxt->output, parms);
8154 }
8155
8156 list_for_each(node, &adev->active_inputs_list) {
8157 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8158 streams_input_ctxt_t,
8159 list);
8160 in_snd_mon_cb((void *)in_ctxt->input, parms);
8161 }
8162
Zhou Songd6d71752019-05-21 18:08:51 +08008163 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308164 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8165 if (ret >= 0) {
8166 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008167 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308168 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008169 } else {
8170 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308171 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008172 audio_extn_sco_reset_configuration();
8173 list_for_each(node, &adev->usecase_list) {
8174 usecase = node_to_item(node, struct audio_usecase, list);
8175 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
8176 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
8177 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
8178 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
8179 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
8180 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
8181 else
8182 continue;
8183 select_devices(adev, usecase->id);
8184 }
8185 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308186 }
8187
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008188 status = voice_set_parameters(adev, parms);
8189 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008190 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008191
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008192 status = platform_set_parameters(adev->platform, parms);
8193 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008194 goto done;
8195
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008196 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8197 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008198 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8200 adev->bluetooth_nrec = true;
8201 else
8202 adev->bluetooth_nrec = false;
8203 }
8204
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008205 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8206 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008207 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8208 adev->screen_off = false;
8209 else
8210 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008211 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008212 }
8213
Eric Laurent4b084132018-10-19 17:33:43 -07008214 ret = str_parms_get_int(parms, "rotation", &val);
8215 if (ret >= 0) {
8216 bool reverse_speakers = false;
8217 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8218 switch (val) {
8219 // FIXME: note that the code below assumes that the speakers are in the correct placement
8220 // relative to the user when the device is rotated 90deg from its default rotation. This
8221 // assumption is device-specific, not platform-specific like this code.
8222 case 270:
8223 reverse_speakers = true;
8224 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8225 break;
8226 case 0:
8227 case 180:
8228 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8229 break;
8230 case 90:
8231 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8232 break;
8233 default:
8234 ALOGE("%s: unexpected rotation of %d", __func__, val);
8235 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008236 }
Eric Laurent4b084132018-10-19 17:33:43 -07008237 if (status == 0) {
8238 // check and set swap
8239 // - check if orientation changed and speaker active
8240 // - set rotation and cache the rotation value
8241 adev->camera_orientation =
8242 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8243 if (!audio_extn_is_maxx_audio_enabled())
8244 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8245 }
8246 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008247
Mingming Yin514a8bc2014-07-29 15:22:21 -07008248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8249 if (ret >= 0) {
8250 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8251 adev->bt_wb_speech_enabled = true;
8252 else
8253 adev->bt_wb_speech_enabled = false;
8254 }
8255
Zhou Song12c29502019-03-16 10:37:18 +08008256 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8257 if (ret >= 0) {
8258 val = atoi(value);
8259 adev->swb_speech_mode = val;
8260 }
8261
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8263 if (ret >= 0) {
8264 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308265 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008266 if (audio_is_output_device(val) &&
8267 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008268 ALOGV("cache new ext disp type and edid");
8269 ret = platform_get_ext_disp_type(adev->platform);
8270 if (ret < 0) {
8271 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308272 } else {
8273 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008274 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308275 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008276 /*
8277 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8278 * Per AudioPolicyManager, USB device is higher priority than WFD.
8279 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8280 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8281 * starting voice call on USB
8282 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008283 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308284 if (ret >= 0)
8285 audio_extn_usb_add_device(device, atoi(value));
8286
Zhou Song6f862822017-11-06 17:27:57 +08008287 if (!audio_extn_usb_is_tunnel_supported()) {
8288 ALOGV("detected USB connect .. disable proxy");
8289 adev->allow_afe_proxy_usage = false;
8290 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008291 }
8292 }
8293
8294 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8295 if (ret >= 0) {
8296 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308297 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008298 /*
8299 * The HDMI / Displayport disconnect handling has been moved to
8300 * audio extension to ensure that its parameters are not
8301 * invalidated prior to updating sysfs of the disconnect event
8302 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8303 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308304 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008305 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308306 if (ret >= 0)
8307 audio_extn_usb_remove_device(device, atoi(value));
8308
Zhou Song6f862822017-11-06 17:27:57 +08008309 if (!audio_extn_usb_is_tunnel_supported()) {
8310 ALOGV("detected USB disconnect .. enable proxy");
8311 adev->allow_afe_proxy_usage = true;
8312 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008313 }
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05308314 if (audio_is_a2dp_out_device(device)) {
8315 struct audio_usecase *usecase;
8316 struct listnode *node;
8317 list_for_each(node, &adev->usecase_list) {
8318 usecase = node_to_item(node, struct audio_usecase, list);
8319 if (PCM_PLAYBACK == usecase->type && usecase->stream.out &&
8320 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8321 usecase->stream.out->a2dp_compress_mute) {
8322 struct stream_out *out = usecase->stream.out;
8323 ALOGD("Unmuting the stream when Bt-A2dp disconnected and stream is mute");
8324 out->a2dp_compress_mute = false;
8325 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8326 }
8327 }
8328 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008329 }
8330
Aalique Grahame22e49102018-12-18 14:23:57 -08008331 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008332 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008333
8334 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008335 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308336 struct audio_usecase *usecase;
8337 struct listnode *node;
8338 list_for_each(node, &adev->usecase_list) {
8339 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308340 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008341 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308342 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008343 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308344 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008345 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308346 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308347 ALOGD("Switching to speaker and muting the stream before select_devices");
8348 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308349 //force device switch to re configure encoder
8350 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308351 ALOGD("Unmuting the stream after select_devices");
8352 usecase->stream.out->a2dp_compress_mute = false;
8353 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 +05308354 audio_extn_a2dp_set_handoff_mode(false);
8355 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308356 break;
8357 }
8358 }
8359 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008360
8361 //handle vr audio setparam
8362 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8363 value, sizeof(value));
8364 if (ret >= 0) {
8365 ALOGI("Setting vr mode to be %s", value);
8366 if (!strncmp(value, "true", 4)) {
8367 adev->vr_audio_mode_enabled = true;
8368 ALOGI("Setting vr mode to true");
8369 } else if (!strncmp(value, "false", 5)) {
8370 adev->vr_audio_mode_enabled = false;
8371 ALOGI("Setting vr mode to false");
8372 } else {
8373 ALOGI("wrong vr mode set");
8374 }
8375 }
8376
Eric Laurent4b084132018-10-19 17:33:43 -07008377 //FIXME: to be replaced by proper video capture properties API
8378 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8379 if (ret >= 0) {
8380 int camera_facing = CAMERA_FACING_BACK;
8381 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8382 camera_facing = CAMERA_FACING_FRONT;
8383 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8384 camera_facing = CAMERA_FACING_BACK;
8385 else {
8386 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8387 goto done;
8388 }
8389 adev->camera_orientation =
8390 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8391 struct audio_usecase *usecase;
8392 struct listnode *node;
8393 list_for_each(node, &adev->usecase_list) {
8394 usecase = node_to_item(node, struct audio_usecase, list);
8395 struct stream_in *in = usecase->stream.in;
8396 if (usecase->type == PCM_CAPTURE && in != NULL &&
8397 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8398 select_devices(adev, in->usecase);
8399 }
8400 }
8401 }
8402
Balázs Triszkaa68afd52017-05-11 03:19:29 +02008403 ret = str_parms_get_int(parms, "ultrasound-sensor", &val);
8404 if (ret >= 0) {
8405 if (val == 1) {
8406 us_start();
8407 } else {
8408 us_stop();
8409 }
8410 }
8411
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05308412 amplifier_set_parameters(parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308413 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008414done:
8415 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008416 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308417error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008418 ALOGV("%s: exit with code(%d)", __func__, status);
8419 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008420}
8421
8422static char* adev_get_parameters(const struct audio_hw_device *dev,
8423 const char *keys)
8424{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308425 ALOGD("%s:%s", __func__, keys);
8426
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008427 struct audio_device *adev = (struct audio_device *)dev;
8428 struct str_parms *reply = str_parms_create();
8429 struct str_parms *query = str_parms_create_str(keys);
8430 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308431 char value[256] = {0};
8432 int ret = 0;
8433
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008434 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008435 if (reply) {
8436 str_parms_destroy(reply);
8437 }
8438 if (query) {
8439 str_parms_destroy(query);
8440 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008441 ALOGE("adev_get_parameters: failed to create query or reply");
8442 return NULL;
8443 }
8444
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008445 //handle vr audio getparam
8446
8447 ret = str_parms_get_str(query,
8448 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8449 value, sizeof(value));
8450
8451 if (ret >= 0) {
8452 bool vr_audio_enabled = false;
8453 pthread_mutex_lock(&adev->lock);
8454 vr_audio_enabled = adev->vr_audio_mode_enabled;
8455 pthread_mutex_unlock(&adev->lock);
8456
8457 ALOGI("getting vr mode to %d", vr_audio_enabled);
8458
8459 if (vr_audio_enabled) {
8460 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8461 "true");
8462 goto exit;
8463 } else {
8464 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8465 "false");
8466 goto exit;
8467 }
8468 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008469
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008470 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008471 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008472 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008473 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008474 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308475 pthread_mutex_unlock(&adev->lock);
8476
Naresh Tannirud7205b62014-06-20 02:54:48 +05308477exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008478 str = str_parms_to_str(reply);
8479 str_parms_destroy(query);
8480 str_parms_destroy(reply);
8481
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308482 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008483 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008484}
8485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008486static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008487{
8488 return 0;
8489}
8490
8491static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8492{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008493 int ret;
8494 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008495
8496 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8497
Haynes Mathew George5191a852013-09-11 14:19:36 -07008498 pthread_mutex_lock(&adev->lock);
8499 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008500 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008501 pthread_mutex_unlock(&adev->lock);
8502 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008503}
8504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008505static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8506 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008507{
8508 return -ENOSYS;
8509}
8510
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008511static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8512 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008513{
8514 return -ENOSYS;
8515}
8516
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008517static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8518 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008519{
8520 return -ENOSYS;
8521}
8522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008523static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8524 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008525{
8526 return -ENOSYS;
8527}
8528
8529static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8530{
8531 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008532 struct listnode *node;
8533 struct audio_usecase *usecase = NULL;
8534 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008536 pthread_mutex_lock(&adev->lock);
8537 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008538 ALOGD("%s: mode %d\n", __func__, mode);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05308539 if (amplifier_set_mode(mode) != 0)
8540 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008541 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008542 if (voice_is_in_call(adev) &&
8543 (mode == AUDIO_MODE_NORMAL ||
8544 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008545 list_for_each(node, &adev->usecase_list) {
8546 usecase = node_to_item(node, struct audio_usecase, list);
8547 if (usecase->type == VOICE_CALL)
8548 break;
8549 }
8550 if (usecase &&
8551 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8552 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8553 true);
8554 if (ret != 0) {
8555 /* default service interval was successfully updated,
8556 reopen USB backend with new service interval */
8557 check_usecases_codec_backend(adev,
8558 usecase,
8559 usecase->out_snd_device);
8560 }
8561 }
8562
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008563 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008564 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008565 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008566 // restore device for other active usecases after stop call
8567 list_for_each(node, &adev->usecase_list) {
8568 usecase = node_to_item(node, struct audio_usecase, list);
8569 select_devices(adev, usecase->id);
8570 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008571 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008572 }
8573 pthread_mutex_unlock(&adev->lock);
8574 return 0;
8575}
8576
8577static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8578{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008579 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008580 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008581
8582 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008583 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008584 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008585
Derek Chend2530072014-11-24 12:39:14 -08008586 if (adev->ext_hw_plugin)
8587 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008588
8589 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008590 pthread_mutex_unlock(&adev->lock);
8591
8592 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008593}
8594
8595static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8596{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008597 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008598 return 0;
8599}
8600
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008601static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008602 const struct audio_config *config)
8603{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008604 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008605
Aalique Grahame22e49102018-12-18 14:23:57 -08008606 /* Don't know if USB HIFI in this context so use true to be conservative */
8607 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8608 true /*is_usb_hifi */) != 0)
8609 return 0;
8610
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008611 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8612 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008613}
8614
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008615static bool adev_input_allow_hifi_record(struct audio_device *adev,
8616 audio_devices_t devices,
8617 audio_input_flags_t flags,
8618 audio_source_t source) {
8619 const bool allowed = true;
8620
8621 if (!audio_is_usb_in_device(devices))
8622 return !allowed;
8623
8624 switch (flags) {
8625 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008626 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008627 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8628 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008629 default:
8630 return !allowed;
8631 }
8632
8633 switch (source) {
8634 case AUDIO_SOURCE_DEFAULT:
8635 case AUDIO_SOURCE_MIC:
8636 case AUDIO_SOURCE_UNPROCESSED:
8637 break;
8638 default:
8639 return !allowed;
8640 }
8641
8642 switch (adev->mode) {
8643 case 0:
8644 break;
8645 default:
8646 return !allowed;
8647 }
8648
8649 return allowed;
8650}
8651
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008652static int adev_update_voice_comm_input_stream(struct stream_in *in,
8653 struct audio_config *config)
8654{
8655 bool valid_rate = (config->sample_rate == 8000 ||
8656 config->sample_rate == 16000 ||
8657 config->sample_rate == 32000 ||
8658 config->sample_rate == 48000);
8659 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8660
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008661 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008662 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008663 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8664 in->config = default_pcm_config_voip_copp;
8665 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8666 DEFAULT_VOIP_BUF_DURATION_MS,
8667 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008668 } else {
8669 ALOGW("%s No valid input in voip, use defaults"
8670 "sample rate %u, channel mask 0x%X",
8671 __func__, config->sample_rate, in->channel_mask);
8672 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008673 in->config.rate = config->sample_rate;
8674 in->sample_rate = config->sample_rate;
8675 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008676 //XXX needed for voice_extn_compress_voip_open_input_stream
8677 in->config.rate = config->sample_rate;
8678 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathacd1de7d2019-08-23 15:13:46 +05308679 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008680 voice_extn_compress_voip_is_active(in->dev)) &&
8681 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8682 valid_rate && valid_ch) {
8683 voice_extn_compress_voip_open_input_stream(in);
8684 // update rate entries to match config from AF
8685 in->config.rate = config->sample_rate;
8686 in->sample_rate = config->sample_rate;
8687 } else {
8688 ALOGW("%s compress voip not active, use defaults", __func__);
8689 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008690 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008691 return 0;
8692}
8693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008694static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008695 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008696 audio_devices_t devices,
8697 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008698 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308699 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008700 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008701 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008702{
8703 struct audio_device *adev = (struct audio_device *)dev;
8704 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008705 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008706 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008707 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308708 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008709 bool is_usb_dev = audio_is_usb_in_device(devices);
8710 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8711 devices,
8712 flags,
8713 source);
Andy Hung94320602018-10-29 18:31:12 -07008714 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8715 " sample_rate %u, channel_mask %#x, format %#x",
8716 __func__, flags, is_usb_dev, may_use_hifi_record,
8717 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308718
kunleizdff872d2018-08-20 14:40:33 +08008719 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008720 is_usb_dev = false;
8721 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8722 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8723 __func__, devices);
8724 }
8725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008726 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008727
8728 if (!(is_usb_dev && may_use_hifi_record)) {
8729 if (config->sample_rate == 0)
8730 config->sample_rate = 48000;
8731 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8732 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8733 if (config->format == AUDIO_FORMAT_DEFAULT)
8734 config->format = AUDIO_FORMAT_PCM_16_BIT;
8735
8736 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8737
Aalique Grahame22e49102018-12-18 14:23:57 -08008738 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8739 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008740 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008742
Rahul Sharma99770982019-03-06 17:05:26 +05308743 pthread_mutex_lock(&adev->lock);
8744 if (in_get_stream(adev, handle) != NULL) {
8745 ALOGW("%s, input stream already opened", __func__);
8746 ret = -EEXIST;
8747 }
8748 pthread_mutex_unlock(&adev->lock);
8749 if (ret)
8750 return ret;
8751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008752 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008753
8754 if (!in) {
8755 ALOGE("failed to allocate input stream");
8756 return -ENOMEM;
8757 }
8758
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308759 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308760 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8761 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008762 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008763 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008765 in->stream.common.get_sample_rate = in_get_sample_rate;
8766 in->stream.common.set_sample_rate = in_set_sample_rate;
8767 in->stream.common.get_buffer_size = in_get_buffer_size;
8768 in->stream.common.get_channels = in_get_channels;
8769 in->stream.common.get_format = in_get_format;
8770 in->stream.common.set_format = in_set_format;
8771 in->stream.common.standby = in_standby;
8772 in->stream.common.dump = in_dump;
8773 in->stream.common.set_parameters = in_set_parameters;
8774 in->stream.common.get_parameters = in_get_parameters;
8775 in->stream.common.add_audio_effect = in_add_audio_effect;
8776 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8777 in->stream.set_gain = in_set_gain;
8778 in->stream.read = in_read;
8779 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008780 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308781 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008782 in->stream.set_microphone_direction = in_set_microphone_direction;
8783 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008784 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008785
8786 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008787 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008788 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008789 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008790 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008791 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008792 in->bit_width = 16;
8793 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008794 in->direction = MIC_DIRECTION_UNSPECIFIED;
8795 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008796 list_init(&in->aec_list);
8797 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008798
Andy Hung94320602018-10-29 18:31:12 -07008799 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008800 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8801 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8802 /* Force channel config requested to mono if incall
8803 record is being requested for only uplink/downlink */
8804 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8805 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8806 ret = -EINVAL;
8807 goto err_open;
8808 }
8809 }
8810
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008811 if (is_usb_dev && may_use_hifi_record) {
8812 /* HiFi record selects an appropriate format, channel, rate combo
8813 depending on sink capabilities*/
8814 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8815 &config->format,
8816 &in->supported_formats[0],
8817 MAX_SUPPORTED_FORMATS,
8818 &config->channel_mask,
8819 &in->supported_channel_masks[0],
8820 MAX_SUPPORTED_CHANNEL_MASKS,
8821 &config->sample_rate,
8822 &in->supported_sample_rates[0],
8823 MAX_SUPPORTED_SAMPLE_RATES);
8824 if (ret != 0) {
8825 ret = -EINVAL;
8826 goto err_open;
8827 }
8828 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008829 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308830 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308831 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8832 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8833 in->config.format = PCM_FORMAT_S32_LE;
8834 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308835 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8836 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8837 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8838 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8839 bool ret_error = false;
8840 in->bit_width = 24;
8841 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8842 from HAL is 24_packed and 8_24
8843 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8844 24_packed return error indicating supported format is 24_packed
8845 *> In case of any other source requesting 24 bit or float return error
8846 indicating format supported is 16 bit only.
8847
8848 on error flinger will retry with supported format passed
8849 */
8850 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8851 (source != AUDIO_SOURCE_CAMCORDER)) {
8852 config->format = AUDIO_FORMAT_PCM_16_BIT;
8853 if (config->sample_rate > 48000)
8854 config->sample_rate = 48000;
8855 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008856 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8857 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308858 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8859 ret_error = true;
8860 }
8861
8862 if (ret_error) {
8863 ret = -EINVAL;
8864 goto err_open;
8865 }
8866 }
8867
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008868 in->channel_mask = config->channel_mask;
8869 in->format = config->format;
8870
8871 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308872
8873 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8874 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8875 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8876 else {
8877 ret = -EINVAL;
8878 goto err_open;
8879 }
8880 }
8881
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008882 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308883 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8884 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008885 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8886 is_low_latency = true;
8887#if LOW_LATENCY_CAPTURE_USE_CASE
8888 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8889#endif
8890 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008891 if (!in->realtime) {
8892 in->config = pcm_config_audio_capture;
8893 frame_size = audio_stream_in_frame_size(&in->stream);
8894 buffer_size = get_input_buffer_size(config->sample_rate,
8895 config->format,
8896 channel_count,
8897 is_low_latency);
8898 in->config.period_size = buffer_size / frame_size;
8899 in->config.rate = config->sample_rate;
8900 in->af_period_multiplier = 1;
8901 } else {
8902 // period size is left untouched for rt mode playback
8903 in->config = pcm_config_audio_capture_rt;
8904 in->af_period_multiplier = af_period_multiplier;
8905 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008906 }
8907
8908 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8909 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8910 in->realtime = 0;
8911 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8912 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008913 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008914 in->stream.start = in_start;
8915 in->stream.stop = in_stop;
8916 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8917 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008918 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8919 } else if (in->realtime) {
8920 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008921 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008922 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008923 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008924 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8925 in->config = pcm_config_audio_capture;
8926 frame_size = audio_stream_in_frame_size(&in->stream);
8927 buffer_size = get_input_buffer_size(config->sample_rate,
8928 config->format,
8929 channel_count,
8930 false /*is_low_latency*/);
8931 in->config.period_size = buffer_size / frame_size;
8932 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008933 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008934 switch (config->format) {
8935 case AUDIO_FORMAT_PCM_32_BIT:
8936 in->bit_width = 32;
8937 break;
8938 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8939 case AUDIO_FORMAT_PCM_8_24_BIT:
8940 in->bit_width = 24;
8941 break;
8942 default:
8943 in->bit_width = 16;
8944 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008945 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308946 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008947 if (config->sample_rate == 0)
8948 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8949 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8950 config->sample_rate != 8000) {
8951 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8952 ret = -EINVAL;
8953 goto err_open;
8954 }
8955 if (config->format == AUDIO_FORMAT_DEFAULT)
8956 config->format = AUDIO_FORMAT_PCM_16_BIT;
8957 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8958 config->format = AUDIO_FORMAT_PCM_16_BIT;
8959 ret = -EINVAL;
8960 goto err_open;
8961 }
8962
8963 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8964 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008965 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008966 in->af_period_multiplier = 1;
8967 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8968 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8969 (config->sample_rate == 8000 ||
8970 config->sample_rate == 16000 ||
8971 config->sample_rate == 32000 ||
8972 config->sample_rate == 48000) &&
8973 channel_count == 1) {
8974 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8975 in->config = pcm_config_audio_capture;
8976 frame_size = audio_stream_in_frame_size(&in->stream);
8977 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8978 config->sample_rate,
8979 config->format,
8980 channel_count, false /*is_low_latency*/);
8981 in->config.period_size = buffer_size / frame_size;
8982 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8983 in->config.rate = config->sample_rate;
8984 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008985 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308986 int ret_val;
8987 pthread_mutex_lock(&adev->lock);
8988 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8989 in, config, &channel_mask_updated);
8990 pthread_mutex_unlock(&adev->lock);
8991
8992 if (!ret_val) {
8993 if (channel_mask_updated == true) {
8994 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8995 __func__, config->channel_mask);
8996 ret = -EINVAL;
8997 goto err_open;
8998 }
8999 ALOGD("%s: created multi-channel session succesfully",__func__);
9000 } else if (audio_extn_compr_cap_enabled() &&
9001 audio_extn_compr_cap_format_supported(config->format) &&
9002 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9003 audio_extn_compr_cap_init(in);
9004 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309005 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309006 if (ret)
9007 goto err_open;
9008 } else {
9009 in->config = pcm_config_audio_capture;
9010 in->config.rate = config->sample_rate;
9011 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309012 in->format = config->format;
9013 frame_size = audio_stream_in_frame_size(&in->stream);
9014 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009015 config->format,
9016 channel_count,
9017 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009018 /* prevent division-by-zero */
9019 if (frame_size == 0) {
9020 ALOGE("%s: Error frame_size==0", __func__);
9021 ret = -EINVAL;
9022 goto err_open;
9023 }
9024
Revathi Uddarajud2634032017-12-07 14:42:34 +05309025 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009026 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009027
Revathi Uddarajud2634032017-12-07 14:42:34 +05309028 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9029 /* optionally use VOIP usecase depending on config(s) */
9030 ret = adev_update_voice_comm_input_stream(in, config);
9031 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009032
Revathi Uddarajud2634032017-12-07 14:42:34 +05309033 if (ret) {
9034 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9035 goto err_open;
9036 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009037 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309038 if (audio_extn_is_concurrent_capture_enabled()) {
9039 /* Acquire lock to avoid two concurrent use cases initialized to
9040 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009041
Samyak Jainc37062f2019-04-25 18:41:06 +05309042 if (in->usecase == USECASE_AUDIO_RECORD) {
9043 pthread_mutex_lock(&adev->lock);
9044 if (!(adev->pcm_record_uc_state)) {
9045 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9046 adev->pcm_record_uc_state = 1;
9047 pthread_mutex_unlock(&adev->lock);
9048 } else {
9049 pthread_mutex_unlock(&adev->lock);
9050 /* Assign compress record use case for second record */
9051 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9052 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9053 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9054 if (audio_extn_cin_applicable_stream(in)) {
9055 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309056 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309057 if (ret)
9058 goto err_open;
9059 }
9060 }
9061 }
kunleiz28c73e72019-03-27 17:24:04 +08009062 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009063 }
Ramjee Singh8b09cc12019-08-21 16:31:33 +05309064 if (audio_extn_ssr_get_stream() != in)
9065 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009066
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009067 in->sample_rate = in->config.rate;
9068
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309069 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9070 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009071 devices, flags, in->format,
9072 in->sample_rate, in->bit_width,
9073 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309074 register_format(in->format, in->supported_formats);
9075 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9076 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309077
Aalique Grahame22e49102018-12-18 14:23:57 -08009078 in->error_log = error_log_create(
9079 ERROR_LOG_ENTRIES,
9080 1000000000 /* aggregate consecutive identical errors within one second */);
9081
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009082 /* This stream could be for sound trigger lab,
9083 get sound trigger pcm if present */
9084 audio_extn_sound_trigger_check_and_get_session(in);
9085
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309086 lock_input_stream(in);
9087 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9088 pthread_mutex_lock(&adev->lock);
9089 in->card_status = adev->card_status;
9090 pthread_mutex_unlock(&adev->lock);
9091 pthread_mutex_unlock(&in->lock);
9092
Aalique Grahame22e49102018-12-18 14:23:57 -08009093 stream_app_type_cfg_init(&in->app_type_cfg);
9094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009095 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009096
9097 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9098 calloc(1, sizeof(streams_input_ctxt_t));
9099 if (in_ctxt == NULL) {
9100 ALOGE("%s fail to allocate input ctxt", __func__);
9101 ret = -ENOMEM;
9102 goto err_open;
9103 }
9104 in_ctxt->input = in;
9105
9106 pthread_mutex_lock(&adev->lock);
9107 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9108 pthread_mutex_unlock(&adev->lock);
9109
Eric Laurent994a6932013-07-17 11:51:42 -07009110 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009111 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112
9113err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309114 if (in->usecase == USECASE_AUDIO_RECORD) {
9115 pthread_mutex_lock(&adev->lock);
9116 adev->pcm_record_uc_state = 0;
9117 pthread_mutex_unlock(&adev->lock);
9118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009119 free(in);
9120 *stream_in = NULL;
9121 return ret;
9122}
9123
9124static void adev_close_input_stream(struct audio_hw_device *dev,
9125 struct audio_stream_in *stream)
9126{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009127 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009128 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009129 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309130
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309131 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009132
kunleiz70e57612018-12-28 17:50:23 +08009133 /* must deregister from sndmonitor first to prevent races
9134 * between the callback and close_stream
9135 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309136 audio_extn_snd_mon_unregister_listener(stream);
9137
kunleiz70e57612018-12-28 17:50:23 +08009138 /* Disable echo reference if there are no active input, hfp call
9139 * and sound trigger while closing input stream
9140 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009141 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009142 !audio_extn_hfp_is_active(adev) &&
9143 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009144 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009145 else
9146 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309147
Pallavid7c7a272018-01-16 11:22:55 +05309148 if (in == NULL) {
9149 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9150 return;
9151 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009152 error_log_destroy(in->error_log);
9153 in->error_log = NULL;
9154
Pallavid7c7a272018-01-16 11:22:55 +05309155
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009156 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309157 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009158 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309159 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009160 if (ret != 0)
9161 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9162 __func__, ret);
9163 } else
9164 in_standby(&stream->common);
9165
Revathi Uddarajud2634032017-12-07 14:42:34 +05309166 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309167 if (in->usecase == USECASE_AUDIO_RECORD) {
9168 adev->pcm_record_uc_state = 0;
9169 }
9170
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009171 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009172 audio_extn_ssr_deinit();
9173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009174
Garmond Leunge2433c32017-09-28 21:51:22 -07009175 if (audio_extn_ffv_get_stream() == in) {
9176 audio_extn_ffv_stream_deinit();
9177 }
9178
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309179 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009180 audio_extn_compr_cap_format_supported(in->config.format))
9181 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309182
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309183 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309184 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009185
Mingming Yinfd7607b2016-01-22 12:48:44 -08009186 if (in->is_st_session) {
9187 ALOGV("%s: sound trigger pcm stop lab", __func__);
9188 audio_extn_sound_trigger_stop_lab(in);
9189 }
Derek Chenf939fb72018-11-13 13:34:41 -08009190 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9191 if (in_ctxt != NULL) {
9192 list_remove(&in_ctxt->list);
9193 free(in_ctxt);
9194 } else {
9195 ALOGW("%s, input stream already closed", __func__);
9196 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009197 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309198 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009199 return;
9200}
9201
Aalique Grahame22e49102018-12-18 14:23:57 -08009202/* verifies input and output devices and their capabilities.
9203 *
9204 * This verification is required when enabling extended bit-depth or
9205 * sampling rates, as not all qcom products support it.
9206 *
9207 * Suitable for calling only on initialization such as adev_open().
9208 * It fills the audio_device use_case_table[] array.
9209 *
9210 * Has a side-effect that it needs to configure audio routing / devices
9211 * in order to power up the devices and read the device parameters.
9212 * It does not acquire any hw device lock. Should restore the devices
9213 * back to "normal state" upon completion.
9214 */
9215static int adev_verify_devices(struct audio_device *adev)
9216{
9217 /* enumeration is a bit difficult because one really wants to pull
9218 * the use_case, device id, etc from the hidden pcm_device_table[].
9219 * In this case there are the following use cases and device ids.
9220 *
9221 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9222 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9223 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9224 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9225 * [USECASE_AUDIO_RECORD] = {0, 0},
9226 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9227 * [USECASE_VOICE_CALL] = {2, 2},
9228 *
9229 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9230 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9231 */
9232
9233 /* should be the usecases enabled in adev_open_input_stream() */
9234 static const int test_in_usecases[] = {
9235 USECASE_AUDIO_RECORD,
9236 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9237 };
9238 /* should be the usecases enabled in adev_open_output_stream()*/
9239 static const int test_out_usecases[] = {
9240 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9241 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9242 };
9243 static const usecase_type_t usecase_type_by_dir[] = {
9244 PCM_PLAYBACK,
9245 PCM_CAPTURE,
9246 };
9247 static const unsigned flags_by_dir[] = {
9248 PCM_OUT,
9249 PCM_IN,
9250 };
9251
9252 size_t i;
9253 unsigned dir;
9254 const unsigned card_id = adev->snd_card;
9255
9256 for (dir = 0; dir < 2; ++dir) {
9257 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9258 const unsigned flags_dir = flags_by_dir[dir];
9259 const size_t testsize =
9260 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9261 const int *testcases =
9262 dir ? test_in_usecases : test_out_usecases;
9263 const audio_devices_t audio_device =
9264 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9265
9266 for (i = 0; i < testsize; ++i) {
9267 const audio_usecase_t audio_usecase = testcases[i];
9268 int device_id;
9269 struct pcm_params **pparams;
9270 struct stream_out out;
9271 struct stream_in in;
9272 struct audio_usecase uc_info;
9273 int retval;
9274
9275 pparams = &adev->use_case_table[audio_usecase];
9276 pcm_params_free(*pparams); /* can accept null input */
9277 *pparams = NULL;
9278
9279 /* find the device ID for the use case (signed, for error) */
9280 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9281 if (device_id < 0)
9282 continue;
9283
9284 /* prepare structures for device probing */
9285 memset(&uc_info, 0, sizeof(uc_info));
9286 uc_info.id = audio_usecase;
9287 uc_info.type = usecase_type;
9288 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009289 memset(&in, 0, sizeof(in));
9290 in.device = audio_device;
9291 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9292 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009293 }
9294 memset(&out, 0, sizeof(out));
9295 out.devices = audio_device; /* only field needed in select_devices */
9296 uc_info.stream.out = &out;
9297 uc_info.devices = audio_device;
9298 uc_info.in_snd_device = SND_DEVICE_NONE;
9299 uc_info.out_snd_device = SND_DEVICE_NONE;
9300 list_add_tail(&adev->usecase_list, &uc_info.list);
9301
9302 /* select device - similar to start_(in/out)put_stream() */
9303 retval = select_devices(adev, audio_usecase);
9304 if (retval >= 0) {
9305 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9306#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009307 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009308 if (*pparams) {
9309 ALOGV("%s: (%s) card %d device %d", __func__,
9310 dir ? "input" : "output", card_id, device_id);
9311 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9312 } else {
9313 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9314 }
9315#endif
9316 }
9317
9318 /* deselect device - similar to stop_(in/out)put_stream() */
9319 /* 1. Get and set stream specific mixer controls */
9320 retval = disable_audio_route(adev, &uc_info);
9321 /* 2. Disable the rx device */
9322 retval = disable_snd_device(adev,
9323 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9324 list_remove(&uc_info.list);
9325 }
9326 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009327 return 0;
9328}
9329
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309330int adev_create_audio_patch(struct audio_hw_device *dev,
9331 unsigned int num_sources,
9332 const struct audio_port_config *sources,
9333 unsigned int num_sinks,
9334 const struct audio_port_config *sinks,
9335 audio_patch_handle_t *handle)
9336{
Derek Chenf939fb72018-11-13 13:34:41 -08009337 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309338
Derek Chenf939fb72018-11-13 13:34:41 -08009339 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9340 num_sources,
9341 sources,
9342 num_sinks,
9343 sinks,
9344 handle);
9345 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9346 num_sources,
9347 sources,
9348 num_sinks,
9349 sinks,
9350 handle);
9351 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309352}
9353
9354int adev_release_audio_patch(struct audio_hw_device *dev,
9355 audio_patch_handle_t handle)
9356{
Derek Chenf939fb72018-11-13 13:34:41 -08009357 int ret;
9358
9359 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9360 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9361 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309362}
9363
9364int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9365{
Derek Chenf13dd492018-11-13 14:53:51 -08009366 int ret = 0;
9367
9368 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9369 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9370 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309371}
9372
9373int adev_set_audio_port_config(struct audio_hw_device *dev,
9374 const struct audio_port_config *config)
9375{
Derek Chenf13dd492018-11-13 14:53:51 -08009376 int ret = 0;
9377
9378 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9379 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9380 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309381}
9382
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009383static int adev_dump(const audio_hw_device_t *device __unused,
9384 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009385{
9386 return 0;
9387}
9388
9389static int adev_close(hw_device_t *device)
9390{
Aalique Grahame22e49102018-12-18 14:23:57 -08009391 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309392 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009393
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309394 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009395 return 0;
9396
9397 pthread_mutex_lock(&adev_init_lock);
9398
9399 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309400 if (audio_extn_spkr_prot_is_enabled())
9401 audio_extn_spkr_prot_deinit();
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05309402 if (amplifier_close() != 0)
9403 ALOGE("Amplifier close failed");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309404 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009405 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009406 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009407 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009408 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309409 audio_extn_utils_release_streams_cfg_lists(
9410 &adev->streams_output_cfg_list,
9411 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309412 if (audio_extn_qap_is_enabled())
9413 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309414 if (audio_extn_qaf_is_enabled())
9415 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009416 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009417 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009418 free(adev->snd_dev_ref_cnt);
9419 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009420 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9421 pcm_params_free(adev->use_case_table[i]);
9422 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009423 if (adev->adm_deinit)
9424 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309425 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009426 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309427 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309428 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009429 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309430 if (adev->device_cfg_params) {
9431 free(adev->device_cfg_params);
9432 adev->device_cfg_params = NULL;
9433 }
Derek Chend2530072014-11-24 12:39:14 -08009434 if(adev->ext_hw_plugin)
9435 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009436 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009437 free(device);
9438 adev = NULL;
9439 }
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009440
9441 us_deinit();
9442
Kiran Kandi910e1862013-10-29 13:29:42 -07009443 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309444 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009445 return 0;
9446}
9447
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009448/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9449 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9450 * just that it _might_ work.
9451 */
9452static int period_size_is_plausible_for_low_latency(int period_size)
9453{
9454 switch (period_size) {
9455 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009456 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009457 case 240:
9458 case 320:
9459 case 480:
9460 return 1;
9461 default:
9462 return 0;
9463 }
9464}
9465
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309466static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9467{
9468 bool is_snd_card_status = false;
9469 bool is_ext_device_status = false;
9470 char value[32];
9471 int card = -1;
9472 card_status_t status;
9473
9474 if (cookie != adev || !parms)
9475 return;
9476
9477 if (!parse_snd_card_status(parms, &card, &status)) {
9478 is_snd_card_status = true;
9479 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9480 is_ext_device_status = true;
9481 } else {
9482 // not a valid event
9483 return;
9484 }
9485
9486 pthread_mutex_lock(&adev->lock);
9487 if (card == adev->snd_card || is_ext_device_status) {
9488 if (is_snd_card_status && adev->card_status != status) {
9489 adev->card_status = status;
9490 platform_snd_card_update(adev->platform, status);
9491 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009492 audio_extn_auto_hal_set_parameters(adev, parms);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309493 } else if (is_ext_device_status) {
9494 platform_set_parameters(adev->platform, parms);
9495 }
9496 }
9497 pthread_mutex_unlock(&adev->lock);
9498 return;
9499}
9500
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309501/* out and adev lock held */
9502static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9503{
9504 struct audio_usecase *uc_info;
9505 float left_p;
9506 float right_p;
9507 audio_devices_t devices;
9508
9509 uc_info = get_usecase_from_list(adev, out->usecase);
9510 if (uc_info == NULL) {
9511 ALOGE("%s: Could not find the usecase (%d) in the list",
9512 __func__, out->usecase);
9513 return -EINVAL;
9514 }
9515
9516 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9517 out->usecase, use_case_table[out->usecase]);
9518
9519 if (restore) {
9520 // restore A2DP device for active usecases and unmute if required
9521 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9522 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9523 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9524 select_devices(adev, uc_info->id);
9525 pthread_mutex_lock(&out->compr_mute_lock);
9526 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05309527 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309528 out->a2dp_compress_mute = false;
9529 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9530 }
9531 pthread_mutex_unlock(&out->compr_mute_lock);
9532 }
9533 } else {
9534 // mute compress stream if suspended
9535 pthread_mutex_lock(&out->compr_mute_lock);
9536 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9537 (!out->a2dp_compress_mute)) {
9538 if (!out->standby) {
9539 ALOGD("%s: selecting speaker and muting stream", __func__);
9540 devices = out->devices;
9541 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9542 left_p = out->volume_l;
9543 right_p = out->volume_r;
9544 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9545 compress_pause(out->compr);
9546 out_set_compr_volume(&out->stream, (float)0, (float)0);
9547 out->a2dp_compress_mute = true;
9548 select_devices(adev, out->usecase);
9549 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9550 compress_resume(out->compr);
9551 out->devices = devices;
9552 out->volume_l = left_p;
9553 out->volume_r = right_p;
9554 }
9555 }
9556 pthread_mutex_unlock(&out->compr_mute_lock);
9557 }
9558 ALOGV("%s: exit", __func__);
9559 return 0;
9560}
9561
9562int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9563{
9564 int ret = 0;
9565
9566 lock_output_stream(out);
9567 pthread_mutex_lock(&adev->lock);
9568
9569 ret = check_a2dp_restore_l(adev, out, restore);
9570
9571 pthread_mutex_unlock(&adev->lock);
9572 pthread_mutex_unlock(&out->lock);
9573 return ret;
9574}
9575
Haynes Mathew George01156f92018-04-13 15:29:54 -07009576void adev_on_battery_status_changed(bool charging)
9577{
9578 pthread_mutex_lock(&adev->lock);
9579 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9580 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009581 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009582 pthread_mutex_unlock(&adev->lock);
9583}
9584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009585static int adev_open(const hw_module_t *module, const char *name,
9586 hw_device_t **device)
9587{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309588 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009589 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309590 char mixer_ctl_name[128] = {0};
9591 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309592
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009593 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009594 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9595
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009596 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009597 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009598 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009599 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009600 ALOGD("%s: returning existing instance of adev", __func__);
9601 ALOGD("%s: exit", __func__);
9602 pthread_mutex_unlock(&adev_init_lock);
9603 return 0;
9604 }
9605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009606 adev = calloc(1, sizeof(struct audio_device));
9607
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009608 if (!adev) {
9609 pthread_mutex_unlock(&adev_init_lock);
9610 return -ENOMEM;
9611 }
9612
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009613 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9614
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009615 // register audio ext hidl at the earliest
9616 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309617#ifdef DYNAMIC_LOG_ENABLED
9618 register_for_dynamic_logging("hal");
9619#endif
9620
Derek Chenf939fb72018-11-13 13:34:41 -08009621 /* default audio HAL major version */
9622 uint32_t maj_version = 2;
9623 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9624 maj_version = atoi(value);
9625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009626 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009627 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009628 adev->device.common.module = (struct hw_module_t *)module;
9629 adev->device.common.close = adev_close;
9630
9631 adev->device.init_check = adev_init_check;
9632 adev->device.set_voice_volume = adev_set_voice_volume;
9633 adev->device.set_master_volume = adev_set_master_volume;
9634 adev->device.get_master_volume = adev_get_master_volume;
9635 adev->device.set_master_mute = adev_set_master_mute;
9636 adev->device.get_master_mute = adev_get_master_mute;
9637 adev->device.set_mode = adev_set_mode;
9638 adev->device.set_mic_mute = adev_set_mic_mute;
9639 adev->device.get_mic_mute = adev_get_mic_mute;
9640 adev->device.set_parameters = adev_set_parameters;
9641 adev->device.get_parameters = adev_get_parameters;
9642 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9643 adev->device.open_output_stream = adev_open_output_stream;
9644 adev->device.close_output_stream = adev_close_output_stream;
9645 adev->device.open_input_stream = adev_open_input_stream;
9646 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309647 adev->device.create_audio_patch = adev_create_audio_patch;
9648 adev->device.release_audio_patch = adev_release_audio_patch;
9649 adev->device.get_audio_port = adev_get_audio_port;
9650 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009651 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309652 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009653
9654 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009655 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009656 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009657 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009658 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009659 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009660 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309661 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009662 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009663 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009664 /* Init audio and voice feature */
9665 audio_extn_feature_init();
9666 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009667 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009668 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009669 list_init(&adev->active_inputs_list);
9670 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +05309671 list_init(&adev->audio_patch_record_list);
9672 adev->audio_patch_index = 0;
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009673 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009674 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309675 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309676 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309677 adev->perf_lock_opts[0] = 0x101;
9678 adev->perf_lock_opts[1] = 0x20E;
9679 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009680 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009681 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309682 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009683 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009685 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009686 adev->platform = platform_init(adev);
9687 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009688 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009689 free(adev->snd_dev_ref_cnt);
9690 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009691 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009692 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9693 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009694 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009695 return -EINVAL;
9696 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009697
Aalique Grahame22e49102018-12-18 14:23:57 -08009698 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309699 if (audio_extn_qap_is_enabled()) {
9700 ret = audio_extn_qap_init(adev);
9701 if (ret < 0) {
9702 pthread_mutex_destroy(&adev->lock);
9703 free(adev);
9704 adev = NULL;
9705 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9706 *device = NULL;
9707 pthread_mutex_unlock(&adev_init_lock);
9708 return ret;
9709 }
9710 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
9711 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
9712 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009713
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309714 if (audio_extn_qaf_is_enabled()) {
9715 ret = audio_extn_qaf_init(adev);
9716 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009717 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309718 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009719 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309720 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9721 *device = NULL;
9722 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309723 return ret;
9724 }
9725
9726 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9727 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9728 }
9729
Derek Chenae7b0342019-02-08 15:17:04 -08009730 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009731 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9732
Eric Laurentc4aef752013-09-12 17:45:53 -07009733 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9734 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9735 if (adev->visualizer_lib == NULL) {
9736 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9737 } else {
9738 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9739 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009740 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009741 "visualizer_hal_start_output");
9742 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009743 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009744 "visualizer_hal_stop_output");
9745 }
9746 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309747 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009748 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009749 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009750 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309751 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009752 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009753
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009754 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9755 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9756 if (adev->offload_effects_lib == NULL) {
9757 ALOGE("%s: DLOPEN failed for %s", __func__,
9758 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9759 } else {
9760 ALOGV("%s: DLOPEN successful for %s", __func__,
9761 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9762 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309763 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009764 "offload_effects_bundle_hal_start_output");
9765 adev->offload_effects_stop_output =
9766 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9767 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009768 adev->offload_effects_set_hpx_state =
9769 (int (*)(bool))dlsym(adev->offload_effects_lib,
9770 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309771 adev->offload_effects_get_parameters =
9772 (void (*)(struct str_parms *, struct str_parms *))
9773 dlsym(adev->offload_effects_lib,
9774 "offload_effects_bundle_get_parameters");
9775 adev->offload_effects_set_parameters =
9776 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9777 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009778 }
9779 }
9780
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009781 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9782 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9783 if (adev->adm_lib == NULL) {
9784 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9785 } else {
9786 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9787 adev->adm_init = (adm_init_t)
9788 dlsym(adev->adm_lib, "adm_init");
9789 adev->adm_deinit = (adm_deinit_t)
9790 dlsym(adev->adm_lib, "adm_deinit");
9791 adev->adm_register_input_stream = (adm_register_input_stream_t)
9792 dlsym(adev->adm_lib, "adm_register_input_stream");
9793 adev->adm_register_output_stream = (adm_register_output_stream_t)
9794 dlsym(adev->adm_lib, "adm_register_output_stream");
9795 adev->adm_deregister_stream = (adm_deregister_stream_t)
9796 dlsym(adev->adm_lib, "adm_deregister_stream");
9797 adev->adm_request_focus = (adm_request_focus_t)
9798 dlsym(adev->adm_lib, "adm_request_focus");
9799 adev->adm_abandon_focus = (adm_abandon_focus_t)
9800 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009801 adev->adm_set_config = (adm_set_config_t)
9802 dlsym(adev->adm_lib, "adm_set_config");
9803 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9804 dlsym(adev->adm_lib, "adm_request_focus_v2");
9805 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9806 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9807 adev->adm_on_routing_change = (adm_on_routing_change_t)
9808 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009809 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9810 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009811 }
9812 }
9813
Aalique Grahame22e49102018-12-18 14:23:57 -08009814 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009815 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009816 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009817 //initialize this to false for now,
9818 //this will be set to true through set param
9819 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009820
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009821 audio_extn_ds2_enable(adev);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009822
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05309823 if (amplifier_open(adev) != 0)
9824 ALOGE("Amplifier initialization failed");
9825
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009826 us_init(adev);
9827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009828 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009829
9830 if (k_enable_extended_precision)
9831 adev_verify_devices(adev);
9832
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009833 adev->dsp_bit_width_enforce_mode =
9834 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009835
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309836 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9837 &adev->streams_output_cfg_list,
9838 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009839
Kiran Kandi910e1862013-10-29 13:29:42 -07009840 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009841
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009842 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009843 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9844 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009845 trial = atoi(value);
9846 if (period_size_is_plausible_for_low_latency(trial)) {
9847 pcm_config_low_latency.period_size = trial;
9848 pcm_config_low_latency.start_threshold = trial / 4;
9849 pcm_config_low_latency.avail_min = trial / 4;
9850 configured_low_latency_capture_period_size = trial;
9851 }
9852 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009853 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9854 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009855 trial = atoi(value);
9856 if (period_size_is_plausible_for_low_latency(trial)) {
9857 configured_low_latency_capture_period_size = trial;
9858 }
9859 }
9860
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009861 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9862
Eric Laurent4b084132018-10-19 17:33:43 -07009863 adev->camera_orientation = CAMERA_DEFAULT;
9864
Aalique Grahame22e49102018-12-18 14:23:57 -08009865 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9866 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009867 af_period_multiplier = atoi(value);
9868 if (af_period_multiplier < 0)
9869 af_period_multiplier = 2;
9870 else if (af_period_multiplier > 4)
9871 af_period_multiplier = 4;
9872
9873 ALOGV("new period_multiplier = %d", af_period_multiplier);
9874 }
9875
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009876 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009877
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009878 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009879 pthread_mutex_unlock(&adev_init_lock);
9880
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009881 if (adev->adm_init)
9882 adev->adm_data = adev->adm_init();
9883
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309884 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309885 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009886 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309887
9888 audio_extn_snd_mon_init();
9889 pthread_mutex_lock(&adev->lock);
9890 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9891 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009892 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9893 /*
9894 * if the battery state callback happens before charging can be queried,
9895 * it will be guarded with the adev->lock held in the cb function and so
9896 * the callback value will reflect the latest state
9897 */
9898 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309899 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009900 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009901 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009902 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309903 /* Allocate memory for Device config params */
9904 adev->device_cfg_params = (struct audio_device_config_param*)
9905 calloc(platform_get_max_codec_backend(),
9906 sizeof(struct audio_device_config_param));
9907 if (adev->device_cfg_params == NULL)
9908 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309909
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309910 /*
9911 * Check if new PSPD matrix mixer control is supported. If not
9912 * supported, then set flag so that old mixer ctrl is sent while
9913 * sending pspd coefficients on older kernel version. Query mixer
9914 * control for default pcm id and channel value one.
9915 */
9916 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9917 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9918
9919 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9920 if (!ctl) {
9921 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9922 __func__, mixer_ctl_name);
9923 adev->use_old_pspd_mix_ctrl = true;
9924 }
9925
Eric Laurent994a6932013-07-17 11:51:42 -07009926 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009927 return 0;
9928}
9929
9930static struct hw_module_methods_t hal_module_methods = {
9931 .open = adev_open,
9932};
9933
9934struct audio_module HAL_MODULE_INFO_SYM = {
9935 .common = {
9936 .tag = HARDWARE_MODULE_TAG,
9937 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9938 .hal_api_version = HARDWARE_HAL_API_VERSION,
9939 .id = AUDIO_HARDWARE_MODULE_ID,
9940 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009941 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009942 .methods = &hal_module_methods,
9943 },
9944};