blob: 300107da60f46eb251514ff1d1b46cf980eddb64 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shalini Manjunatha8a17fe32020-01-03 15:00:14 +05302 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
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),
Mingshu pang9915e022019-10-25 15:38:27 +0800496 STRING_TO_ENUM(352800),
497 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700498};
499
Carter Hsu2e429db2019-05-14 18:50:52 +0800500struct in_effect_list {
501 struct listnode list;
502 effect_handle_t handle;
503};
504
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700505static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700506static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700507static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700508//cache last MBDRC cal step level
509static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700510
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530511static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
512static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700513static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800514static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530515static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530516
Derek Chen6f293672019-04-01 01:40:24 -0700517static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
518static void in_snd_mon_cb(void * stream, struct str_parms * parms);
519static void out_snd_mon_cb(void * stream, struct str_parms * parms);
520
Zhou Song4721e282019-08-26 14:16:12 +0800521static int configure_btsco_sample_rate(snd_device_t snd_device);
522
Vatsal Buchac09ae062018-11-14 13:25:08 +0530523#ifdef AUDIO_FEATURE_ENABLED_GCOV
524extern void __gcov_flush();
525static void enable_gcov()
526{
527 __gcov_flush();
528}
529#else
530static void enable_gcov()
531{
532}
533#endif
534
justinweng20fb6d82019-02-21 18:49:00 -0700535static int in_set_microphone_direction(const struct audio_stream_in *stream,
536 audio_microphone_direction_t dir);
537static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
538
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700539static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
540 int flags __unused)
541{
542 int dir = 0;
543 switch (uc_id) {
544 case USECASE_AUDIO_RECORD_LOW_LATENCY:
545 dir = 1;
546 case USECASE_AUDIO_PLAYBACK_ULL:
547 break;
548 default:
549 return false;
550 }
551
552 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
553 PCM_PLAYBACK : PCM_CAPTURE);
554 if (adev->adm_is_noirq_avail)
555 return adev->adm_is_noirq_avail(adev->adm_data,
556 adev->snd_card, dev_id, dir);
557 return false;
558}
559
560static void register_out_stream(struct stream_out *out)
561{
562 struct audio_device *adev = out->dev;
563 if (is_offload_usecase(out->usecase) ||
564 !adev->adm_register_output_stream)
565 return;
566
567 // register stream first for backward compatibility
568 adev->adm_register_output_stream(adev->adm_data,
569 out->handle,
570 out->flags);
571
572 if (!adev->adm_set_config)
573 return;
574
575 if (out->realtime)
576 adev->adm_set_config(adev->adm_data,
577 out->handle,
578 out->pcm, &out->config);
579}
580
581static void register_in_stream(struct stream_in *in)
582{
583 struct audio_device *adev = in->dev;
584 if (!adev->adm_register_input_stream)
585 return;
586
587 adev->adm_register_input_stream(adev->adm_data,
588 in->capture_handle,
589 in->flags);
590
591 if (!adev->adm_set_config)
592 return;
593
594 if (in->realtime)
595 adev->adm_set_config(adev->adm_data,
596 in->capture_handle,
597 in->pcm,
598 &in->config);
599}
600
601static void request_out_focus(struct stream_out *out, long ns)
602{
603 struct audio_device *adev = out->dev;
604
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700605 if (adev->adm_request_focus_v2)
606 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
607 else if (adev->adm_request_focus)
608 adev->adm_request_focus(adev->adm_data, out->handle);
609}
610
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700611static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700612{
613 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700615
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 if (adev->adm_request_focus_v2_1)
617 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
618 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus)
621 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700622
623 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700624}
625
626static void release_out_focus(struct stream_out *out)
627{
628 struct audio_device *adev = out->dev;
629
630 if (adev->adm_abandon_focus)
631 adev->adm_abandon_focus(adev->adm_data, out->handle);
632}
633
634static void release_in_focus(struct stream_in *in)
635{
636 struct audio_device *adev = in->dev;
637 if (adev->adm_abandon_focus)
638 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
639}
640
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530641static int parse_snd_card_status(struct str_parms *parms, int *card,
642 card_status_t *status)
643{
644 char value[32]={0};
645 char state[32]={0};
646
647 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
648 if (ret < 0)
649 return -1;
650
651 // sscanf should be okay as value is of max length 32.
652 // same as sizeof state.
653 if (sscanf(value, "%d,%s", card, state) < 2)
654 return -1;
655
656 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
657 CARD_STATUS_OFFLINE;
658 return 0;
659}
660
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700661static inline void adjust_frames_for_device_delay(struct stream_out *out,
662 uint32_t *dsp_frames) {
663 // Adjustment accounts for A2dp encoder latency with offload usecases
664 // Note: Encoder latency is returned in ms.
665 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
666 unsigned long offset =
667 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
668 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
669 }
670}
671
vivek mehtaa76401a2015-04-24 14:12:15 -0700672__attribute__ ((visibility ("default")))
673bool audio_hw_send_gain_dep_calibration(int level) {
674 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700675 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700676
677 pthread_mutex_lock(&adev_init_lock);
678
679 if (adev != NULL && adev->platform != NULL) {
680 pthread_mutex_lock(&adev->lock);
681 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700682
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530683 // cache level info for any of the use case which
684 // was not started.
685 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700686
vivek mehtaa76401a2015-04-24 14:12:15 -0700687 pthread_mutex_unlock(&adev->lock);
688 } else {
689 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
690 }
691
692 pthread_mutex_unlock(&adev_init_lock);
693
694 return ret_val;
695}
696
Ashish Jain5106d362016-05-11 19:23:33 +0530697static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
698{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800699 bool gapless_enabled = false;
700 const char *mixer_ctl_name = "Compress Gapless Playback";
701 struct mixer_ctl *ctl;
702
703 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700704 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530705
706 /*Disable gapless if its AV playback*/
707 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800708
709 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
710 if (!ctl) {
711 ALOGE("%s: Could not get ctl for mixer cmd - %s",
712 __func__, mixer_ctl_name);
713 return -EINVAL;
714 }
715
716 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
717 ALOGE("%s: Could not set gapless mode %d",
718 __func__, gapless_enabled);
719 return -EINVAL;
720 }
721 return 0;
722}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700723
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700724__attribute__ ((visibility ("default")))
725int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
726 int table_size) {
727 int ret_val = 0;
728 ALOGV("%s: enter ... ", __func__);
729
730 pthread_mutex_lock(&adev_init_lock);
731 if (adev == NULL) {
732 ALOGW("%s: adev is NULL .... ", __func__);
733 goto done;
734 }
735
736 pthread_mutex_lock(&adev->lock);
737 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
738 pthread_mutex_unlock(&adev->lock);
739done:
740 pthread_mutex_unlock(&adev_init_lock);
741 ALOGV("%s: exit ... ", __func__);
742 return ret_val;
743}
744
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800745bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800746{
747 bool ret = false;
748 ALOGV("%s: enter ...", __func__);
749
750 pthread_mutex_lock(&adev_init_lock);
751
752 if (adev != NULL && adev->platform != NULL) {
753 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800754 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800755 pthread_mutex_unlock(&adev->lock);
756 }
757
758 pthread_mutex_unlock(&adev_init_lock);
759
760 ALOGV("%s: exit with ret %d", __func__, ret);
761 return ret;
762}
Aalique Grahame22e49102018-12-18 14:23:57 -0800763
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700764static bool is_supported_format(audio_format_t format)
765{
Eric Laurent86e17132013-09-12 17:49:30 -0700766 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530767 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530768 format == AUDIO_FORMAT_AAC_LC ||
769 format == AUDIO_FORMAT_AAC_HE_V1 ||
770 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530771 format == AUDIO_FORMAT_AAC_ADTS_LC ||
772 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
773 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530774 format == AUDIO_FORMAT_AAC_LATM_LC ||
775 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
776 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530777 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
778 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530779 format == AUDIO_FORMAT_PCM_FLOAT ||
780 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700781 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530782 format == AUDIO_FORMAT_AC3 ||
783 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700784 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530785 format == AUDIO_FORMAT_DTS ||
786 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800787 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530788 format == AUDIO_FORMAT_ALAC ||
789 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530790 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530791 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800792 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530793 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700794 format == AUDIO_FORMAT_APTX ||
795 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800796 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700797
798 return false;
799}
800
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700801static inline bool is_mmap_usecase(audio_usecase_t uc_id)
802{
803 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
804 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
805}
806
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700807static inline bool is_valid_volume(float left, float right)
808{
809 return ((left >= 0.0f && right >= 0.0f) ? true : false);
810}
811
Avinash Vaish71a8b972014-07-24 15:36:33 +0530812static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
813 struct audio_usecase *uc_info)
814{
815 struct listnode *node;
816 struct audio_usecase *usecase;
817
818 if (uc_info == NULL)
819 return -EINVAL;
820
821 /* Re-route all voice usecases on the shared backend other than the
822 specified usecase to new snd devices */
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800825 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530826 enable_audio_route(adev, usecase);
827 }
828 return 0;
829}
830
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530831static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530832{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530833 ALOGV("%s", __func__);
834 audio_route_apply_and_update_path(adev->audio_route,
835 "asrc-mode");
836 adev->asrc_mode_enabled = true;
837}
838
839static void disable_asrc_mode(struct audio_device *adev)
840{
841 ALOGV("%s", __func__);
842 audio_route_reset_and_update_path(adev->audio_route,
843 "asrc-mode");
844 adev->asrc_mode_enabled = false;
845}
846
847/*
848 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
849 * 44.1 or Native DSD backends are enabled for any of current use case.
850 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
851 * - Disable current mix path use case(Headphone backend) and re-enable it with
852 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
853 * e.g. Naitve DSD or Headphone 44.1 -> + 48
854 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530855static void check_and_set_asrc_mode(struct audio_device *adev,
856 struct audio_usecase *uc_info,
857 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530858{
859 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530860 int i, num_new_devices = 0;
861 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
862 /*
863 *Split snd device for new combo use case
864 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
865 */
866 if (platform_split_snd_device(adev->platform,
867 snd_device,
868 &num_new_devices,
869 split_new_snd_devices) == 0) {
870 for (i = 0; i < num_new_devices; i++)
871 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
872 } else {
873 int new_backend_idx = platform_get_backend_index(snd_device);
874 if (((new_backend_idx == HEADPHONE_BACKEND) ||
875 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
876 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
877 !adev->asrc_mode_enabled) {
878 struct listnode *node = NULL;
879 struct audio_usecase *uc = NULL;
880 struct stream_out *curr_out = NULL;
881 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
882 int i, num_devices, ret = 0;
883 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530884
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530885 list_for_each(node, &adev->usecase_list) {
886 uc = node_to_item(node, struct audio_usecase, list);
887 curr_out = (struct stream_out*) uc->stream.out;
888 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
889 /*
890 *Split snd device for existing combo use case
891 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
892 */
893 ret = platform_split_snd_device(adev->platform,
894 uc->out_snd_device,
895 &num_devices,
896 split_snd_devices);
897 if (ret < 0 || num_devices == 0) {
898 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
899 split_snd_devices[0] = uc->out_snd_device;
900 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800901 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530902 for (i = 0; i < num_devices; i++) {
903 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
904 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
905 if((new_backend_idx == HEADPHONE_BACKEND) &&
906 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
907 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
908 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
909 __func__);
910 enable_asrc_mode(adev);
911 break;
912 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
913 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
914 (usecase_backend_idx == HEADPHONE_BACKEND)) {
915 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
916 __func__);
917 disable_audio_route(adev, uc);
918 disable_snd_device(adev, uc->out_snd_device);
919 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
920 if (new_backend_idx == DSD_NATIVE_BACKEND)
921 audio_route_apply_and_update_path(adev->audio_route,
922 "hph-true-highquality-mode");
923 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
924 (curr_out->bit_width >= 24))
925 audio_route_apply_and_update_path(adev->audio_route,
926 "hph-highquality-mode");
927 enable_asrc_mode(adev);
928 enable_snd_device(adev, uc->out_snd_device);
929 enable_audio_route(adev, uc);
930 break;
931 }
932 }
933 // reset split devices count
934 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800935 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530936 if (adev->asrc_mode_enabled)
937 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530938 }
939 }
940 }
941}
942
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700943static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
944 struct audio_effect_config effect_config,
945 unsigned int param_value)
946{
947 char mixer_ctl_name[] = "Audio Effect";
948 struct mixer_ctl *ctl;
949 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800950 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700951
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700952 if (in == NULL) {
953 ALOGE("%s: active input stream is NULL", __func__);
954 return -EINVAL;
955 }
956
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700957 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
958 if (!ctl) {
959 ALOGE("%s: Could not get mixer ctl - %s",
960 __func__, mixer_ctl_name);
961 return -EINVAL;
962 }
963
964 set_values[0] = 1; //0:Rx 1:Tx
965 set_values[1] = in->app_type_cfg.app_type;
966 set_values[2] = (long)effect_config.module_id;
967 set_values[3] = (long)effect_config.instance_id;
968 set_values[4] = (long)effect_config.param_id;
969 set_values[5] = param_value;
970
971 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
972
973 return 0;
974
975}
976
977static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
978 int effect_type, unsigned int *param_value)
979{
980 int ret = 0;
981 struct audio_effect_config other_effect_config;
982 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800983 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700984
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700985 if (in == NULL) {
986 ALOGE("%s: active input stream is NULL", __func__);
987 return -EINVAL;
988 }
989
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700990 usecase = get_usecase_from_list(adev, in->usecase);
991 if (!usecase)
992 return -EINVAL;
993
994 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
995 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
996 if (ret < 0) {
997 ALOGE("%s Failed to get effect params %d", __func__, ret);
998 return ret;
999 }
1000
1001 if (module_id == other_effect_config.module_id) {
1002 //Same module id for AEC/NS. Values need to be combined
1003 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1004 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1005 *param_value |= other_effect_config.param_value;
1006 }
1007 }
1008
1009 return ret;
1010}
1011
1012static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301013{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001014 struct audio_effect_config effect_config;
1015 struct audio_usecase *usecase = NULL;
1016 int ret = 0;
1017 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001018 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001019
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001020 if(!voice_extn_is_dynamic_ecns_enabled())
1021 return ENOSYS;
1022
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001023 if (!in) {
1024 ALOGE("%s: Invalid input stream", __func__);
1025 return -EINVAL;
1026 }
1027
1028 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1029
1030 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001031 if (usecase == NULL) {
1032 ALOGE("%s: Could not find the usecase (%d) in the list",
1033 __func__, in->usecase);
1034 return -EINVAL;
1035 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001036
1037 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1038 if (ret < 0) {
1039 ALOGE("%s Failed to get module id %d", __func__, ret);
1040 return ret;
1041 }
1042 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1043 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1044
1045 if(enable)
1046 param_value = effect_config.param_value;
1047
1048 /*Special handling for AEC & NS effects Param values need to be
1049 updated if module ids are same*/
1050
1051 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1052 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1053 if (ret < 0)
1054 return ret;
1055 }
1056
1057 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1058
1059 return ret;
1060}
1061
1062static void check_and_enable_effect(struct audio_device *adev)
1063{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001064 if(!voice_extn_is_dynamic_ecns_enabled())
1065 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001066
Eric Laurent637e2d42018-11-15 12:24:31 -08001067 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068
Eric Laurent637e2d42018-11-15 12:24:31 -08001069 if (in != NULL && !in->standby) {
1070 if (in->enable_aec)
1071 enable_disable_effect(adev, EFFECT_AEC, true);
1072
1073 if (in->enable_ns &&
1074 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1075 enable_disable_effect(adev, EFFECT_NS, true);
1076 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001077 }
1078}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001079
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001080int pcm_ioctl(struct pcm *pcm, int request, ...)
1081{
1082 va_list ap;
1083 void * arg;
1084 int pcm_fd = *(int*)pcm;
1085
1086 va_start(ap, request);
1087 arg = va_arg(ap, void *);
1088 va_end(ap);
1089
1090 return ioctl(pcm_fd, request, arg);
1091}
1092
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001093int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001094 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001097 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301098 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301099 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301100 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001101
1102 if (usecase == NULL)
1103 return -EINVAL;
1104
1105 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1106
Carter Hsu2e429db2019-05-14 18:50:52 +08001107 if (usecase->type == PCM_CAPTURE) {
1108 struct stream_in *in = usecase->stream.in;
1109 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001111
1112 if (in) {
1113 if (in->enable_aec || in->enable_ec_port) {
1114 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1115 struct listnode *node;
1116 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1117 USECASE_AUDIO_PLAYBACK_VOIP);
1118 if (voip_usecase) {
1119 out_device = voip_usecase->stream.out->devices;
1120 } else if (adev->primary_output &&
1121 !adev->primary_output->standby) {
1122 out_device = adev->primary_output->devices;
1123 } else {
1124 list_for_each(node, &adev->usecase_list) {
1125 uinfo = node_to_item(node, struct audio_usecase, list);
1126 if (uinfo->type != PCM_CAPTURE) {
1127 out_device = uinfo->stream.out->devices;
1128 break;
1129 }
1130 }
1131 }
1132 platform_set_echo_reference(adev, true, out_device);
1133 in->ec_opened = true;
1134 }
1135 }
1136 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1137 snd_device = usecase->in_snd_device;
1138 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001140 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001141
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001142#ifdef DS1_DOLBY_DAP_ENABLED
1143 audio_extn_dolby_set_dmid(adev);
1144 audio_extn_dolby_set_endpoint(adev);
1145#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001146 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001147 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301148 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001149 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001150 if (audio_extn_is_maxx_audio_enabled())
1151 audio_extn_ma_set_device(usecase);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001152#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1153 if (usecase->id != USECASE_AUDIO_ULTRASOUND_TX)
1154#endif
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301155 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301156 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1157 out = usecase->stream.out;
1158 if (out && out->compr)
1159 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1160 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301161
1162 if (usecase->type == PCM_CAPTURE) {
1163 in = usecase->stream.in;
1164 if (in && is_loopback_input_device(in->device)) {
1165 ALOGD("%s: set custom mtmx params v1", __func__);
1166 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1167 }
1168 } else {
1169 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1170 }
Manish Dewangan58229382017-02-02 15:48:41 +05301171
Andy Hung756ecc12018-10-19 17:47:12 -07001172 // we shouldn't truncate mixer_path
1173 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1174 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1175 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001176 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001177 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301178 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1179 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1180 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1181 if (parms) {
1182 audio_extn_fm_set_parameters(adev, parms);
1183 str_parms_destroy(parms);
1184 }
1185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186 ALOGV("%s: exit", __func__);
1187 return 0;
1188}
1189
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001190int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001191 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001192{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001193 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001194 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301195 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001196
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301197 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001198 return -EINVAL;
1199
1200 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301201 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 snd_device = usecase->in_snd_device;
1203 else
1204 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001205 // we shouldn't truncate mixer_path
1206 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1207 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1208 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001209 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001210 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001211 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 if (usecase->type == PCM_CAPTURE) {
1213 struct stream_in *in = usecase->stream.in;
1214 if (in && in->ec_opened) {
1215 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1216 in->ec_opened = false;
1217 }
1218 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001219 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301220 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301221
1222 if (usecase->type == PCM_CAPTURE) {
1223 in = usecase->stream.in;
1224 if (in && is_loopback_input_device(in->device)) {
1225 ALOGD("%s: reset custom mtmx params v1", __func__);
1226 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1227 }
1228 } else {
1229 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1230 }
1231
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001232 if ((usecase->type == PCM_PLAYBACK) &&
1233 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301234 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001236 ALOGV("%s: exit", __func__);
1237 return 0;
1238}
1239
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001240int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001241 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301243 int i, num_devices = 0;
1244 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001245 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1246
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001247 if (snd_device < SND_DEVICE_MIN ||
1248 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001249 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001250 return -EINVAL;
1251 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001252
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001253 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001254 ALOGE("%s: Invalid sound device returned", __func__);
1255 return -EINVAL;
1256 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001257
1258 adev->snd_dev_ref_cnt[snd_device]++;
1259
1260 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1261 (platform_split_snd_device(adev->platform,
1262 snd_device,
1263 &num_devices,
1264 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001265 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001266 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001267 return 0;
1268 }
1269
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001270 if (audio_extn_spkr_prot_is_enabled())
1271 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001272
Aalique Grahame22e49102018-12-18 14:23:57 -08001273 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1274
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001275 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1276 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001277 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1278 goto err;
1279 }
1280 audio_extn_dev_arbi_acquire(snd_device);
1281 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001282 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001283 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001284 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001285 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001286 } else if (platform_split_snd_device(adev->platform,
1287 snd_device,
1288 &num_devices,
1289 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301290 for (i = 0; i < num_devices; i++) {
1291 enable_snd_device(adev, new_snd_devices[i]);
1292 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001293 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001294 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001295 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301296
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301297
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001298 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1299 (audio_extn_a2dp_start_playback() < 0)) {
1300 ALOGE(" fail to configure A2dp Source control path ");
1301 goto err;
1302 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001303
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001304 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1305 (audio_extn_a2dp_start_capture() < 0)) {
1306 ALOGE(" fail to configure A2dp Sink control path ");
1307 goto err;
1308 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301309
Zhou Song12c29502019-03-16 10:37:18 +08001310 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1311 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1312 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1313 (audio_extn_sco_start_configuration() < 0)) {
1314 ALOGE(" fail to configure sco control path ");
1315 goto err;
1316 }
1317
Zhou Song4721e282019-08-26 14:16:12 +08001318 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001319 /* due to the possibility of calibration overwrite between listen
1320 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001321 audio_extn_sound_trigger_update_device_status(snd_device,
1322 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301323 audio_extn_listen_update_device_status(snd_device,
1324 LISTEN_EVENT_SND_DEVICE_BUSY);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001325#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1326 if (snd_device != SND_DEVICE_OUT_ULTRASOUND_HANDSET &&
1327 snd_device != SND_DEVICE_IN_ULTRASOUND_MIC)
1328#endif
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001329 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001330 audio_extn_sound_trigger_update_device_status(snd_device,
1331 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301332 audio_extn_listen_update_device_status(snd_device,
1333 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001334 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001335 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001336 audio_extn_dev_arbi_acquire(snd_device);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05301337 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001338 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301339
1340 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1341 !adev->native_playback_enabled &&
1342 audio_is_true_native_stream_active(adev)) {
1343 ALOGD("%s: %d: napb: enabling native mode in hardware",
1344 __func__, __LINE__);
1345 audio_route_apply_and_update_path(adev->audio_route,
1346 "true-native-mode");
1347 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301348 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301349 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1350 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001351 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001352 ALOGD("%s: init ec ref loopback", __func__);
1353 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1354 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001355 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001357err:
1358 adev->snd_dev_ref_cnt[snd_device]--;
1359 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001360}
1361
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001362int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001363 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301365 int i, num_devices = 0;
1366 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001367 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1368
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001369 if (snd_device < SND_DEVICE_MIN ||
1370 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001371 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001372 return -EINVAL;
1373 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001374
1375 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1376 ALOGE("%s: Invalid sound device returned", __func__);
1377 return -EINVAL;
1378 }
1379
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001380 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1381 ALOGE("%s: device ref cnt is already 0", __func__);
1382 return -EINVAL;
1383 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001384
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001385 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001386
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001387
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001389 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301390
Aalique Grahame22e49102018-12-18 14:23:57 -08001391 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1392
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001393 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1394 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001395 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001396
1397 // when speaker device is disabled, reset swap.
1398 // will be renabled on usecase start
1399 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001400 } else if (platform_split_snd_device(adev->platform,
1401 snd_device,
1402 &num_devices,
1403 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301404 for (i = 0; i < num_devices; i++) {
1405 disable_snd_device(adev, new_snd_devices[i]);
1406 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001407 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001408 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001409 audio_route_reset_and_update_path(adev->audio_route, device_name);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05301410 amplifier_enable_devices(snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001411 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001412
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001413 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301414 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001415 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001416 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001417 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001418 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301419 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001420 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421 adev->native_playback_enabled) {
1422 ALOGD("%s: %d: napb: disabling native mode in hardware",
1423 __func__, __LINE__);
1424 audio_route_reset_and_update_path(adev->audio_route,
1425 "true-native-mode");
1426 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001427 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301428 adev->asrc_mode_enabled) {
1429 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301430 disable_asrc_mode(adev);
1431 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001432 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301433 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001434 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001435 ALOGD("%s: deinit ec ref loopback", __func__);
1436 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1437 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001438
1439 audio_extn_utils_release_snd_device(snd_device);
1440 } else {
1441 if (platform_split_snd_device(adev->platform,
1442 snd_device,
1443 &num_devices,
1444 new_snd_devices) == 0) {
1445 for (i = 0; i < num_devices; i++) {
1446 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1447 }
1448 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 return 0;
1452}
1453
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001454/*
1455 legend:
1456 uc - existing usecase
1457 new_uc - new usecase
1458 d1, d11, d2 - SND_DEVICE enums
1459 a1, a2 - corresponding ANDROID device enums
1460 B1, B2 - backend strings
1461
1462case 1
1463 uc->dev d1 (a1) B1
1464 new_uc->dev d1 (a1), d2 (a2) B1, B2
1465
1466 resolution: disable and enable uc->dev on d1
1467
1468case 2
1469 uc->dev d1 (a1) B1
1470 new_uc->dev d11 (a1) B1
1471
1472 resolution: need to switch uc since d1 and d11 are related
1473 (e.g. speaker and voice-speaker)
1474 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1475
1476case 3
1477 uc->dev d1 (a1) B1
1478 new_uc->dev d2 (a2) B2
1479
1480 resolution: no need to switch uc
1481
1482case 4
1483 uc->dev d1 (a1) B1
1484 new_uc->dev d2 (a2) B1
1485
1486 resolution: disable enable uc-dev on d2 since backends match
1487 we cannot enable two streams on two different devices if they
1488 share the same backend. e.g. if offload is on speaker device using
1489 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1490 using the same backend, offload must also be switched to voice-handset.
1491
1492case 5
1493 uc->dev d1 (a1) B1
1494 new_uc->dev d1 (a1), d2 (a2) B1
1495
1496 resolution: disable enable uc-dev on d2 since backends match
1497 we cannot enable two streams on two different devices if they
1498 share the same backend.
1499
1500case 6
1501 uc->dev d1 (a1) B1
1502 new_uc->dev d2 (a1) B2
1503
1504 resolution: no need to switch
1505
1506case 7
1507 uc->dev d1 (a1), d2 (a2) B1, B2
1508 new_uc->dev d1 (a1) B1
1509
1510 resolution: no need to switch
1511
Zhou Song4ba65882018-07-09 14:48:07 +08001512case 8
1513 uc->dev d1 (a1) B1
1514 new_uc->dev d11 (a1), d2 (a2) B1, B2
1515 resolution: compared to case 1, for this case, d1 and d11 are related
1516 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001517*/
1518static snd_device_t derive_playback_snd_device(void * platform,
1519 struct audio_usecase *uc,
1520 struct audio_usecase *new_uc,
1521 snd_device_t new_snd_device)
1522{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301523 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001524
1525 snd_device_t d1 = uc->out_snd_device;
1526 snd_device_t d2 = new_snd_device;
1527
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301528 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301529 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301530 a1 = uc->stream.inout->out_config.devices;
1531 a2 = new_uc->stream.inout->out_config.devices;
1532 break;
1533 default :
1534 a1 = uc->stream.out->devices;
1535 a2 = new_uc->stream.out->devices;
1536 break;
1537 }
1538
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001539 // Treat as a special case when a1 and a2 are not disjoint
1540 if ((a1 != a2) && (a1 & a2)) {
1541 snd_device_t d3[2];
1542 int num_devices = 0;
1543 int ret = platform_split_snd_device(platform,
1544 popcount(a1) > 1 ? d1 : d2,
1545 &num_devices,
1546 d3);
1547 if (ret < 0) {
1548 if (ret != -ENOSYS) {
1549 ALOGW("%s failed to split snd_device %d",
1550 __func__,
1551 popcount(a1) > 1 ? d1 : d2);
1552 }
1553 goto end;
1554 }
1555
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001556 if (platform_check_backends_match(d3[0], d3[1])) {
1557 return d2; // case 5
1558 } else {
Samyak Jaind826b502019-07-17 16:16:42 +05301559 if (popcount(a1) > 1)
1560 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001561 // check if d1 is related to any of d3's
1562 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001563 return d1; // case 1
1564 else
1565 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001566 }
1567 } else {
1568 if (platform_check_backends_match(d1, d2)) {
1569 return d2; // case 2, 4
1570 } else {
1571 return d1; // case 6, 3
1572 }
1573 }
1574
1575end:
1576 return d2; // return whatever was calculated before.
1577}
1578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301580 struct audio_usecase *uc_info,
1581 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582{
1583 struct listnode *node;
1584 struct audio_usecase *usecase;
1585 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301586 snd_device_t uc_derive_snd_device;
1587 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001588 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1589 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001590 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301591 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 /*
1593 * This function is to make sure that all the usecases that are active on
1594 * the hardware codec backend are always routed to any one device that is
1595 * handled by the hardware codec.
1596 * For example, if low-latency and deep-buffer usecases are currently active
1597 * on speaker and out_set_parameters(headset) is received on low-latency
1598 * output, then we have to make sure deep-buffer is also switched to headset,
1599 * because of the limitation that both the devices cannot be enabled
1600 * at the same time as they share the same backend.
1601 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001602 /*
1603 * This call is to check if we need to force routing for a particular stream
1604 * If there is a backend configuration change for the device when a
1605 * new stream starts, then ADM needs to be closed and re-opened with the new
1606 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001607 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001608 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001609 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1610 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301611 /* For a2dp device reconfigure all active sessions
1612 * with new AFE encoder format based on a2dp state
1613 */
1614 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1615 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1616 audio_extn_a2dp_is_force_device_switch()) {
1617 force_routing = true;
1618 force_restart_session = true;
1619 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301620 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001623 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001624 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1626 switch_device[i] = false;
1627
1628 list_for_each(node, &adev->usecase_list) {
1629 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001630
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301631 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1632 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301633 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301634 platform_get_snd_device_name(usecase->out_snd_device),
1635 platform_check_backends_match(snd_device, usecase->out_snd_device));
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001636
1637#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1638 if (usecase->id == USECASE_AUDIO_ULTRASOUND_RX)
1639 continue;
1640#endif
1641
Rahul Sharma99770982019-03-06 17:05:26 +05301642 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1643 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301644 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1645 usecase, uc_info, snd_device);
1646 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1647 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1648 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1649 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001650 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301651 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1652 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1653 ((force_restart_session) ||
1654 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301655 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1656 __func__, use_case_table[usecase->id],
1657 platform_get_snd_device_name(usecase->out_snd_device));
1658 disable_audio_route(adev, usecase);
1659 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301660 /* Enable existing usecase on derived playback device */
1661 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301662 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664 }
1665 }
1666
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301667 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1668 num_uc_to_switch);
1669
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001671 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001672
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301673 /* Make sure the previous devices to be disabled first and then enable the
1674 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 list_for_each(node, &adev->usecase_list) {
1676 usecase = node_to_item(node, struct audio_usecase, list);
1677 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001678 /* Check if output sound device to be switched can be split and if any
1679 of the split devices match with derived sound device */
1680 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1681 &num_devices, split_snd_devices) == 0) {
1682 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1683 for (i = 0; i < num_devices; i++) {
1684 /* Disable devices that do not match with derived sound device */
1685 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1686 disable_snd_device(adev, split_snd_devices[i]);
1687 }
1688 } else {
1689 disable_snd_device(adev, usecase->out_snd_device);
1690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001691 }
1692 }
1693
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001694 list_for_each(node, &adev->usecase_list) {
1695 usecase = node_to_item(node, struct audio_usecase, list);
1696 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001697 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1698 &num_devices, split_snd_devices) == 0) {
1699 /* Enable derived sound device only if it does not match with
1700 one of the split sound devices. This is because the matching
1701 sound device was not disabled */
1702 bool should_enable = true;
1703 for (i = 0; i < num_devices; i++) {
1704 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1705 should_enable = false;
1706 break;
1707 }
1708 }
1709 if (should_enable)
1710 enable_snd_device(adev, derive_snd_device[usecase->id]);
1711 } else {
1712 enable_snd_device(adev, derive_snd_device[usecase->id]);
1713 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001714 }
1715 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001716
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001717 /* Re-route all the usecases on the shared backend other than the
1718 specified usecase to new snd devices */
1719 list_for_each(node, &adev->usecase_list) {
1720 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301721 /* Update the out_snd_device only before enabling the audio route */
1722 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301723 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301724 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301725 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301726 use_case_table[usecase->id],
1727 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001728 /* Update voc calibration before enabling VoIP route */
1729 if (usecase->type == VOIP_CALL)
1730 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001731 usecase->out_snd_device,
1732 platform_get_input_snd_device(
1733 adev->platform, NULL,
1734 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301735 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301736 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001737 out_set_voip_volume(&usecase->stream.out->stream,
1738 usecase->stream.out->volume_l,
1739 usecase->stream.out->volume_r);
1740 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001742 }
1743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001744 }
1745}
1746
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301747static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001748 struct audio_usecase *uc_info,
1749 snd_device_t snd_device)
1750{
1751 struct listnode *node;
1752 struct audio_usecase *usecase;
1753 bool switch_device[AUDIO_USECASE_MAX];
1754 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301755 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001756 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001757
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301758 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1759 snd_device);
1760 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301761
1762 /*
1763 * Make sure out devices is checked against out codec backend device and
1764 * also in devices against in codec backend. Checking out device against in
1765 * codec backend or vice versa causes issues.
1766 */
1767 if (uc_info->type == PCM_CAPTURE)
1768 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001769 /*
1770 * This function is to make sure that all the active capture usecases
1771 * are always routed to the same input sound device.
1772 * For example, if audio-record and voice-call usecases are currently
1773 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1774 * is received for voice call then we have to make sure that audio-record
1775 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1776 * because of the limitation that two devices cannot be enabled
1777 * at the same time if they share the same backend.
1778 */
1779 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1780 switch_device[i] = false;
1781
1782 list_for_each(node, &adev->usecase_list) {
1783 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301784 /*
1785 * TODO: Enhance below condition to handle BT sco/USB multi recording
1786 */
Balázs Triszkaa68afd52017-05-11 03:19:29 +02001787
1788#ifdef ELLIPTIC_ULTRASOUND_ENABLED
1789 if (usecase->id == USECASE_AUDIO_ULTRASOUND_TX)
1790 continue;
1791#endif
1792
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001793 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001794 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301795 (usecase->in_snd_device != snd_device || force_routing) &&
juyuchen34574a02019-08-20 18:36:01 +08001796 (((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301797 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
juyuchen34574a02019-08-20 18:36:01 +08001798 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001799 ((uc_info->type == VOICE_CALL &&
1800 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1801 platform_check_backends_match(snd_device,\
juyuchen34574a02019-08-20 18:36:01 +08001802 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001803 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001804 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1805 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001806 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001807 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001808 switch_device[usecase->id] = true;
1809 num_uc_to_switch++;
1810 }
1811 }
1812
1813 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001814 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001815
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301816 /* Make sure the previous devices to be disabled first and then enable the
1817 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001818 list_for_each(node, &adev->usecase_list) {
1819 usecase = node_to_item(node, struct audio_usecase, list);
1820 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001821 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001822 }
1823 }
1824
1825 list_for_each(node, &adev->usecase_list) {
1826 usecase = node_to_item(node, struct audio_usecase, list);
1827 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001828 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001829 }
1830 }
1831
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001832 /* Re-route all the usecases on the shared backend other than the
1833 specified usecase to new snd devices */
1834 list_for_each(node, &adev->usecase_list) {
1835 usecase = node_to_item(node, struct audio_usecase, list);
1836 /* Update the in_snd_device only before enabling the audio route */
1837 if (switch_device[usecase->id] ) {
1838 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001839 if (usecase->type != VOICE_CALL) {
1840 /* Update voc calibration before enabling VoIP route */
1841 if (usecase->type == VOIP_CALL)
1842 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001843 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001844 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301845 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001846 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001847 }
1848 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001849 }
1850}
1851
Mingming Yin3a941d42016-02-17 18:08:05 -08001852static void reset_hdmi_sink_caps(struct stream_out *out) {
1853 int i = 0;
1854
1855 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1856 out->supported_channel_masks[i] = 0;
1857 }
1858 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1859 out->supported_formats[i] = 0;
1860 }
1861 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1862 out->supported_sample_rates[i] = 0;
1863 }
1864}
1865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001867static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868{
Mingming Yin3a941d42016-02-17 18:08:05 -08001869 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001870 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871
Mingming Yin3a941d42016-02-17 18:08:05 -08001872 reset_hdmi_sink_caps(out);
1873
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001874 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001875 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001876 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001877 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001878 }
1879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001882 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001883 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001884 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1885 case 6:
1886 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1887 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1888 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1889 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1890 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1891 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 break;
1893 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001894 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001895 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 break;
1897 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001898
1899 // check channel format caps
1900 i = 0;
1901 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1902 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1903 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1904 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1905 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1906 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1907 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1908 }
1909
Ben Romberger1aaaf862017-04-06 17:49:46 -07001910 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1911 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1912 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1913 }
1914
Mingming Yin3a941d42016-02-17 18:08:05 -08001915 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1916 ALOGV(":%s HDMI supports DTS format", __func__);
1917 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1918 }
1919
1920 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1921 ALOGV(":%s HDMI supports DTS HD format", __func__);
1922 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1923 }
1924
Naresh Tanniru928f0862017-04-07 16:44:23 -07001925 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1926 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1927 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1928 }
1929
Mingming Yin3a941d42016-02-17 18:08:05 -08001930
1931 // check sample rate caps
1932 i = 0;
1933 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1934 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1935 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1936 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1937 }
1938 }
1939
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001940 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941}
1942
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001943static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1944 uint32_t *supported_sample_rates __unused,
1945 uint32_t max_rates __unused)
1946{
1947 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1948 supported_sample_rates,
1949 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301950 ssize_t i = 0;
1951
1952 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001953 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1954 supported_sample_rates[i]);
1955 }
1956 return count;
1957}
1958
1959static inline int read_usb_sup_channel_masks(bool is_playback,
1960 audio_channel_mask_t *supported_channel_masks,
1961 uint32_t max_masks)
1962{
1963 int channels = audio_extn_usb_get_max_channels(is_playback);
1964 int channel_count;
1965 uint32_t num_masks = 0;
1966 if (channels > MAX_HIFI_CHANNEL_COUNT)
1967 channels = MAX_HIFI_CHANNEL_COUNT;
1968
1969 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001970 // start from 2 channels as framework currently doesn't support mono.
1971 if (channels >= FCC_2) {
1972 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1973 }
1974 for (channel_count = FCC_2;
1975 channel_count <= channels && num_masks < max_masks;
1976 ++channel_count) {
1977 supported_channel_masks[num_masks++] =
1978 audio_channel_mask_for_index_assignment_from_count(channel_count);
1979 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001980 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001981 // For capture we report all supported channel masks from 1 channel up.
1982 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001983 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1984 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001985 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1986 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1987 if (channel_count <= FCC_2) {
1988 mask = audio_channel_in_mask_from_count(channel_count);
1989 supported_channel_masks[num_masks++] = mask;
1990 }
1991 const audio_channel_mask_t index_mask =
1992 audio_channel_mask_for_index_assignment_from_count(channel_count);
1993 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1994 supported_channel_masks[num_masks++] = index_mask;
1995 }
1996 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001997 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301998
vincenttewf51c94e2019-05-07 10:28:53 +08001999 for (size_t i = 0; i < num_masks; ++i) {
2000 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2001 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302002 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002003 return num_masks;
2004}
2005
2006static inline int read_usb_sup_formats(bool is_playback __unused,
2007 audio_format_t *supported_formats,
2008 uint32_t max_formats __unused)
2009{
2010 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2011 switch (bitwidth) {
2012 case 24:
2013 // XXX : usb.c returns 24 for s24 and s24_le?
2014 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2015 break;
2016 case 32:
2017 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2018 break;
2019 case 16:
2020 default :
2021 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2022 break;
2023 }
2024 ALOGV("%s: %s supported format %d", __func__,
2025 is_playback ? "P" : "C", bitwidth);
2026 return 1;
2027}
2028
2029static inline int read_usb_sup_params_and_compare(bool is_playback,
2030 audio_format_t *format,
2031 audio_format_t *supported_formats,
2032 uint32_t max_formats,
2033 audio_channel_mask_t *mask,
2034 audio_channel_mask_t *supported_channel_masks,
2035 uint32_t max_masks,
2036 uint32_t *rate,
2037 uint32_t *supported_sample_rates,
2038 uint32_t max_rates) {
2039 int ret = 0;
2040 int num_formats;
2041 int num_masks;
2042 int num_rates;
2043 int i;
2044
2045 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2046 max_formats);
2047 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2048 max_masks);
2049
2050 num_rates = read_usb_sup_sample_rates(is_playback,
2051 supported_sample_rates, max_rates);
2052
2053#define LUT(table, len, what, dflt) \
2054 for (i=0; i<len && (table[i] != what); i++); \
2055 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2056
2057 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2058 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2059 LUT(supported_sample_rates, num_rates, *rate, 0);
2060
2061#undef LUT
2062 return ret < 0 ? -EINVAL : 0; // HACK TBD
2063}
2064
Alexy Josephb1379942016-01-29 15:49:38 -08002065audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002066 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002067{
2068 struct audio_usecase *usecase;
2069 struct listnode *node;
2070
2071 list_for_each(node, &adev->usecase_list) {
2072 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002073 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002074 ALOGV("%s: usecase id %d", __func__, usecase->id);
2075 return usecase->id;
2076 }
2077 }
2078 return USECASE_INVALID;
2079}
2080
Alexy Josephb1379942016-01-29 15:49:38 -08002081struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002082 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083{
2084 struct audio_usecase *usecase;
2085 struct listnode *node;
2086
2087 list_for_each(node, &adev->usecase_list) {
2088 usecase = node_to_item(node, struct audio_usecase, list);
2089 if (usecase->id == uc_id)
2090 return usecase;
2091 }
2092 return NULL;
2093}
2094
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302095/*
2096 * is a true native playback active
2097 */
2098bool audio_is_true_native_stream_active(struct audio_device *adev)
2099{
2100 bool active = false;
2101 int i = 0;
2102 struct listnode *node;
2103
2104 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2105 ALOGV("%s:napb: not in true mode or non hdphones device",
2106 __func__);
2107 active = false;
2108 goto exit;
2109 }
2110
2111 list_for_each(node, &adev->usecase_list) {
2112 struct audio_usecase *uc;
2113 uc = node_to_item(node, struct audio_usecase, list);
2114 struct stream_out *curr_out =
2115 (struct stream_out*) uc->stream.out;
2116
2117 if (curr_out && PCM_PLAYBACK == uc->type) {
2118 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2119 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2120 uc->id, curr_out->sample_rate,
2121 curr_out->bit_width,
2122 platform_get_snd_device_name(uc->out_snd_device));
2123
2124 if (is_offload_usecase(uc->id) &&
2125 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2126 active = true;
2127 ALOGD("%s:napb:native stream detected", __func__);
2128 }
2129 }
2130 }
2131exit:
2132 return active;
2133}
2134
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002135uint32_t adev_get_dsp_bit_width_enforce_mode()
2136{
2137 if (adev == NULL) {
2138 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2139 return 0;
2140 }
2141 return adev->dsp_bit_width_enforce_mode;
2142}
2143
2144static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2145{
2146 char value[PROPERTY_VALUE_MAX];
2147 int trial;
2148 uint32_t dsp_bit_width_enforce_mode = 0;
2149
2150 if (!mixer) {
2151 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2152 __func__);
2153 return 0;
2154 }
2155
2156 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2157 value, NULL) > 0) {
2158 trial = atoi(value);
2159 switch (trial) {
2160 case 16:
2161 dsp_bit_width_enforce_mode = 16;
2162 break;
2163 case 24:
2164 dsp_bit_width_enforce_mode = 24;
2165 break;
2166 case 32:
2167 dsp_bit_width_enforce_mode = 32;
2168 break;
2169 default:
2170 dsp_bit_width_enforce_mode = 0;
2171 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2172 break;
2173 }
2174 }
2175
2176 return dsp_bit_width_enforce_mode;
2177}
2178
2179static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2180 uint32_t enforce_mode,
2181 bool enable)
2182{
2183 struct mixer_ctl *ctl = NULL;
2184 const char *mixer_ctl_name = "ASM Bit Width";
2185 uint32_t asm_bit_width_mode = 0;
2186
2187 if (enforce_mode == 0) {
2188 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2189 return;
2190 }
2191
2192 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2193 if (!ctl) {
2194 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2195 __func__, mixer_ctl_name);
2196 return;
2197 }
2198
2199 if (enable)
2200 asm_bit_width_mode = enforce_mode;
2201 else
2202 asm_bit_width_mode = 0;
2203
2204 ALOGV("%s DSP bit width feature status is %d width=%d",
2205 __func__, enable, asm_bit_width_mode);
2206 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2207 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2208 asm_bit_width_mode);
2209
2210 return;
2211}
2212
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302213/*
2214 * if native DSD playback active
2215 */
2216bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2217{
2218 bool active = false;
2219 struct listnode *node = NULL;
2220 struct audio_usecase *uc = NULL;
2221 struct stream_out *curr_out = NULL;
2222
2223 list_for_each(node, &adev->usecase_list) {
2224 uc = node_to_item(node, struct audio_usecase, list);
2225 curr_out = (struct stream_out*) uc->stream.out;
2226
2227 if (curr_out && PCM_PLAYBACK == uc->type &&
2228 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2229 active = true;
2230 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302231 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302232 }
2233 }
2234 return active;
2235}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302236
2237static bool force_device_switch(struct audio_usecase *usecase)
2238{
2239 bool ret = false;
2240 bool is_it_true_mode = false;
2241
Zhou Song30f2c3e2018-02-08 14:02:15 +08002242 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302243 usecase->type == TRANSCODE_LOOPBACK_RX ||
2244 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002245 return false;
2246 }
2247
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002248 if(usecase->stream.out == NULL) {
2249 ALOGE("%s: stream.out is NULL", __func__);
2250 return false;
2251 }
2252
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302253 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002254 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2255 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2256 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302257 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2258 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2259 (!is_it_true_mode && adev->native_playback_enabled)){
2260 ret = true;
2261 ALOGD("napb: time to toggle native mode");
2262 }
2263 }
2264
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302265 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302266 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2267 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002268 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302269 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302270 ALOGD("Force a2dp device switch to update new encoder config");
2271 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002272 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302273
Florian Pfister1a84f312018-07-19 14:38:18 +02002274 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302275 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2276 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002277 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302278 return ret;
2279}
2280
Aalique Grahame22e49102018-12-18 14:23:57 -08002281static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2282{
2283 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2284}
2285
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302286bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2287{
2288 bool ret=false;
2289 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2290 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2291 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2292 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2293 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2294 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2295 ret = true;
2296
2297 return ret;
2298}
2299
2300bool is_a2dp_device(snd_device_t out_snd_device)
2301{
2302 bool ret=false;
2303 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2304 ret = true;
2305
2306 return ret;
2307}
2308
2309bool is_bt_soc_on(struct audio_device *adev)
2310{
2311 struct mixer_ctl *ctl;
2312 char *mixer_ctl_name = "BT SOC status";
2313 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2314 bool bt_soc_status = true;
2315 if (!ctl) {
2316 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2317 __func__, mixer_ctl_name);
2318 /*This is to ensure we dont break targets which dont have the kernel change*/
2319 return true;
2320 }
2321 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2322 ALOGD("BT SOC status: %d",bt_soc_status);
2323 return bt_soc_status;
2324}
2325
Zhou Song4721e282019-08-26 14:16:12 +08002326static int configure_btsco_sample_rate(snd_device_t snd_device)
2327{
2328 struct mixer_ctl *ctl = NULL;
2329 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2330 char *rate_str = NULL;
2331 bool is_rx_dev = true;
2332
2333 if (is_btsco_device(snd_device, snd_device)) {
2334 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2335 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2336 if (!ctl_sr_tx || !ctl_sr_rx) {
2337 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2338 if (!ctl_sr)
2339 return -ENOSYS;
2340 }
2341
2342 switch (snd_device) {
2343 case SND_DEVICE_OUT_BT_SCO:
2344 rate_str = "KHZ_8";
2345 break;
2346 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2347 case SND_DEVICE_IN_BT_SCO_MIC:
2348 rate_str = "KHZ_8";
2349 is_rx_dev = false;
2350 break;
2351 case SND_DEVICE_OUT_BT_SCO_WB:
2352 rate_str = "KHZ_16";
2353 break;
2354 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2355 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2356 rate_str = "KHZ_16";
2357 is_rx_dev = false;
2358 break;
2359 default:
2360 return 0;
2361 }
2362
2363 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2364 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2365 return -ENOSYS;
2366 }
2367 return 0;
2368}
2369
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302370int out_standby_l(struct audio_stream *stream);
2371
Eric Laurent637e2d42018-11-15 12:24:31 -08002372struct stream_in *adev_get_active_input(const struct audio_device *adev)
2373{
2374 struct listnode *node;
2375 struct stream_in *last_active_in = NULL;
2376
2377 /* Get last added active input.
2378 * TODO: We may use a priority mechanism to pick highest priority active source */
2379 list_for_each(node, &adev->usecase_list)
2380 {
2381 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2382 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2383 last_active_in = usecase->stream.in;
2384 }
2385
2386 return last_active_in;
2387}
2388
2389struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2390{
2391 struct listnode *node;
2392
2393 /* First check active inputs with voice communication source and then
2394 * any input if audio mode is in communication */
2395 list_for_each(node, &adev->usecase_list)
2396 {
2397 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2398 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2399 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2400 return usecase->stream.in;
2401 }
2402 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2403 return adev_get_active_input(adev);
2404
2405 return NULL;
2406}
2407
Carter Hsu2e429db2019-05-14 18:50:52 +08002408/*
2409 * Aligned with policy.h
2410 */
2411static inline int source_priority(int inputSource)
2412{
2413 switch (inputSource) {
2414 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2415 return 9;
2416 case AUDIO_SOURCE_CAMCORDER:
2417 return 8;
2418 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2419 return 7;
2420 case AUDIO_SOURCE_UNPROCESSED:
2421 return 6;
2422 case AUDIO_SOURCE_MIC:
2423 return 5;
2424 case AUDIO_SOURCE_ECHO_REFERENCE:
2425 return 4;
2426 case AUDIO_SOURCE_FM_TUNER:
2427 return 3;
2428 case AUDIO_SOURCE_VOICE_RECOGNITION:
2429 return 2;
2430 case AUDIO_SOURCE_HOTWORD:
2431 return 1;
2432 default:
2433 break;
2434 }
2435 return 0;
2436}
2437
2438static struct stream_in *get_priority_input(struct audio_device *adev)
2439{
2440 struct listnode *node;
2441 struct audio_usecase *usecase;
2442 int last_priority = 0, priority;
2443 struct stream_in *priority_in = NULL;
2444 struct stream_in *in;
2445
2446 list_for_each(node, &adev->usecase_list) {
2447 usecase = node_to_item(node, struct audio_usecase, list);
2448 if (usecase->type == PCM_CAPTURE) {
2449 in = usecase->stream.in;
2450 if (!in)
2451 continue;
2452 priority = source_priority(in->source);
2453
2454 if (priority > last_priority) {
2455 last_priority = priority;
2456 priority_in = in;
2457 }
2458 }
2459 }
2460 return priority_in;
2461}
2462
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002463int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002465 snd_device_t out_snd_device = SND_DEVICE_NONE;
2466 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002467 struct audio_usecase *usecase = NULL;
2468 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002469 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002470 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302471 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002472 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002473 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302475 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2476
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002477 usecase = get_usecase_from_list(adev, uc_id);
2478 if (usecase == NULL) {
2479 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2480 return -EINVAL;
2481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002483 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002484 (usecase->type == VOIP_CALL) ||
2485 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302486 if(usecase->stream.out == NULL) {
2487 ALOGE("%s: stream.out is NULL", __func__);
2488 return -EINVAL;
2489 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002490 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002491 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002492 in_snd_device = platform_get_input_snd_device(adev->platform,
2493 NULL,
2494 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302496 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302497 if (usecase->stream.inout == NULL) {
2498 ALOGE("%s: stream.inout is NULL", __func__);
2499 return -EINVAL;
2500 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302501 stream_out.devices = usecase->stream.inout->out_config.devices;
2502 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2503 stream_out.format = usecase->stream.inout->out_config.format;
2504 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2505 out_snd_device = platform_get_output_snd_device(adev->platform,
2506 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302507 usecase->devices = out_snd_device;
2508 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2509 if (usecase->stream.inout == NULL) {
2510 ALOGE("%s: stream.inout is NULL", __func__);
2511 return -EINVAL;
2512 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002513 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302514 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002515 } else {
2516 /*
2517 * If the voice call is active, use the sound devices of voice call usecase
2518 * so that it would not result any device switch. All the usecases will
2519 * be switched to new device when select_devices() is called for voice call
2520 * usecase. This is to avoid switching devices for voice call when
2521 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002522 * choose voice call device only if the use case device is
2523 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002524 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002525 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002526 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002527 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002528 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2529 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302530 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2531 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002532 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2533 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002534 in_snd_device = vc_usecase->in_snd_device;
2535 out_snd_device = vc_usecase->out_snd_device;
2536 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002537 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002538 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002539 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002540 if ((voip_usecase != NULL) &&
2541 (usecase->type == PCM_PLAYBACK) &&
2542 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002543 out_snd_device_backend_match = platform_check_backends_match(
2544 voip_usecase->out_snd_device,
2545 platform_get_output_snd_device(
2546 adev->platform,
2547 usecase->stream.out));
2548 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002549 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002550 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2551 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002552 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002553 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002554 in_snd_device = voip_usecase->in_snd_device;
2555 out_snd_device = voip_usecase->out_snd_device;
2556 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002557 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002558 hfp_ucid = audio_extn_hfp_get_usecase();
2559 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002560 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002561 in_snd_device = hfp_usecase->in_snd_device;
2562 out_snd_device = hfp_usecase->out_snd_device;
2563 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002564 }
2565 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302566 if (usecase->stream.out == NULL) {
2567 ALOGE("%s: stream.out is NULL", __func__);
2568 return -EINVAL;
2569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002570 usecase->devices = usecase->stream.out->devices;
2571 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002572 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002573 struct stream_out *voip_out = adev->primary_output;
2574 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002575 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002576 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002577 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002578
Eric Laurent637e2d42018-11-15 12:24:31 -08002579 if (voip_usecase)
2580 voip_out = voip_usecase->stream.out;
2581
2582 if (usecase->stream.out == voip_out && voip_in != NULL)
2583 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002584 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302586 if (usecase->stream.in == NULL) {
2587 ALOGE("%s: stream.in is NULL", __func__);
2588 return -EINVAL;
2589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002590 usecase->devices = usecase->stream.in->device;
2591 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002592 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002593 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002594 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002595 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002596
2597 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002598 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2599 USECASE_AUDIO_PLAYBACK_VOIP);
2600
Carter Hsu2e429db2019-05-14 18:50:52 +08002601 usecase->stream.in->enable_ec_port = false;
2602
Eric Laurent637e2d42018-11-15 12:24:31 -08002603 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2604 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2605 } else if (voip_usecase) {
2606 out_device = voip_usecase->stream.out->devices;
2607 } else if (adev->primary_output &&
2608 !adev->primary_output->standby) {
2609 out_device = adev->primary_output->devices;
2610 } else {
2611 /* forcing speaker o/p device to get matching i/p pair
2612 in case o/p is not routed from same primary HAL */
2613 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2614 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002615 priority_in = voip_in;
2616 } else {
2617 /* get the input with the highest priority source*/
2618 priority_in = get_priority_input(adev);
2619
2620 if (!priority_in)
2621 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002622 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002623
Eric Laurent637e2d42018-11-15 12:24:31 -08002624 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002625 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002626 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002627 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002628 }
2629 }
2630
2631 if (out_snd_device == usecase->out_snd_device &&
2632 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302633
2634 if (!force_device_switch(usecase))
2635 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 }
2637
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302638 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002639 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302640 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2641 return 0;
2642 }
2643
Aalique Grahame22e49102018-12-18 14:23:57 -08002644 if (out_snd_device != SND_DEVICE_NONE &&
2645 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2646 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2647 __func__,
2648 use_case_table[uc_id],
2649 adev->last_logged_snd_device[uc_id][0],
2650 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2651 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2652 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2653 -1,
2654 out_snd_device,
2655 platform_get_snd_device_name(out_snd_device),
2656 platform_get_snd_device_acdb_id(out_snd_device));
2657 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2658 }
2659 if (in_snd_device != SND_DEVICE_NONE &&
2660 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2661 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2662 __func__,
2663 use_case_table[uc_id],
2664 adev->last_logged_snd_device[uc_id][1],
2665 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2666 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2667 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2668 -1,
2669 in_snd_device,
2670 platform_get_snd_device_name(in_snd_device),
2671 platform_get_snd_device_acdb_id(in_snd_device));
2672 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2673 }
2674
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 /*
2677 * Limitation: While in call, to do a device switch we need to disable
2678 * and enable both RX and TX devices though one of them is same as current
2679 * device.
2680 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002681 if ((usecase->type == VOICE_CALL) &&
2682 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2683 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002684 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002685 }
2686
2687 if (((usecase->type == VOICE_CALL) ||
2688 (usecase->type == VOIP_CALL)) &&
2689 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2690 /* Disable sidetone only if voice/voip call already exists */
2691 if (voice_is_call_state_active(adev) ||
2692 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002693 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002694
2695 /* Disable aanc only if voice call exists */
2696 if (voice_is_call_state_active(adev))
2697 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002698 }
2699
Aalique Grahame22e49102018-12-18 14:23:57 -08002700 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2701 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002702 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302703 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002704 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2705 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2706 else
2707 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302708 }
2709
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002710 /* Disable current sound devices */
2711 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002712 disable_audio_route(adev, usecase);
2713 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714 }
2715
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002716 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002717 disable_audio_route(adev, usecase);
2718 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 }
2720
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002721 /* Applicable only on the targets that has external modem.
2722 * New device information should be sent to modem before enabling
2723 * the devices to reduce in-call device switch time.
2724 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002725 if ((usecase->type == VOICE_CALL) &&
2726 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2727 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002728 status = platform_switch_voice_call_enable_device_config(adev->platform,
2729 out_snd_device,
2730 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002731 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002732
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 /* Enable new sound devices */
2734 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002735 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302736 if (platform_check_codec_asrc_support(adev->platform))
2737 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002738 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 }
2740
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002741 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302742 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002743 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002745
Avinash Vaish71a8b972014-07-24 15:36:33 +05302746 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002747 status = platform_switch_voice_call_device_post(adev->platform,
2748 out_snd_device,
2749 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302750 enable_audio_route_for_voice_usecases(adev, usecase);
2751 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002752
sangwoo170731f2013-06-08 15:36:36 +09002753 usecase->in_snd_device = in_snd_device;
2754 usecase->out_snd_device = out_snd_device;
2755
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302756 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2757 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302758 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002759 if ((24 == usecase->stream.out->bit_width) &&
2760 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2761 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2762 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2763 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2764 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2765 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2766 /*
2767 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2768 * configured device sample rate, if not update the COPP rate to be equal to the
2769 * device sample rate, else open COPP at stream sample rate
2770 */
2771 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2772 usecase->stream.out->sample_rate,
2773 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302774 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawate3af5102019-09-30 14:39:47 +05302775 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2776 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302777 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002778 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2779 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2780 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2781 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002782 }
2783 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002784
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002785 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002786
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002787 /* If input stream is already running then effect needs to be
2788 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002789 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002790 check_and_enable_effect(adev);
2791
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002792 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002793 /* Enable aanc only if voice call exists */
2794 if (voice_is_call_state_active(adev))
2795 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2796
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002797 /* Enable sidetone only if other voice/voip call already exists */
2798 if (voice_is_call_state_active(adev) ||
2799 voice_extn_compress_voip_is_started(adev))
2800 voice_set_sidetone(adev, out_snd_device, true);
2801 }
2802
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05302803 /* Rely on amplifier_set_devices to distinguish between in/out devices */
2804 amplifier_set_input_devices(in_snd_device);
2805 amplifier_set_output_devices(out_snd_device);
2806
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002807 /* Applicable only on the targets that has external modem.
2808 * Enable device command should be sent to modem only after
2809 * enabling voice call mixer controls
2810 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002811 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002812 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2813 out_snd_device,
2814 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302815
2816 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002817 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302818 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002819 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302820 if (is_bt_soc_on(adev) == false){
2821 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002822 if (in->pcm != NULL)
2823 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302824 }
2825 }
2826 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2827 && usecase->stream.out->started) {
2828 if (is_bt_soc_on(adev) == false) {
2829 ALOGD("BT SCO/A2DP disconnected while in connection");
2830 out_standby_l(&usecase->stream.out->stream.common);
2831 }
2832 }
2833 } else if ((usecase->stream.out != NULL) &&
2834 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302835 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2836 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0791c8e2019-07-25 13:18:17 +08002837 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302838 usecase->stream.out->started) {
2839 if (is_bt_soc_on(adev) == false) {
2840 ALOGD("BT SCO/A2dp disconnected while in connection");
2841 out_standby_l(&usecase->stream.out->stream.common);
2842 }
2843 }
2844 }
2845
Yung Ti Su70cb8242018-06-22 17:38:47 +08002846 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002847 struct stream_out *voip_out = voip_usecase->stream.out;
2848 audio_extn_utils_send_app_type_gain(adev,
2849 voip_out->app_type_cfg.app_type,
2850 &voip_out->app_type_cfg.gain[0]);
2851 }
2852
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302853 ALOGD("%s: done",__func__);
2854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 return status;
2856}
2857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858static int stop_input_stream(struct stream_in *in)
2859{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302860 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302862
2863 if (in == NULL) {
2864 ALOGE("%s: stream_in ptr is NULL", __func__);
2865 return -EINVAL;
2866 }
2867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002869 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870
Eric Laurent994a6932013-07-17 11:51:42 -07002871 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002872 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 uc_info = get_usecase_from_list(adev, in->usecase);
2874 if (uc_info == NULL) {
2875 ALOGE("%s: Could not find the usecase (%d) in the list",
2876 __func__, in->usecase);
2877 return -EINVAL;
2878 }
2879
Carter Hsu2e429db2019-05-14 18:50:52 +08002880 priority_in = get_priority_input(adev);
2881
Derek Chenea197282019-01-07 17:35:01 -08002882 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2883 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002884
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002885 /* Close in-call recording streams */
2886 voice_check_and_stop_incall_rec_usecase(adev, in);
2887
Eric Laurent150dbfe2013-02-27 14:31:02 -08002888 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002889 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002890
2891 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002892 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302894 if (is_loopback_input_device(in->device))
2895 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2896
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002897 list_remove(&uc_info->list);
2898 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899
Carter Hsu2e429db2019-05-14 18:50:52 +08002900 if (priority_in == in) {
2901 priority_in = get_priority_input(adev);
2902 if (priority_in)
2903 select_devices(adev, priority_in->usecase);
2904 }
2905
Vatsal Buchac09ae062018-11-14 13:25:08 +05302906 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002907 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 return ret;
2909}
2910
2911int start_input_stream(struct stream_in *in)
2912{
2913 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002914 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302916
2917 if (in == NULL) {
2918 ALOGE("%s: stream_in ptr is NULL", __func__);
2919 return -EINVAL;
2920 }
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002923 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002924 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925
Mingming Yin2664a5b2015-09-03 10:53:11 -07002926 if (get_usecase_from_list(adev, usecase) == NULL)
2927 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302928 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2929 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002930
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302931 if (CARD_STATUS_OFFLINE == in->card_status||
2932 CARD_STATUS_OFFLINE == adev->card_status) {
2933 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302934 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302935 goto error_config;
2936 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302937
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302938 if (audio_is_bluetooth_sco_device(in->device)) {
2939 if (!adev->bt_sco_on) {
2940 ALOGE("%s: SCO profile is not ready, return error", __func__);
2941 ret = -EIO;
2942 goto error_config;
2943 }
2944 }
2945
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002946 /* Check if source matches incall recording usecase criteria */
2947 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2948 if (ret)
2949 goto error_config;
2950 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002951 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2952
2953 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2954 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2955 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002956 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002957 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002958
Eric Laurentb23d5282013-05-14 15:27:20 -07002959 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 if (in->pcm_device_id < 0) {
2961 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2962 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002963 ret = -EINVAL;
2964 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002968
2969 if (!uc_info) {
2970 ret = -ENOMEM;
2971 goto error_config;
2972 }
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 uc_info->id = in->usecase;
2975 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002976 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002977 uc_info->devices = in->device;
2978 uc_info->in_snd_device = SND_DEVICE_NONE;
2979 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002981 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002982 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302983 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2984 adev->perf_lock_opts,
2985 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002986 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987
Derek Chenea197282019-01-07 17:35:01 -08002988 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2989 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002990
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302991 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2992
Haynes Mathew George16081042017-05-31 17:16:49 -07002993 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302994 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302995 if (ret)
2996 goto error_open;
2997 else
2998 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002999 }
3000
Haynes Mathew George16081042017-05-31 17:16:49 -07003001 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003002 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003003 ALOGE("%s: pcm stream not ready", __func__);
3004 goto error_open;
3005 }
3006 ret = pcm_start(in->pcm);
3007 if (ret < 0) {
3008 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3009 goto error_open;
3010 }
3011 } else {
3012 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3013 unsigned int pcm_open_retry_count = 0;
3014
3015 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3016 flags |= PCM_MMAP | PCM_NOIRQ;
3017 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3018 } else if (in->realtime) {
3019 flags |= PCM_MMAP | PCM_NOIRQ;
3020 }
3021
Garmond Leunge2433c32017-09-28 21:51:22 -07003022 if (audio_extn_ffv_get_stream() == in) {
3023 ALOGD("%s: ffv stream, update pcm config", __func__);
3024 audio_extn_ffv_update_pcm_config(&config);
3025 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003026 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3027 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3028
3029 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003030 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003031 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003032 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003033 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303034 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303035 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3036 adev->card_status = CARD_STATUS_OFFLINE;
3037 in->card_status = CARD_STATUS_OFFLINE;
3038 ret = -EIO;
3039 goto error_open;
3040 }
3041
Haynes Mathew George16081042017-05-31 17:16:49 -07003042 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3043 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3044 if (in->pcm != NULL) {
3045 pcm_close(in->pcm);
3046 in->pcm = NULL;
3047 }
3048 if (pcm_open_retry_count-- == 0) {
3049 ret = -EIO;
3050 goto error_open;
3051 }
3052 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3053 continue;
3054 }
3055 break;
3056 }
3057
3058 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003059 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003060 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003061 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003062 if (ret < 0) {
3063 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3064 pcm_close(in->pcm);
3065 in->pcm = NULL;
3066 goto error_open;
3067 }
3068 register_in_stream(in);
3069 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003070 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003071 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003072 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003073 if (ret < 0) {
3074 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003075 pcm_close(in->pcm);
3076 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003077 goto error_open;
3078 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003079 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003080 }
3081
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003082 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003083 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3084 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003085
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303086 if (is_loopback_input_device(in->device))
3087 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3088
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303089done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003090 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303091 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003092 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303093 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003094 return ret;
3095
3096error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003097 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303098 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003100
Eric Laurentc8400632013-02-14 19:04:54 -08003101error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303102 /*
3103 * sleep 50ms to allow sufficient time for kernel
3104 * drivers to recover incases like SSR.
3105 */
3106 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003107 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303108 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003109 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110}
3111
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003112void lock_input_stream(struct stream_in *in)
3113{
3114 pthread_mutex_lock(&in->pre_lock);
3115 pthread_mutex_lock(&in->lock);
3116 pthread_mutex_unlock(&in->pre_lock);
3117}
3118
3119void lock_output_stream(struct stream_out *out)
3120{
3121 pthread_mutex_lock(&out->pre_lock);
3122 pthread_mutex_lock(&out->lock);
3123 pthread_mutex_unlock(&out->pre_lock);
3124}
3125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003126/* must be called with out->lock locked */
3127static int send_offload_cmd_l(struct stream_out* out, int command)
3128{
3129 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3130
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003131 if (!cmd) {
3132 ALOGE("failed to allocate mem for command 0x%x", command);
3133 return -ENOMEM;
3134 }
3135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 ALOGVV("%s %d", __func__, command);
3137
3138 cmd->cmd = command;
3139 list_add_tail(&out->offload_cmd_list, &cmd->node);
3140 pthread_cond_signal(&out->offload_cond);
3141 return 0;
3142}
3143
3144/* must be called iwth out->lock locked */
3145static void stop_compressed_output_l(struct stream_out *out)
3146{
3147 out->offload_state = OFFLOAD_STATE_IDLE;
3148 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003149 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 if (out->compr != NULL) {
3151 compress_stop(out->compr);
3152 while (out->offload_thread_blocked) {
3153 pthread_cond_wait(&out->cond, &out->lock);
3154 }
3155 }
3156}
3157
Varun Balaraje49253e2017-07-06 19:48:56 +05303158bool is_interactive_usecase(audio_usecase_t uc_id)
3159{
3160 unsigned int i;
3161 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3162 if (uc_id == interactive_usecases[i])
3163 return true;
3164 }
3165 return false;
3166}
3167
3168static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3169{
3170 audio_usecase_t ret_uc = USECASE_INVALID;
3171 unsigned int intract_uc_index;
3172 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3173
3174 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3175 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3176 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3177 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3178 ret_uc = interactive_usecases[intract_uc_index];
3179 break;
3180 }
3181 }
3182
3183 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3184 return ret_uc;
3185}
3186
3187static void free_interactive_usecase(struct audio_device *adev,
3188 audio_usecase_t uc_id)
3189{
3190 unsigned int interact_uc_index;
3191 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3192
3193 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3194 if (interactive_usecases[interact_uc_index] == uc_id) {
3195 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3196 break;
3197 }
3198 }
3199 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3200}
3201
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003202bool is_offload_usecase(audio_usecase_t uc_id)
3203{
3204 unsigned int i;
3205 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3206 if (uc_id == offload_usecases[i])
3207 return true;
3208 }
3209 return false;
3210}
3211
Dhananjay Kumarac341582017-02-23 23:42:25 +05303212static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003213{
vivek mehta446c3962015-09-14 10:57:35 -07003214 audio_usecase_t ret_uc = USECASE_INVALID;
3215 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003216 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003217 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303218 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003219 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3220 else
3221 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003222
vivek mehta446c3962015-09-14 10:57:35 -07003223 pthread_mutex_lock(&adev->lock);
3224 if (get_usecase_from_list(adev, ret_uc) != NULL)
3225 ret_uc = USECASE_INVALID;
3226 pthread_mutex_unlock(&adev->lock);
3227
3228 return ret_uc;
3229 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003230
3231 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003232 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3233 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3234 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3235 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003236 break;
3237 }
3238 }
vivek mehta446c3962015-09-14 10:57:35 -07003239
3240 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3241 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003242}
3243
3244static void free_offload_usecase(struct audio_device *adev,
3245 audio_usecase_t uc_id)
3246{
vivek mehta446c3962015-09-14 10:57:35 -07003247 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003248 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003249
3250 if (!adev->multi_offload_enable)
3251 return;
3252
3253 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3254 if (offload_usecases[offload_uc_index] == uc_id) {
3255 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003256 break;
3257 }
3258 }
3259 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3260}
3261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262static void *offload_thread_loop(void *context)
3263{
3264 struct stream_out *out = (struct stream_out *) context;
3265 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003266 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangebfa0502019-07-18 17:24:21 +08003269 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3271
3272 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003273 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003274 out->offload_state = OFFLOAD_STATE_IDLE;
3275 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003276 for (;;) {
3277 struct offload_cmd *cmd = NULL;
3278 stream_callback_event_t event;
3279 bool send_callback = false;
3280
3281 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3282 __func__, list_empty(&out->offload_cmd_list),
3283 out->offload_state);
3284 if (list_empty(&out->offload_cmd_list)) {
3285 ALOGV("%s SLEEPING", __func__);
3286 pthread_cond_wait(&out->offload_cond, &out->lock);
3287 ALOGV("%s RUNNING", __func__);
3288 continue;
3289 }
3290
3291 item = list_head(&out->offload_cmd_list);
3292 cmd = node_to_item(item, struct offload_cmd, node);
3293 list_remove(item);
3294
3295 ALOGVV("%s STATE %d CMD %d out->compr %p",
3296 __func__, out->offload_state, cmd->cmd, out->compr);
3297
3298 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3299 free(cmd);
3300 break;
3301 }
3302
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003303 // allow OFFLOAD_CMD_ERROR reporting during standby
3304 // this is needed to handle failures during compress_open
3305 // Note however that on a pause timeout, the stream is closed
3306 // and no offload usecase will be active. Therefore this
3307 // special case is needed for compress_open failures alone
3308 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3309 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003310 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003311 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003312 pthread_cond_signal(&out->cond);
3313 continue;
3314 }
3315 out->offload_thread_blocked = true;
3316 pthread_mutex_unlock(&out->lock);
3317 send_callback = false;
3318 switch(cmd->cmd) {
3319 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003320 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003321 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003322 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003323 send_callback = true;
3324 event = STREAM_CBK_EVENT_WRITE_READY;
3325 break;
3326 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003327 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303328 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003329 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303330 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003331 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303332 if (ret < 0)
3333 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303334 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303335 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003336 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003337 else
3338 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003339 if (-ENETRESET != ret && !(-EINTR == ret &&
3340 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303341 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303342 pthread_mutex_lock(&out->lock);
3343 out->send_new_metadata = 1;
3344 out->send_next_track_params = true;
3345 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303346 event = STREAM_CBK_EVENT_DRAIN_READY;
3347 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3348 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303349 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003350 break;
3351 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003352 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003353 ret = compress_drain(out->compr);
3354 ALOGD("copl(%p):out of compress_drain", out);
3355 // EINTR check avoids drain interruption due to SSR
3356 if (-ENETRESET != ret && !(-EINTR == ret &&
3357 CARD_STATUS_OFFLINE == out->card_status)) {
3358 send_callback = true;
3359 event = STREAM_CBK_EVENT_DRAIN_READY;
3360 } else
3361 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303363 case OFFLOAD_CMD_ERROR:
3364 ALOGD("copl(%p): sending error callback to AF", out);
3365 send_callback = true;
3366 event = STREAM_CBK_EVENT_ERROR;
3367 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 default:
3369 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3370 break;
3371 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003372 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 out->offload_thread_blocked = false;
3374 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003375 if (send_callback && out->client_callback) {
3376 ALOGVV("%s: sending client_callback event %d", __func__, event);
3377 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003378 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 free(cmd);
3380 }
3381
3382 pthread_cond_signal(&out->cond);
3383 while (!list_empty(&out->offload_cmd_list)) {
3384 item = list_head(&out->offload_cmd_list);
3385 list_remove(item);
3386 free(node_to_item(item, struct offload_cmd, node));
3387 }
3388 pthread_mutex_unlock(&out->lock);
3389
3390 return NULL;
3391}
3392
3393static int create_offload_callback_thread(struct stream_out *out)
3394{
3395 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3396 list_init(&out->offload_cmd_list);
3397 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3398 offload_thread_loop, out);
3399 return 0;
3400}
3401
3402static int destroy_offload_callback_thread(struct stream_out *out)
3403{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003404 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003405 stop_compressed_output_l(out);
3406 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3407
3408 pthread_mutex_unlock(&out->lock);
3409 pthread_join(out->offload_thread, (void **) NULL);
3410 pthread_cond_destroy(&out->offload_cond);
3411
3412 return 0;
3413}
3414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415static int stop_output_stream(struct stream_out *out)
3416{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303417 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 struct audio_usecase *uc_info;
3419 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003420 bool has_voip_usecase =
3421 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422
Eric Laurent994a6932013-07-17 11:51:42 -07003423 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003424 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 uc_info = get_usecase_from_list(adev, out->usecase);
3426 if (uc_info == NULL) {
3427 ALOGE("%s: Could not find the usecase (%d) in the list",
3428 __func__, out->usecase);
3429 return -EINVAL;
3430 }
3431
Derek Chenea197282019-01-07 17:35:01 -08003432 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3433 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003434
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003435 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303436 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003437 if (adev->visualizer_stop_output != NULL)
3438 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003439
3440 audio_extn_dts_remove_state_notifier_node(out->usecase);
3441
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003442 if (adev->offload_effects_stop_output != NULL)
3443 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003444 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3445 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3446 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003447 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003448
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003449 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3450 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003451 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003452 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003453
Eric Laurent150dbfe2013-02-27 14:31:02 -08003454 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003455 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003456
3457 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003458 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459
Aalique Grahame22e49102018-12-18 14:23:57 -08003460 audio_extn_extspk_update(adev->extspk);
3461
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003462 if (is_offload_usecase(out->usecase)) {
3463 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3464 adev->dsp_bit_width_enforce_mode,
3465 false);
3466 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003467 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3468 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3469 false);
3470
3471 if (ret != 0)
3472 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3473 /* default service interval was successfully updated,
3474 reopen USB backend with new service interval */
3475 ret = 0;
3476 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003477
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003478 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303479 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003480 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303481 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003482 ALOGV("Disable passthrough , reset mixer to pcm");
3483 /* NO_PASSTHROUGH */
3484 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003485 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003486 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3487 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003488
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303489 /* Must be called after removing the usecase from list */
3490 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303491 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303492
Manish Dewangan21a850a2017-08-14 12:03:55 +05303493 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003494 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3495 if (ret < 0)
3496 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3497 }
3498
juyuchen2d415992018-11-16 14:15:16 +08003499 /* 1) media + voip output routing to handset must route media back to
3500 speaker when voip stops.
3501 2) trigger voip input to reroute when voip output changes to
3502 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003503 if (has_voip_usecase ||
3504 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3505 struct listnode *node;
3506 struct audio_usecase *usecase;
3507 list_for_each(node, &adev->usecase_list) {
3508 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003509 if ((usecase->type == PCM_CAPTURE &&
3510 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3511 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003512 continue;
3513
3514 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3515 __func__, usecase->id, use_case_table[usecase->id],
3516 out->usecase, use_case_table[out->usecase]);
3517 select_devices(adev, usecase->id);
3518 }
3519 }
3520
Garmond Leung5fd0b552018-04-17 11:56:12 -07003521 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003522 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 return ret;
3524}
3525
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003526struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3527 unsigned int flags, unsigned int pcm_open_retry_count,
3528 struct pcm_config *config)
3529{
3530 struct pcm* pcm = NULL;
3531
3532 while (1) {
3533 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3534 if (pcm == NULL || !pcm_is_ready(pcm)) {
3535 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3536 if (pcm != NULL) {
3537 pcm_close(pcm);
3538 pcm = NULL;
3539 }
3540 if (pcm_open_retry_count-- == 0)
3541 return NULL;
3542
3543 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3544 continue;
3545 }
3546 break;
3547 }
3548
3549 if (pcm_is_ready(pcm)) {
3550 int ret = pcm_prepare(pcm);
3551 if (ret < 0) {
3552 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3553 pcm_close(pcm);
3554 pcm = NULL;
3555 }
3556 }
3557
3558 return pcm;
3559}
3560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561int start_output_stream(struct stream_out *out)
3562{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 struct audio_usecase *uc_info;
3565 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003566 char mixer_ctl_name[128];
3567 struct mixer_ctl *ctl = NULL;
3568 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303569 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003570 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571
Haynes Mathew George380745d2017-10-04 15:27:45 -07003572 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003573 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3574 ret = -EINVAL;
3575 goto error_config;
3576 }
3577
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003578 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303579 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003580 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303581
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303582 if (CARD_STATUS_OFFLINE == out->card_status ||
3583 CARD_STATUS_OFFLINE == adev->card_status) {
3584 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303585 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303586 goto error_config;
3587 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303588
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003589 //Update incall music usecase to reflect correct voice session
3590 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3591 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3592 if (ret != 0) {
3593 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3594 __func__, ret);
3595 goto error_config;
3596 }
3597 }
3598
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303599 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003600 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003601 if (out->devices &
3602 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303603 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303604 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303605 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3606 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3607 ret = -EAGAIN;
3608 goto error_config;
3609 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303610 }
3611 }
3612 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303613 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3614 if (!adev->bt_sco_on) {
3615 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3616 //combo usecase just by pass a2dp
3617 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3618 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3619 } else {
3620 ALOGE("%s: SCO profile is not ready, return error", __func__);
3621 ret = -EAGAIN;
3622 goto error_config;
3623 }
3624 }
3625 }
3626
Eric Laurentb23d5282013-05-14 15:27:20 -07003627 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 if (out->pcm_device_id < 0) {
3629 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3630 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003631 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003632 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 }
3634
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003635 if (is_haptic_usecase) {
3636 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3637 if (adev->haptic_pcm_device_id < 0) {
3638 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3639 __func__, adev->haptic_pcm_device_id, out->usecase);
3640 ret = -EINVAL;
3641 goto error_config;
3642 }
3643 }
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003646
3647 if (!uc_info) {
3648 ret = -ENOMEM;
3649 goto error_config;
3650 }
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 uc_info->id = out->usecase;
3653 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003654 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003655 uc_info->devices = out->devices;
3656 uc_info->in_snd_device = SND_DEVICE_NONE;
3657 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003658
3659 /* This must be called before adding this usecase to the list */
3660 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3661 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3662 /* USB backend is not reopened immediately.
3663 This is eventually done as part of select_devices */
3664 }
3665
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003666 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667
Wei Wangf7ca6c92017-11-21 14:51:20 -08003668 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303669 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3670 adev->perf_lock_opts,
3671 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303672
3673 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303674 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303675 if (audio_extn_passthru_is_enabled() &&
3676 audio_extn_passthru_is_passthrough_stream(out)) {
3677 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303678 }
3679 }
3680
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303681 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003682 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303683 if (!a2dp_combo) {
3684 check_a2dp_restore_l(adev, out, false);
3685 } else {
3686 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003687 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3688 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3689 else
3690 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303691 select_devices(adev, out->usecase);
3692 out->devices = dev;
3693 }
3694 } else {
3695 select_devices(adev, out->usecase);
3696 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003697
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003698 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3699 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003700 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003701 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003702
Derek Chenea197282019-01-07 17:35:01 -08003703 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3704 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003705
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003706 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3707 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003708
3709 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003710 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003711 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3712 ALOGE("%s: pcm stream not ready", __func__);
3713 goto error_open;
3714 }
3715 ret = pcm_start(out->pcm);
3716 if (ret < 0) {
3717 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3718 goto error_open;
3719 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003720 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003721 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003722 unsigned int flags = PCM_OUT;
3723 unsigned int pcm_open_retry_count = 0;
3724 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3725 flags |= PCM_MMAP | PCM_NOIRQ;
3726 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003727 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003728 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003729 } else
3730 flags |= PCM_MONOTONIC;
3731
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003732 if ((adev->vr_audio_mode_enabled) &&
3733 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3734 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3735 "PCM_Dev %d Topology", out->pcm_device_id);
3736 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3737 if (!ctl) {
3738 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3739 __func__, mixer_ctl_name);
3740 } else {
3741 //if success use ULLPP
3742 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3743 __func__, mixer_ctl_name, out->pcm_device_id);
3744 //There is a still a possibility that some sessions
3745 // that request for FAST|RAW when 3D audio is active
3746 //can go through ULLPP. Ideally we expects apps to
3747 //listen to audio focus and stop concurrent playback
3748 //Also, we will look for mode flag (voice_in_communication)
3749 //before enabling the realtime flag.
3750 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3751 }
3752 }
3753
Surendar Karka91fa3682018-07-02 18:12:12 +05303754 if (out->realtime)
3755 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3756 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3757
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003758 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3759 flags, pcm_open_retry_count,
3760 &(out->config));
3761 if (out->pcm == NULL) {
3762 ret = -EIO;
3763 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003764 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003765
3766 if (is_haptic_usecase) {
3767 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3768 adev->haptic_pcm_device_id,
3769 flags, pcm_open_retry_count,
3770 &(adev->haptics_config));
3771 // failure to open haptics pcm shouldnt stop audio,
3772 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003773
3774 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3775 ALOGD("%s: enable haptic audio synchronization", __func__);
3776 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3777 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003778 }
3779
Surendar Karka91fa3682018-07-02 18:12:12 +05303780 if (!out->realtime)
3781 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303782 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003783
Zhou Song2b8f28f2017-09-11 10:51:38 +08003784 // apply volume for voip playback after path is set up
3785 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3786 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303787 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3788 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303789 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3790 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003791 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3792 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303793 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003794 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003795 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303796 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003797 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3798 adev->dsp_bit_width_enforce_mode,
3799 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003801 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003802 out->compr = compress_open(adev->snd_card,
3803 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003804 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003805 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303806 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303807 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3808 adev->card_status = CARD_STATUS_OFFLINE;
3809 out->card_status = CARD_STATUS_OFFLINE;
3810 ret = -EIO;
3811 goto error_open;
3812 }
3813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003815 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003816 compress_close(out->compr);
3817 out->compr = NULL;
3818 ret = -EIO;
3819 goto error_open;
3820 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303821 /* compress_open sends params of the track, so reset the flag here */
3822 out->is_compr_metadata_avail = false;
3823
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003824 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003825 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003826
Fred Oh3f43e742015-03-04 18:42:34 -08003827 /* Since small bufs uses blocking writes, a write will be blocked
3828 for the default max poll time (20s) in the event of an SSR.
3829 Reduce the poll time to observe and deal with SSR faster.
3830 */
Ashish Jain5106d362016-05-11 19:23:33 +05303831 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003832 compress_set_max_poll_wait(out->compr, 1000);
3833 }
3834
Manish Dewangan69426c82017-01-30 17:35:36 +05303835 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303836 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303837
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003838 audio_extn_dts_create_state_notifier_node(out->usecase);
3839 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3840 popcount(out->channel_mask),
3841 out->playback_started);
3842
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003843#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303844 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003845 audio_extn_dolby_send_ddp_endp_params(adev);
3846#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303847 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3848 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003849 if (adev->visualizer_start_output != NULL)
3850 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3851 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303852 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003853 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003854 }
Derek Chenf13dd492018-11-13 14:53:51 -08003855
3856 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3857 /* Update cached volume from media to offload/direct stream */
3858 struct listnode *node = NULL;
3859 list_for_each(node, &adev->active_outputs_list) {
3860 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3861 streams_output_ctxt_t,
3862 list);
3863 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3864 out->volume_l = out_ctxt->output->volume_l;
3865 out->volume_r = out_ctxt->output->volume_r;
3866 }
3867 }
3868 out_set_compr_volume(&out->stream,
3869 out->volume_l, out->volume_r);
3870 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003872
3873 if (ret == 0) {
3874 register_out_stream(out);
3875 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003876 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3877 ALOGE("%s: pcm stream not ready", __func__);
3878 goto error_open;
3879 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003880 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003881 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003882 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003883 if (ret < 0)
3884 goto error_open;
3885 }
3886 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003887 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303888 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003889 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003890
vivek mehtad15d2bf2019-05-17 13:35:10 -07003891 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3892 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3893 audio_low_latency_hint_start();
3894 }
3895
Manish Dewangan21a850a2017-08-14 12:03:55 +05303896 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003897 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003898 if (ret < 0)
3899 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3900 }
3901
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003902 // consider a scenario where on pause lower layers are tear down.
3903 // so on resume, swap mixer control need to be sent only when
3904 // backend is active, hence rather than sending from enable device
3905 // sending it from start of streamtream
3906
3907 platform_set_swap_channels(adev, true);
3908
Haynes Mathew George380745d2017-10-04 15:27:45 -07003909 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303910 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003911 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003912error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003913 if (adev->haptic_pcm) {
3914 pcm_close(adev->haptic_pcm);
3915 adev->haptic_pcm = NULL;
3916 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003917 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303918 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003920error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303921 /*
3922 * sleep 50ms to allow sufficient time for kernel
3923 * drivers to recover incases like SSR.
3924 */
3925 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003926 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303927 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003928 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929}
3930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931static int check_input_parameters(uint32_t sample_rate,
3932 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003933 int channel_count,
3934 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003936 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303938 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3939 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3940 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003941 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003942 !audio_extn_compr_cap_format_supported(format) &&
3943 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003944 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003945
Aalique Grahame22e49102018-12-18 14:23:57 -08003946 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3947 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3948 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3949 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3950 return -EINVAL;
3951 }
3952
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003953 switch (channel_count) {
3954 case 1:
3955 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303956 case 3:
3957 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003958 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003959 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303960 case 10:
3961 case 12:
3962 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003963 break;
3964 default:
3965 ret = -EINVAL;
3966 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967
3968 switch (sample_rate) {
3969 case 8000:
3970 case 11025:
3971 case 12000:
3972 case 16000:
3973 case 22050:
3974 case 24000:
3975 case 32000:
3976 case 44100:
3977 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003978 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303979 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003980 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303981 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 break;
3983 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003984 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985 }
3986
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003987 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988}
3989
Naresh Tanniru04f71882018-06-26 17:46:22 +05303990
3991/** Add a value in a list if not already present.
3992 * @return true if value was successfully inserted or already present,
3993 * false if the list is full and does not contain the value.
3994 */
3995static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3996 for (size_t i = 0; i < list_length; i++) {
3997 if (list[i] == value) return true; // value is already present
3998 if (list[i] == 0) { // no values in this slot
3999 list[i] = value;
4000 return true; // value inserted
4001 }
4002 }
4003 return false; // could not insert value
4004}
4005
4006/** Add channel_mask in supported_channel_masks if not already present.
4007 * @return true if channel_mask was successfully inserted or already present,
4008 * false if supported_channel_masks is full and does not contain channel_mask.
4009 */
4010static void register_channel_mask(audio_channel_mask_t channel_mask,
4011 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4012 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4013 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4014}
4015
4016/** Add format in supported_formats if not already present.
4017 * @return true if format was successfully inserted or already present,
4018 * false if supported_formats is full and does not contain format.
4019 */
4020static void register_format(audio_format_t format,
4021 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4022 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4023 "%s: stream can not declare supporting its format %x", __func__, format);
4024}
4025/** Add sample_rate in supported_sample_rates if not already present.
4026 * @return true if sample_rate was successfully inserted or already present,
4027 * false if supported_sample_rates is full and does not contain sample_rate.
4028 */
4029static void register_sample_rate(uint32_t sample_rate,
4030 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4031 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4032 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4033}
4034
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004035static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4036{
4037 uint32_t high = num1, low = num2, temp = 0;
4038
4039 if (!num1 || !num2)
4040 return 0;
4041
4042 if (num1 < num2) {
4043 high = num2;
4044 low = num1;
4045 }
4046
4047 while (low != 0) {
4048 temp = low;
4049 low = high % low;
4050 high = temp;
4051 }
4052 return (num1 * num2)/high;
4053}
4054
4055static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4056{
4057 uint32_t remainder = 0;
4058
4059 if (!multiplier)
4060 return num;
4061
4062 remainder = num % multiplier;
4063 if (remainder)
4064 num += (multiplier - remainder);
4065
4066 return num;
4067}
4068
Aalique Grahame22e49102018-12-18 14:23:57 -08004069static size_t get_stream_buffer_size(size_t duration_ms,
4070 uint32_t sample_rate,
4071 audio_format_t format,
4072 int channel_count,
4073 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074{
4075 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004076 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077
Aalique Grahame22e49102018-12-18 14:23:57 -08004078 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004079 if (is_low_latency)
4080 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304081
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004082 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004083 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084
Ralf Herzbd08d632018-09-28 15:50:49 +02004085 /* make sure the size is multiple of 32 bytes and additionally multiple of
4086 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004087 * At 48 kHz mono 16-bit PCM:
4088 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4089 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004090 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004091 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004092 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004093
4094 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095}
4096
Aalique Grahame22e49102018-12-18 14:23:57 -08004097static size_t get_input_buffer_size(uint32_t sample_rate,
4098 audio_format_t format,
4099 int channel_count,
4100 bool is_low_latency)
4101{
4102 /* Don't know if USB HIFI in this context so use true to be conservative */
4103 if (check_input_parameters(sample_rate, format, channel_count,
4104 true /*is_usb_hifi */) != 0)
4105 return 0;
4106
4107 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4108 sample_rate,
4109 format,
4110 channel_count,
4111 is_low_latency);
4112}
4113
Derek Chenf6318be2017-06-12 17:16:24 -04004114size_t get_output_period_size(uint32_t sample_rate,
4115 audio_format_t format,
4116 int channel_count,
4117 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304118{
4119 size_t size = 0;
4120 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4121
4122 if ((duration == 0) || (sample_rate == 0) ||
4123 (bytes_per_sample == 0) || (channel_count == 0)) {
4124 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4125 bytes_per_sample, channel_count);
4126 return -EINVAL;
4127 }
4128
4129 size = (sample_rate *
4130 duration *
4131 bytes_per_sample *
4132 channel_count) / 1000;
4133 /*
4134 * To have same PCM samples for all channels, the buffer size requires to
4135 * be multiple of (number of channels * bytes per sample)
4136 * For writes to succeed, the buffer must be written at address which is multiple of 32
4137 */
4138 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4139
4140 return (size/(channel_count * bytes_per_sample));
4141}
4142
Zhou Song48453a02018-01-10 17:50:59 +08004143static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304144{
4145 uint64_t actual_frames_rendered = 0;
4146 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4147
4148 /* This adjustment accounts for buffering after app processor.
4149 * It is based on estimated DSP latency per use case, rather than exact.
4150 */
4151 int64_t platform_latency = platform_render_latency(out->usecase) *
4152 out->sample_rate / 1000000LL;
4153
Zhou Song48453a02018-01-10 17:50:59 +08004154 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304155 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4156 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4157 * hence only estimate.
4158 */
4159 int64_t signed_frames = out->written - kernel_buffer_size;
4160
4161 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4162
Zhou Song48453a02018-01-10 17:50:59 +08004163 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304164 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004165 if (timestamp != NULL )
4166 *timestamp = out->writeAt;
4167 } else if (timestamp != NULL) {
4168 clock_gettime(CLOCK_MONOTONIC, timestamp);
4169 }
4170 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304171
4172 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4173 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4174 (long long int)out->written, (int)kernel_buffer_size,
4175 audio_bytes_per_sample(out->compr_config.codec->format),
4176 popcount(out->channel_mask));
4177
4178 return actual_frames_rendered;
4179}
4180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4182{
4183 struct stream_out *out = (struct stream_out *)stream;
4184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004185 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186}
4187
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004188static int out_set_sample_rate(struct audio_stream *stream __unused,
4189 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190{
4191 return -ENOSYS;
4192}
4193
4194static size_t out_get_buffer_size(const struct audio_stream *stream)
4195{
4196 struct stream_out *out = (struct stream_out *)stream;
4197
Varun Balaraje49253e2017-07-06 19:48:56 +05304198 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304199 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304200 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304201 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4202 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4203 else
4204 return out->compr_config.fragment_size;
4205 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004206 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304207 else if (is_offload_usecase(out->usecase) &&
4208 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304209 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004210
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004211 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004212 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213}
4214
4215static uint32_t out_get_channels(const struct audio_stream *stream)
4216{
4217 struct stream_out *out = (struct stream_out *)stream;
4218
4219 return out->channel_mask;
4220}
4221
4222static audio_format_t out_get_format(const struct audio_stream *stream)
4223{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004224 struct stream_out *out = (struct stream_out *)stream;
4225
4226 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227}
4228
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004229static int out_set_format(struct audio_stream *stream __unused,
4230 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231{
4232 return -ENOSYS;
4233}
4234
4235static int out_standby(struct audio_stream *stream)
4236{
4237 struct stream_out *out = (struct stream_out *)stream;
4238 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004239 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004240
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304241 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4242 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004244 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004246 if (adev->adm_deregister_stream)
4247 adev->adm_deregister_stream(adev->adm_data, out->handle);
4248
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004249 if (is_offload_usecase(out->usecase))
4250 stop_compressed_output_l(out);
4251
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004252 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05304253
4254 amplifier_output_stream_standby((struct audio_stream_out *) stream);
4255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004257 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4258 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304259 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004260 pthread_mutex_unlock(&adev->lock);
4261 pthread_mutex_unlock(&out->lock);
4262 ALOGD("VOIP output entered standby");
4263 return 0;
4264 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004265 if (out->pcm) {
4266 pcm_close(out->pcm);
4267 out->pcm = NULL;
4268 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004269 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4270 do_stop = out->playback_started;
4271 out->playback_started = false;
4272 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004273 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004274 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304275 out->send_next_track_params = false;
4276 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004277 out->gapless_mdata.encoder_delay = 0;
4278 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004279 if (out->compr != NULL) {
4280 compress_close(out->compr);
4281 out->compr = NULL;
4282 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004283 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004284 if (do_stop) {
4285 stop_output_stream(out);
4286 }
Lakshman Chaluvaraju40459022019-06-24 10:04:52 +05304287 // if fm is active route on selected device in UI
4288 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004289 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290 }
4291 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304292 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293 return 0;
4294}
4295
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304296static int out_on_error(struct audio_stream *stream)
4297{
4298 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004299 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304300
4301 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004302 // always send CMD_ERROR for offload streams, this
4303 // is needed e.g. when SSR happens within compress_open
4304 // since the stream is active, offload_callback_thread is also active.
4305 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4306 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004307 }
4308 pthread_mutex_unlock(&out->lock);
4309
4310 status = out_standby(&out->stream.common);
4311
4312 lock_output_stream(out);
4313 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004314 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304315 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304316
4317 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4318 ALOGD("Setting previous card status if offline");
4319 out->prev_card_status_offline = true;
4320 }
4321
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304322 pthread_mutex_unlock(&out->lock);
4323
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004324 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304325}
4326
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304327/*
4328 *standby implementation without locks, assumes that the callee already
4329 *has taken adev and out lock.
4330 */
4331int out_standby_l(struct audio_stream *stream)
4332{
4333 struct stream_out *out = (struct stream_out *)stream;
4334 struct audio_device *adev = out->dev;
4335
4336 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4337 stream, out->usecase, use_case_table[out->usecase]);
4338
4339 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004340 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304341 if (adev->adm_deregister_stream)
4342 adev->adm_deregister_stream(adev->adm_data, out->handle);
4343
4344 if (is_offload_usecase(out->usecase))
4345 stop_compressed_output_l(out);
4346
4347 out->standby = true;
4348 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4349 voice_extn_compress_voip_close_output_stream(stream);
4350 out->started = 0;
4351 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004352 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304353 return 0;
4354 } else if (!is_offload_usecase(out->usecase)) {
4355 if (out->pcm) {
4356 pcm_close(out->pcm);
4357 out->pcm = NULL;
4358 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004359 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4360 if (adev->haptic_pcm) {
4361 pcm_close(adev->haptic_pcm);
4362 adev->haptic_pcm = NULL;
4363 }
4364
4365 if (adev->haptic_buffer != NULL) {
4366 free(adev->haptic_buffer);
4367 adev->haptic_buffer = NULL;
4368 adev->haptic_buffer_size = 0;
4369 }
4370 adev->haptic_pcm_device_id = 0;
4371 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304372 } else {
4373 ALOGD("copl(%p):standby", out);
4374 out->send_next_track_params = false;
4375 out->is_compr_metadata_avail = false;
4376 out->gapless_mdata.encoder_delay = 0;
4377 out->gapless_mdata.encoder_padding = 0;
4378 if (out->compr != NULL) {
4379 compress_close(out->compr);
4380 out->compr = NULL;
4381 }
4382 }
4383 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004384 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304385 }
4386 ALOGD("%s: exit", __func__);
4387 return 0;
4388}
4389
Aalique Grahame22e49102018-12-18 14:23:57 -08004390static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391{
Aalique Grahame22e49102018-12-18 14:23:57 -08004392 struct stream_out *out = (struct stream_out *)stream;
4393
4394 // We try to get the lock for consistency,
4395 // but it isn't necessary for these variables.
4396 // If we're not in standby, we may be blocked on a write.
4397 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4398 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4399 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4400
4401 if (locked) {
4402 pthread_mutex_unlock(&out->lock);
4403 }
4404
4405 // dump error info
4406 (void)error_log_dump(
4407 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 return 0;
4410}
4411
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004412static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4413{
4414 int ret = 0;
4415 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004416
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004417 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004418 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004419 return -EINVAL;
4420 }
4421
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304422 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004423
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004424 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4425 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304426 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004427 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004428 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4429 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304430 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004431 }
4432
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004433 ALOGV("%s new encoder delay %u and padding %u", __func__,
4434 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4435
4436 return 0;
4437}
4438
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004439static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4440{
4441 return out == adev->primary_output || out == adev->voice_tx_output;
4442}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004443
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304444// note: this call is safe only if the stream_cb is
4445// removed first in close_output_stream (as is done now).
4446static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4447{
4448 if (!stream || !parms)
4449 return;
4450
4451 struct stream_out *out = (struct stream_out *)stream;
4452 struct audio_device *adev = out->dev;
4453
4454 card_status_t status;
4455 int card;
4456 if (parse_snd_card_status(parms, &card, &status) < 0)
4457 return;
4458
4459 pthread_mutex_lock(&adev->lock);
4460 bool valid_cb = (card == adev->snd_card);
4461 pthread_mutex_unlock(&adev->lock);
4462
4463 if (!valid_cb)
4464 return;
4465
4466 lock_output_stream(out);
4467 if (out->card_status != status)
4468 out->card_status = status;
4469 pthread_mutex_unlock(&out->lock);
4470
4471 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4472 use_case_table[out->usecase],
4473 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4474
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304475 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304476 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304477 if (voice_is_call_state_active(adev) &&
4478 out == adev->primary_output) {
4479 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4480 pthread_mutex_lock(&adev->lock);
4481 voice_stop_call(adev);
4482 adev->mode = AUDIO_MODE_NORMAL;
4483 pthread_mutex_unlock(&adev->lock);
4484 }
4485 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304486 return;
4487}
4488
Kevin Rocardfce19002017-08-07 19:21:36 -07004489static int get_alive_usb_card(struct str_parms* parms) {
4490 int card;
4491 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4492 !audio_extn_usb_alive(card)) {
4493 return card;
4494 }
4495 return -ENODEV;
4496}
4497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4499{
4500 struct stream_out *out = (struct stream_out *)stream;
4501 struct audio_device *adev = out->dev;
4502 struct str_parms *parms;
4503 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004504 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304505 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004506 bool reconfig = false;
4507 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508
sangwoobc677242013-08-08 16:53:43 +09004509 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004510 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304512 if (!parms)
4513 goto error;
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05304514
4515 amplifier_out_set_parameters(parms);
4516
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004517 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4518 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004520 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004521 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004523 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004524 * When HDMI cable is unplugged the music playback is paused and
4525 * the policy manager sends routing=0. But the audioflinger continues
4526 * to write data until standby time (3sec). As the HDMI core is
4527 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004528 * Avoid this by routing audio to speaker until standby.
4529 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004530 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4531 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304532 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004533 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4534 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004535 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304536 /*
4537 * When A2DP is disconnected the
4538 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004539 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304540 * (3sec). As BT is turned off, the write gets blocked.
4541 * Avoid this by routing audio to speaker until standby.
4542 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004543 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004544 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004545 !audio_extn_a2dp_source_is_ready() &&
4546 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304547 val = AUDIO_DEVICE_OUT_SPEAKER;
4548 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304549 /*
4550 * When USB headset is disconnected the music platback paused
4551 * and the policy manager send routing=0. But if the USB is connected
4552 * back before the standby time, AFE is not closed and opened
4553 * when USB is connected back. So routing to speker will guarantee
4554 * AFE reconfiguration and AFE will be opend once USB is connected again
4555 */
4556 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4557 (val == AUDIO_DEVICE_NONE) &&
4558 !audio_extn_usb_connected(parms)) {
4559 val = AUDIO_DEVICE_OUT_SPEAKER;
4560 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304561 /* To avoid a2dp to sco overlapping / BT device improper state
4562 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304563 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304564 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004565 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004566 if (val &
4567 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304568 //combo usecase just by pass a2dp
4569 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304570 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304571 } else {
4572 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4573 /* update device to a2dp and don't route as BT returned error
4574 * However it is still possible a2dp routing called because
4575 * of current active device disconnection (like wired headset)
4576 */
4577 out->devices = val;
4578 pthread_mutex_unlock(&out->lock);
4579 pthread_mutex_unlock(&adev->lock);
4580 goto error;
4581 }
4582 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304583 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004584
4585 audio_devices_t new_dev = val;
4586
4587 // Workaround: If routing to an non existing usb device, fail gracefully
4588 // The routing request will otherwise block during 10 second
4589 int card;
4590 if (audio_is_usb_out_device(new_dev) &&
4591 (card = get_alive_usb_card(parms)) >= 0) {
4592
4593 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4594 pthread_mutex_unlock(&adev->lock);
4595 pthread_mutex_unlock(&out->lock);
4596 ret = -ENOSYS;
4597 goto routing_fail;
4598 }
4599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004600 /*
4601 * select_devices() call below switches all the usecases on the same
4602 * backend to the new device. Refer to check_usecases_codec_backend() in
4603 * the select_devices(). But how do we undo this?
4604 *
4605 * For example, music playback is active on headset (deep-buffer usecase)
4606 * and if we go to ringtones and select a ringtone, low-latency usecase
4607 * will be started on headset+speaker. As we can't enable headset+speaker
4608 * and headset devices at the same time, select_devices() switches the music
4609 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4610 * So when the ringtone playback is completed, how do we undo the same?
4611 *
4612 * We are relying on the out_set_parameters() call on deep-buffer output,
4613 * once the ringtone playback is ended.
4614 * NOTE: We should not check if the current devices are same as new devices.
4615 * Because select_devices() must be called to switch back the music
4616 * playback to headset.
4617 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004618 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004619 audio_devices_t new_dev = val;
4620 bool same_dev = out->devices == new_dev;
4621 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004622
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004623 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004624 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004625 if (adev->mode == AUDIO_MODE_IN_CALL) {
4626 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004627 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4628 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4629 audio_extn_usb_set_service_interval(true /*playback*/,
4630 service_interval,
4631 &reconfig);
4632 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4633 }
4634 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004635 }
4636 } else {
4637 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004638 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004639 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004640 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004641
4642 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004643 if (!same_dev) {
4644 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304645 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4646 adev->perf_lock_opts,
4647 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004648 if (adev->adm_on_routing_change)
4649 adev->adm_on_routing_change(adev->adm_data,
4650 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004651 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304652 if (!bypass_a2dp) {
4653 select_devices(adev, out->usecase);
4654 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004655 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4656 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4657 else
4658 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304659 select_devices(adev, out->usecase);
4660 out->devices = new_dev;
4661 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004662
4663 if (!same_dev) {
4664 // on device switch force swap, lower functions will make sure
4665 // to check if swap is allowed or not.
4666 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304667 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004668 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304669 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4670 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004671 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304672 pthread_mutex_lock(&out->compr_mute_lock);
4673 out->a2dp_compress_mute = false;
4674 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4675 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004676 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4677 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304678 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004679 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004680 }
4681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004683 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004684
4685 /*handles device and call state changes*/
4686 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004688 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004689
4690 if (out == adev->primary_output) {
4691 pthread_mutex_lock(&adev->lock);
4692 audio_extn_set_parameters(adev, parms);
4693 pthread_mutex_unlock(&adev->lock);
4694 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004695 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004696 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004697 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004698
4699 audio_extn_dts_create_state_notifier_node(out->usecase);
4700 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4701 popcount(out->channel_mask),
4702 out->playback_started);
4703
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004704 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004705 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004706
Surendar Karkaf51b5842018-04-26 11:28:38 +05304707 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4708 sizeof(value));
4709 if (err >= 0) {
4710 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4711 audio_extn_send_dual_mono_mixing_coefficients(out);
4712 }
4713
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304714 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4715 if (err >= 0) {
4716 strlcpy(out->profile, value, sizeof(out->profile));
4717 ALOGV("updating stream profile with value '%s'", out->profile);
4718 lock_output_stream(out);
4719 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4720 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004721 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304722 out->sample_rate, out->bit_width,
4723 out->channel_mask, out->profile,
4724 &out->app_type_cfg);
4725 pthread_mutex_unlock(&out->lock);
4726 }
4727
Alexy Joseph98988832017-01-13 14:56:59 -08004728 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004729 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4730 // and vendor.audio.hal.output.suspend.supported is set to true
4731 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004732 //check suspend parameter only for low latency and if the property
4733 //is enabled
4734 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4735 ALOGI("%s: got suspend_playback %s", __func__, value);
4736 lock_output_stream(out);
4737 if (!strncmp(value, "false", 5)) {
4738 //suspend_playback=false is supposed to set QOS value back to 75%
4739 //the mixer control sent with value Enable will achieve that
4740 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4741 } else if (!strncmp (value, "true", 4)) {
4742 //suspend_playback=true is supposed to remove QOS value
4743 //resetting the mixer control will set the default value
4744 //for the mixer control which is Disable and this removes the QOS vote
4745 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4746 } else {
4747 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4748 " got %s", __func__, value);
4749 ret = -1;
4750 }
4751
4752 if (ret != 0) {
4753 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4754 __func__, out->pm_qos_mixer_path, ret);
4755 }
4756
4757 pthread_mutex_unlock(&out->lock);
4758 }
4759 }
4760 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304762error:
Eric Laurent994a6932013-07-17 11:51:42 -07004763 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 return ret;
4765}
4766
Paul McLeana50b7332018-12-17 08:24:21 -07004767static int in_set_microphone_direction(const struct audio_stream_in *stream,
4768 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004769 struct stream_in *in = (struct stream_in *)stream;
4770
4771 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4772
4773 in->direction = dir;
4774
4775 if (in->standby)
4776 return 0;
4777
4778 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004779}
4780
4781static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004782 struct stream_in *in = (struct stream_in *)stream;
4783
4784 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4785
4786 if (zoom > 1.0 || zoom < -1.0)
4787 return -EINVAL;
4788
4789 in->zoom = zoom;
4790
4791 if (in->standby)
4792 return 0;
4793
4794 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004795}
4796
4797
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004798static bool stream_get_parameter_channels(struct str_parms *query,
4799 struct str_parms *reply,
4800 audio_channel_mask_t *supported_channel_masks) {
4801 int ret = -1;
4802 char value[512];
4803 bool first = true;
4804 size_t i, j;
4805
4806 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4807 ret = 0;
4808 value[0] = '\0';
4809 i = 0;
4810 while (supported_channel_masks[i] != 0) {
4811 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4812 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4813 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304814 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004815
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304816 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004817 first = false;
4818 break;
4819 }
4820 }
4821 i++;
4822 }
4823 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4824 }
4825 return ret == 0;
4826}
4827
4828static bool stream_get_parameter_formats(struct str_parms *query,
4829 struct str_parms *reply,
4830 audio_format_t *supported_formats) {
4831 int ret = -1;
4832 char value[256];
4833 size_t i, j;
4834 bool first = true;
4835
4836 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4837 ret = 0;
4838 value[0] = '\0';
4839 i = 0;
4840 while (supported_formats[i] != 0) {
4841 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4842 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4843 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304844 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004845 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304846 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004847 first = false;
4848 break;
4849 }
4850 }
4851 i++;
4852 }
4853 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4854 }
4855 return ret == 0;
4856}
4857
4858static bool stream_get_parameter_rates(struct str_parms *query,
4859 struct str_parms *reply,
4860 uint32_t *supported_sample_rates) {
4861
4862 int i;
4863 char value[256];
4864 int ret = -1;
4865 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4866 ret = 0;
4867 value[0] = '\0';
4868 i=0;
4869 int cursor = 0;
4870 while (supported_sample_rates[i]) {
4871 int avail = sizeof(value) - cursor;
4872 ret = snprintf(value + cursor, avail, "%s%d",
4873 cursor > 0 ? "|" : "",
4874 supported_sample_rates[i]);
4875 if (ret < 0 || ret >= avail) {
4876 // if cursor is at the last element of the array
4877 // overwrite with \0 is duplicate work as
4878 // snprintf already put a \0 in place.
4879 // else
4880 // we had space to write the '|' at value[cursor]
4881 // (which will be overwritten) or no space to fill
4882 // the first element (=> cursor == 0)
4883 value[cursor] = '\0';
4884 break;
4885 }
4886 cursor += ret;
4887 ++i;
4888 }
4889 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4890 value);
4891 }
4892 return ret >= 0;
4893}
4894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4896{
4897 struct stream_out *out = (struct stream_out *)stream;
4898 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004899 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004900 char value[256];
4901 struct str_parms *reply = str_parms_create();
4902 size_t i, j;
4903 int ret;
4904 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004905
4906 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004907 if (reply) {
4908 str_parms_destroy(reply);
4909 }
4910 if (query) {
4911 str_parms_destroy(query);
4912 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004913 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4914 return NULL;
4915 }
4916
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004917 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4919 if (ret >= 0) {
4920 value[0] = '\0';
4921 i = 0;
4922 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004923 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4924 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004926 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004928 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004929 first = false;
4930 break;
4931 }
4932 }
4933 i++;
4934 }
4935 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4936 str = str_parms_to_str(reply);
4937 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004938 voice_extn_out_get_parameters(out, query, reply);
4939 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004941
Alexy Joseph62142aa2015-11-16 15:10:34 -08004942
4943 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4944 if (ret >= 0) {
4945 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304946 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4947 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004948 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304949 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004950 } else {
4951 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304952 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004953 }
4954 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004955 if (str)
4956 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004957 str = str_parms_to_str(reply);
4958 }
4959
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004960 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4961 if (ret >= 0) {
4962 value[0] = '\0';
4963 i = 0;
4964 first = true;
4965 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004966 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4967 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004968 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004969 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004970 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004971 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004972 first = false;
4973 break;
4974 }
4975 }
4976 i++;
4977 }
4978 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004979 if (str)
4980 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004981 str = str_parms_to_str(reply);
4982 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004983
4984 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4985 if (ret >= 0) {
4986 value[0] = '\0';
4987 i = 0;
4988 first = true;
4989 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004990 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4991 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004992 if (!first) {
4993 strlcat(value, "|", sizeof(value));
4994 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004995 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004996 first = false;
4997 break;
4998 }
4999 }
5000 i++;
5001 }
5002 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5003 if (str)
5004 free(str);
5005 str = str_parms_to_str(reply);
5006 }
5007
Alexy Joseph98988832017-01-13 14:56:59 -08005008 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5009 //only low latency track supports suspend_resume
5010 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005011 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005012 if (str)
5013 free(str);
5014 str = str_parms_to_str(reply);
5015 }
5016
5017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005018 str_parms_destroy(query);
5019 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005020 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021 return str;
5022}
5023
5024static uint32_t out_get_latency(const struct audio_stream_out *stream)
5025{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005026 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005028 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005029
Alexy Josephaa54c872014-12-03 02:46:47 -08005030 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305031 lock_output_stream(out);
5032 latency = audio_extn_utils_compress_get_dsp_latency(out);
5033 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005034 } else if ((out->realtime) ||
5035 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005036 // since the buffer won't be filled up faster than realtime,
5037 // return a smaller number
5038 if (out->config.rate)
5039 period_ms = (out->af_period_multiplier * out->config.period_size *
5040 1000) / (out->config.rate);
5041 else
5042 period_ms = 0;
5043 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005044 } else {
5045 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005046 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005047 }
5048
yidongh0515e042017-07-06 15:00:34 +08005049 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005050 latency += audio_extn_a2dp_get_encoder_latency();
5051
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305052 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005053 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005054}
5055
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305056static float AmpToDb(float amplification)
5057{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305058 float db = DSD_VOLUME_MIN_DB;
5059 if (amplification > 0) {
5060 db = 20 * log10(amplification);
5061 if(db < DSD_VOLUME_MIN_DB)
5062 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305063 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305064 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305065}
5066
Arun Mirpuri5d170872019-03-26 13:21:31 -07005067static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5068 float right)
5069{
5070 struct stream_out *out = (struct stream_out *)stream;
5071 long volume = 0;
5072 char mixer_ctl_name[128] = "";
5073 struct audio_device *adev = out->dev;
5074 struct mixer_ctl *ctl = NULL;
5075 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5076 PCM_PLAYBACK);
5077
5078 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5079 "Playback %d Volume", pcm_device_id);
5080 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5081 if (!ctl) {
5082 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5083 __func__, mixer_ctl_name);
5084 return -EINVAL;
5085 }
5086 if (left != right)
5087 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5088 __func__, left, right);
5089 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5090 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5091 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5092 __func__, mixer_ctl_name, volume);
5093 return -EINVAL;
5094 }
5095 return 0;
5096}
5097
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305098static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5099 float right)
5100{
5101 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305102 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305103 char mixer_ctl_name[128];
5104 struct audio_device *adev = out->dev;
5105 struct mixer_ctl *ctl;
5106 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5107 PCM_PLAYBACK);
5108
5109 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5110 "Compress Playback %d Volume", pcm_device_id);
5111 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5112 if (!ctl) {
5113 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5114 __func__, mixer_ctl_name);
5115 return -EINVAL;
5116 }
5117 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5118 __func__, mixer_ctl_name, left, right);
5119 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5120 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5121 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5122
5123 return 0;
5124}
5125
Zhou Song2b8f28f2017-09-11 10:51:38 +08005126static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5127 float right)
5128{
5129 struct stream_out *out = (struct stream_out *)stream;
5130 char mixer_ctl_name[] = "App Type Gain";
5131 struct audio_device *adev = out->dev;
5132 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305133 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005134
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005135 if (!is_valid_volume(left, right)) {
5136 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5137 __func__, left, right);
5138 return -EINVAL;
5139 }
5140
Zhou Song2b8f28f2017-09-11 10:51:38 +08005141 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5142 if (!ctl) {
5143 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5144 __func__, mixer_ctl_name);
5145 return -EINVAL;
5146 }
5147
5148 set_values[0] = 0; //0: Rx Session 1:Tx Session
5149 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305150 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5151 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005152
5153 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5154 return 0;
5155}
5156
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305157static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5158 float right)
5159{
5160 struct stream_out *out = (struct stream_out *)stream;
5161 /* Volume control for pcm playback */
5162 if (left != right) {
5163 return -EINVAL;
5164 } else {
5165 char mixer_ctl_name[128];
5166 struct audio_device *adev = out->dev;
5167 struct mixer_ctl *ctl;
5168 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5169 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5170 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5171 if (!ctl) {
5172 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5173 return -EINVAL;
5174 }
5175
5176 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5177 int ret = mixer_ctl_set_value(ctl, 0, volume);
5178 if (ret < 0) {
5179 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5180 return -EINVAL;
5181 }
5182
5183 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5184
5185 return 0;
5186 }
5187}
5188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189static int out_set_volume(struct audio_stream_out *stream, float left,
5190 float right)
5191{
Eric Laurenta9024de2013-04-04 09:19:12 -07005192 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005193 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305194 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005195
Arun Mirpuri5d170872019-03-26 13:21:31 -07005196 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005197 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5198 /* only take left channel into account: the API is for stereo anyway */
5199 out->muted = (left == 0.0f);
5200 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005201 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305202 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005203 /*
5204 * Set mute or umute on HDMI passthrough stream.
5205 * Only take left channel into account.
5206 * Mute is 0 and unmute 1
5207 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305208 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305209 } else if (out->format == AUDIO_FORMAT_DSD){
5210 char mixer_ctl_name[128] = "DSD Volume";
5211 struct audio_device *adev = out->dev;
5212 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5213
5214 if (!ctl) {
5215 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5216 __func__, mixer_ctl_name);
5217 return -EINVAL;
5218 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305219 volume[0] = (long)(AmpToDb(left));
5220 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305221 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5222 return 0;
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005223 } else if ((out->devices & AUDIO_DEVICE_OUT_BUS) &&
5224 (audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) ==
5225 SND_DEVICE_OUT_BUS_MEDIA)) {
5226 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5227 struct listnode *node = NULL;
5228 list_for_each(node, &adev->active_outputs_list) {
5229 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5230 streams_output_ctxt_t,
5231 list);
5232 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5233 out->volume_l = out_ctxt->output->volume_l;
5234 out->volume_r = out_ctxt->output->volume_r;
5235 }
5236 }
5237 if (!out->a2dp_compress_mute) {
5238 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5239 }
5240 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005241 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305242 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005243 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305244 if (!out->a2dp_compress_mute)
5245 ret = out_set_compr_volume(stream, left, right);
5246 out->volume_l = left;
5247 out->volume_r = right;
5248 pthread_mutex_unlock(&out->compr_mute_lock);
5249 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005250 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005251 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005252 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5253 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5254 if (!out->standby) {
5255 audio_extn_utils_send_app_type_gain(out->dev,
5256 out->app_type_cfg.app_type,
5257 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005258 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005259 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005260 out->volume_l = left;
5261 out->volume_r = right;
5262 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005263 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5264 ALOGV("%s: MMAP set volume called", __func__);
5265 if (!out->standby)
5266 ret = out_set_mmap_volume(stream, left, right);
5267 out->volume_l = left;
5268 out->volume_r = right;
5269 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305270 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305271 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5272 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305273 /* Volume control for pcm playback */
5274 if (!out->standby)
5275 ret = out_set_pcm_volume(stream, left, right);
5276 else
5277 out->apply_volume = true;
5278
5279 out->volume_l = left;
5280 out->volume_r = right;
5281 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005282 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5283 ALOGV("%s: bus device set volume called", __func__);
5284 if (!out->standby)
5285 ret = out_set_pcm_volume(stream, left, right);
5286 out->volume_l = left;
5287 out->volume_r = right;
5288 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005289 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291 return -ENOSYS;
5292}
5293
Zhou Songc9672822017-08-16 16:01:39 +08005294static void update_frames_written(struct stream_out *out, size_t bytes)
5295{
5296 size_t bpf = 0;
5297
5298 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5299 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5300 bpf = 1;
5301 else if (!is_offload_usecase(out->usecase))
5302 bpf = audio_bytes_per_sample(out->format) *
5303 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005304
5305 pthread_mutex_lock(&out->position_query_lock);
5306 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005307 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005308 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5309 }
5310 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005311}
5312
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005313int split_and_write_audio_haptic_data(struct stream_out *out,
5314 const void *buffer, size_t bytes_to_write)
5315{
5316 struct audio_device *adev = out->dev;
5317
5318 int ret = 0;
5319 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5320 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5321 size_t frame_size = channel_count * bytes_per_sample;
5322 size_t frame_count = bytes_to_write / frame_size;
5323
5324 bool force_haptic_path =
5325 property_get_bool("vendor.audio.test_haptic", false);
5326
5327 // extract Haptics data from Audio buffer
5328 bool alloc_haptic_buffer = false;
5329 int haptic_channel_count = adev->haptics_config.channels;
5330 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5331 size_t audio_frame_size = frame_size - haptic_frame_size;
5332 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5333
5334 if (adev->haptic_buffer == NULL) {
5335 alloc_haptic_buffer = true;
5336 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5337 free(adev->haptic_buffer);
5338 adev->haptic_buffer_size = 0;
5339 alloc_haptic_buffer = true;
5340 }
5341
5342 if (alloc_haptic_buffer) {
5343 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005344 if(adev->haptic_buffer == NULL) {
5345 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5346 return -ENOMEM;
5347 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005348 adev->haptic_buffer_size = total_haptic_buffer_size;
5349 }
5350
5351 size_t src_index = 0, aud_index = 0, hap_index = 0;
5352 uint8_t *audio_buffer = (uint8_t *)buffer;
5353 uint8_t *haptic_buffer = adev->haptic_buffer;
5354
5355 // This is required for testing only. This works for stereo data only.
5356 // One channel is fed to audio stream and other to haptic stream for testing.
5357 if (force_haptic_path)
5358 audio_frame_size = haptic_frame_size = bytes_per_sample;
5359
5360 for (size_t i = 0; i < frame_count; i++) {
5361 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5362 audio_frame_size);
5363 aud_index += audio_frame_size;
5364 src_index += audio_frame_size;
5365
5366 if (adev->haptic_pcm)
5367 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5368 haptic_frame_size);
5369 hap_index += haptic_frame_size;
5370 src_index += haptic_frame_size;
5371
5372 // This is required for testing only.
5373 // Discard haptic channel data.
5374 if (force_haptic_path)
5375 src_index += haptic_frame_size;
5376 }
5377
5378 // write to audio pipeline
5379 ret = pcm_write(out->pcm, (void *)audio_buffer,
5380 frame_count * audio_frame_size);
5381
5382 // write to haptics pipeline
5383 if (adev->haptic_pcm)
5384 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5385 frame_count * haptic_frame_size);
5386
5387 return ret;
5388}
5389
Aalique Grahame22e49102018-12-18 14:23:57 -08005390#ifdef NO_AUDIO_OUT
5391static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5392 const void *buffer __unused, size_t bytes)
5393{
5394 struct stream_out *out = (struct stream_out *)stream;
5395
5396 /* No Output device supported other than BT for playback.
5397 * Sleep for the amount of buffer duration
5398 */
5399 lock_output_stream(out);
5400 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5401 (const struct audio_stream_out *)&out->stream) /
5402 out_get_sample_rate(&out->stream.common));
5403 pthread_mutex_unlock(&out->lock);
5404 return bytes;
5405}
5406#endif
5407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5409 size_t bytes)
5410{
5411 struct stream_out *out = (struct stream_out *)stream;
5412 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005413 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305414 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005415 const size_t frame_size = audio_stream_out_frame_size(stream);
5416 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305417 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005418
Haynes Mathew George380745d2017-10-04 15:27:45 -07005419 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005420 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305421
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305422 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005423
Dhananjay Kumarac341582017-02-23 23:42:25 +05305424 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305425 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305426 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5427 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005428 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305429 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305430 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305431 ALOGD(" %s: sound card is not active/SSR state", __func__);
5432 ret= -EIO;
5433 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305434 }
5435 }
5436
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305437 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305438 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305439 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305440 goto exit;
5441 }
5442
Haynes Mathew George16081042017-05-31 17:16:49 -07005443 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5444 ret = -EINVAL;
5445 goto exit;
5446 }
5447
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305448 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5449 !out->is_iec61937_info_available) {
5450
5451 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5452 out->is_iec61937_info_available = true;
5453 } else if (audio_extn_passthru_is_enabled()) {
5454 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305455 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305456
5457 if((out->format == AUDIO_FORMAT_DTS) ||
5458 (out->format == AUDIO_FORMAT_DTS_HD)) {
5459 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5460 buffer, bytes);
5461 if (ret) {
5462 if (ret != -ENOSYS) {
5463 out->is_iec61937_info_available = false;
5464 ALOGD("iec61937 transmission info not yet updated retry");
5465 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305466 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305467 /* if stream has started and after that there is
5468 * stream config change (iec transmission config)
5469 * then trigger select_device to update backend configuration.
5470 */
5471 out->stream_config_changed = true;
5472 pthread_mutex_lock(&adev->lock);
5473 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305474 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005475 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305476 ret = -EINVAL;
5477 goto exit;
5478 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305479 pthread_mutex_unlock(&adev->lock);
5480 out->stream_config_changed = false;
5481 out->is_iec61937_info_available = true;
5482 }
5483 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305484
Garmond Leung317cbf12017-09-13 16:20:50 -07005485 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305486 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5487 (out->is_iec61937_info_available == true)) {
5488 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5489 ret = -EINVAL;
5490 goto exit;
5491 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305492 }
5493 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305494
5495 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005496 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005497 if (!(out->devices &
5498 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305499 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305500 ret = -EIO;
5501 goto exit;
5502 }
5503 }
5504 }
5505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005506 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005507 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005508 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005509 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5510 ret = voice_extn_compress_voip_start_output_stream(out);
5511 else
5512 ret = start_output_stream(out);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05305513
5514 if (ret == 0)
5515 amplifier_output_stream_start(stream,
5516 is_offload_usecase(out->usecase));
5517
Eric Laurent150dbfe2013-02-27 14:31:02 -08005518 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005519 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005520 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005521 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005522 goto exit;
5523 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305524 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005525 if (last_known_cal_step != -1) {
5526 ALOGD("%s: retry previous failed cal level set", __func__);
5527 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305528 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005529 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305530
5531 if ((out->is_iec61937_info_available == true) &&
5532 (audio_extn_passthru_is_passthrough_stream(out))&&
5533 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5534 ret = -EINVAL;
5535 goto exit;
5536 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305537 if (out->set_dual_mono)
5538 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540
Ashish Jain81eb2a82015-05-13 10:52:34 +05305541 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005542 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305543 adev->is_channel_status_set = true;
5544 }
5545
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305546 if ((adev->use_old_pspd_mix_ctrl == true) &&
5547 (out->pspd_coeff_sent == false)) {
5548 /*
5549 * Need to resend pspd coefficients after stream started for
5550 * older kernel version as it does not save the coefficients
5551 * and also stream has to be started for coeff to apply.
5552 */
5553 usecase = get_usecase_from_list(adev, out->usecase);
5554 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305555 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305556 out->pspd_coeff_sent = true;
5557 }
5558 }
5559
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005560 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005561 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005562 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005563 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005564 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5565 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305566 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5567 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangebfa0502019-07-18 17:24:21 +08005568 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305569 out->send_next_track_params = false;
5570 out->is_compr_metadata_avail = false;
5571 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005572 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305573 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305574 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005575
Ashish Jain83a6cc22016-06-28 14:34:17 +05305576 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305577 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305578 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305579 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005580 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305581 return -EINVAL;
5582 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305583 audio_format_t dst_format = out->hal_op_format;
5584 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305585
Dieter Luecking5d57def2018-09-07 14:23:37 +02005586 /* prevent division-by-zero */
5587 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5588 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5589 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5590 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305591 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005592 ATRACE_END();
5593 return -EINVAL;
5594 }
5595
Ashish Jainf1eaa582016-05-23 20:54:24 +05305596 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5597 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5598
Ashish Jain83a6cc22016-06-28 14:34:17 +05305599 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305600 dst_format,
5601 buffer,
5602 src_format,
5603 frames);
5604
Ashish Jain83a6cc22016-06-28 14:34:17 +05305605 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305606 bytes_to_write);
5607
5608 /*Convert written bytes in audio flinger format*/
5609 if (ret > 0)
5610 ret = ((ret * format_to_bitwidth_table[out->format]) /
5611 format_to_bitwidth_table[dst_format]);
5612 }
5613 } else
5614 ret = compress_write(out->compr, buffer, bytes);
5615
Zhou Songc9672822017-08-16 16:01:39 +08005616 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5617 update_frames_written(out, bytes);
5618
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305619 if (ret < 0)
5620 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005621 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305622 /*msg to cb thread only if non blocking write is enabled*/
5623 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305624 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005625 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305626 } else if (-ENETRESET == ret) {
5627 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305628 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305629 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305630 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005631 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305632 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005633 }
Ashish Jain5106d362016-05-11 19:23:33 +05305634
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305635 /* Call compr start only when non-zero bytes of data is there to be rendered */
5636 if (!out->playback_started && ret > 0) {
5637 int status = compress_start(out->compr);
5638 if (status < 0) {
5639 ret = status;
5640 ALOGE("%s: compr start failed with err %d", __func__, errno);
5641 goto exit;
5642 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005643 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005644 out->playback_started = 1;
5645 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005646
5647 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5648 popcount(out->channel_mask),
5649 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005650 }
5651 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005652 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005653 return ret;
5654 } else {
5655 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005656 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005657 if (out->muted)
5658 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005659 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5660 __func__, frames, frame_size, bytes_to_write);
5661
Aalique Grahame22e49102018-12-18 14:23:57 -08005662 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005663 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5664 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5665 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005666 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5667 int16_t *src = (int16_t *)buffer;
5668 int16_t *dst = (int16_t *)buffer;
5669
5670 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5671 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005672 "out_write called for %s use case with wrong properties",
5673 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005674
5675 /*
5676 * FIXME: this can be removed once audio flinger mixer supports
5677 * mono output
5678 */
5679
5680 /*
5681 * Code below goes over each frame in the buffer and adds both
5682 * L and R samples and then divides by 2 to convert to mono
5683 */
5684 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5685 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5686 }
5687 bytes_to_write /= 2;
5688 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005689
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305690 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005691
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005692 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005693
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005694 if (out->config.rate)
5695 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5696 out->config.rate;
5697
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005698 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005699 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5700
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005701 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005702 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005703 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305704 out->convert_buffer != NULL) {
5705
5706 memcpy_by_audio_format(out->convert_buffer,
5707 out->hal_op_format,
5708 buffer,
5709 out->hal_ip_format,
5710 out->config.period_size * out->config.channels);
5711
5712 ret = pcm_write(out->pcm, out->convert_buffer,
5713 (out->config.period_size *
5714 out->config.channels *
5715 format_to_bitwidth_table[out->hal_op_format]));
5716 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305717 /*
5718 * To avoid underrun in DSP when the application is not pumping
5719 * data at required rate, check for the no. of bytes and ignore
5720 * pcm_write if it is less than actual buffer size.
5721 * It is a work around to a change in compress VOIP driver.
5722 */
5723 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5724 bytes < (out->config.period_size * out->config.channels *
5725 audio_bytes_per_sample(out->format))) {
5726 size_t voip_buf_size =
5727 out->config.period_size * out->config.channels *
5728 audio_bytes_per_sample(out->format);
5729 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5730 __func__, bytes, voip_buf_size);
5731 usleep(((uint64_t)voip_buf_size - bytes) *
5732 1000000 / audio_stream_out_frame_size(stream) /
5733 out_get_sample_rate(&out->stream.common));
5734 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005735 } else {
5736 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5737 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5738 else
5739 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5740 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305741 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005742
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005743 release_out_focus(out);
5744
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305745 if (ret < 0)
5746 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005747 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305748 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750 }
5751
5752exit:
Zhou Songc9672822017-08-16 16:01:39 +08005753 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305754 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305755 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305756 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757 pthread_mutex_unlock(&out->lock);
5758
5759 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005760 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005761 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305762 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305763 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305764 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305765 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305766 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305767 out->standby = true;
5768 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305769 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005770 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5771 /* prevent division-by-zero */
5772 uint32_t stream_size = audio_stream_out_frame_size(stream);
5773 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005774
Dieter Luecking5d57def2018-09-07 14:23:37 +02005775 if ((stream_size == 0) || (srate == 0)) {
5776 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5777 ATRACE_END();
5778 return -EINVAL;
5779 }
5780 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5781 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005782 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305783 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005784 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005785 return ret;
5786 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005787 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005788 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005789 return bytes;
5790}
5791
5792static int out_get_render_position(const struct audio_stream_out *stream,
5793 uint32_t *dsp_frames)
5794{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005795 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005796
5797 if (dsp_frames == NULL)
5798 return -EINVAL;
5799
5800 *dsp_frames = 0;
5801 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005802 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305803
5804 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5805 * this operation and adev_close_output_stream(where out gets reset).
5806 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305807 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005808 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305809 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005810 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305811 return 0;
5812 }
5813
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005814 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305815 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305816 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005817 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305818 if (ret < 0)
5819 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005820 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305821 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005822 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305823 if (-ENETRESET == ret) {
5824 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305825 out->card_status = CARD_STATUS_OFFLINE;
5826 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305827 } else if(ret < 0) {
5828 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305829 ret = -EINVAL;
5830 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305831 /*
5832 * Handle corner case where compress session is closed during SSR
5833 * and timestamp is queried
5834 */
5835 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305836 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305837 } else if (out->prev_card_status_offline) {
5838 ALOGE("ERROR: previously sound card was offline,return error");
5839 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305840 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305841 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005842 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305843 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305844 pthread_mutex_unlock(&out->lock);
5845 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005846 } else if (audio_is_linear_pcm(out->format)) {
5847 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005848 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005849 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005850 } else
5851 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005852}
5853
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005854static int out_add_audio_effect(const struct audio_stream *stream __unused,
5855 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005856{
5857 return 0;
5858}
5859
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005860static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5861 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005862{
5863 return 0;
5864}
5865
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005866static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5867 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305869 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005870}
5871
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005872static int out_get_presentation_position(const struct audio_stream_out *stream,
5873 uint64_t *frames, struct timespec *timestamp)
5874{
5875 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305876 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005877 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005878
Ashish Jain5106d362016-05-11 19:23:33 +05305879 /* below piece of code is not guarded against any lock because audioFliner serializes
5880 * this operation and adev_close_output_stream( where out gets reset).
5881 */
5882 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305883 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005884 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305885 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5886 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5887 return 0;
5888 }
5889
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005890 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005891
Ashish Jain5106d362016-05-11 19:23:33 +05305892 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5893 ret = compress_get_tstamp(out->compr, &dsp_frames,
5894 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005895 // Adjustment accounts for A2dp encoder latency with offload usecases
5896 // Note: Encoder latency is returned in ms.
5897 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5898 unsigned long offset =
5899 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5900 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5901 }
Ashish Jain5106d362016-05-11 19:23:33 +05305902 ALOGVV("%s rendered frames %ld sample_rate %d",
5903 __func__, dsp_frames, out->sample_rate);
5904 *frames = dsp_frames;
5905 if (ret < 0)
5906 ret = -errno;
5907 if (-ENETRESET == ret) {
5908 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305909 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305910 ret = -EINVAL;
5911 } else
5912 ret = 0;
5913 /* this is the best we can do */
5914 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005915 } else {
5916 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005917 unsigned int avail;
5918 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5919 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5920 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5921 // This adjustment accounts for buffering after app processor.
5922 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005923 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005924 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005925
Weiyin Jiangd4633762018-03-16 12:05:03 +08005926 // Adjustment accounts for A2dp encoder latency with non offload usecases
5927 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5928 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5929 signed_frames -=
5930 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5931 }
5932
5933 // It would be unusual for this value to be negative, but check just in case ...
5934 if (signed_frames >= 0) {
5935 *frames = signed_frames;
5936 ret = 0;
5937 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005938 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305939 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305940 *frames = out->written;
5941 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305942 if (is_offload_usecase(out->usecase))
5943 ret = -EINVAL;
5944 else
5945 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005946 }
5947 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005948 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005949 return ret;
5950}
5951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005952static int out_set_callback(struct audio_stream_out *stream,
5953 stream_callback_t callback, void *cookie)
5954{
5955 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005956 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005957
5958 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005959 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005960 out->client_callback = callback;
5961 out->client_cookie = cookie;
5962 if (out->adsp_hdlr_stream_handle) {
5963 ret = audio_extn_adsp_hdlr_stream_set_callback(
5964 out->adsp_hdlr_stream_handle,
5965 callback,
5966 cookie);
5967 if (ret)
5968 ALOGW("%s:adsp hdlr callback registration failed %d",
5969 __func__, ret);
5970 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005971 pthread_mutex_unlock(&out->lock);
5972 return 0;
5973}
5974
5975static int out_pause(struct audio_stream_out* stream)
5976{
5977 struct stream_out *out = (struct stream_out *)stream;
5978 int status = -ENOSYS;
5979 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005980 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005981 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005982 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005983 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305984 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305985 status = compress_pause(out->compr);
5986
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005987 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005988
Mingming Yin21854652016-04-13 11:54:02 -07005989 if (audio_extn_passthru_is_active()) {
5990 ALOGV("offload use case, pause passthru");
5991 audio_extn_passthru_on_pause(out);
5992 }
5993
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305994 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005995 audio_extn_dts_notify_playback_state(out->usecase, 0,
5996 out->sample_rate, popcount(out->channel_mask),
5997 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005998 }
5999 pthread_mutex_unlock(&out->lock);
6000 }
6001 return status;
6002}
6003
6004static int out_resume(struct audio_stream_out* stream)
6005{
6006 struct stream_out *out = (struct stream_out *)stream;
6007 int status = -ENOSYS;
6008 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006009 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006010 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006011 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006012 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306014 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306015 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006016 }
6017 if (!status) {
6018 out->offload_state = OFFLOAD_STATE_PLAYING;
6019 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306020 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006021 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6022 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006023 }
6024 pthread_mutex_unlock(&out->lock);
6025 }
6026 return status;
6027}
6028
6029static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6030{
6031 struct stream_out *out = (struct stream_out *)stream;
6032 int status = -ENOSYS;
6033 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006034 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006035 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006036 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6037 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6038 else
6039 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6040 pthread_mutex_unlock(&out->lock);
6041 }
6042 return status;
6043}
6044
6045static int out_flush(struct audio_stream_out* stream)
6046{
6047 struct stream_out *out = (struct stream_out *)stream;
6048 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006049 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006050 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006051 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006052 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6053 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006054 } else {
6055 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6056 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006057 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006058 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006059 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006060 return 0;
6061 }
6062 return -ENOSYS;
6063}
6064
Haynes Mathew George16081042017-05-31 17:16:49 -07006065static int out_stop(const struct audio_stream_out* stream)
6066{
6067 struct stream_out *out = (struct stream_out *)stream;
6068 struct audio_device *adev = out->dev;
6069 int ret = -ENOSYS;
6070
6071 ALOGV("%s", __func__);
6072 pthread_mutex_lock(&adev->lock);
6073 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6074 out->playback_started && out->pcm != NULL) {
6075 pcm_stop(out->pcm);
6076 ret = stop_output_stream(out);
6077 out->playback_started = false;
6078 }
6079 pthread_mutex_unlock(&adev->lock);
6080 return ret;
6081}
6082
6083static int out_start(const struct audio_stream_out* stream)
6084{
6085 struct stream_out *out = (struct stream_out *)stream;
6086 struct audio_device *adev = out->dev;
6087 int ret = -ENOSYS;
6088
6089 ALOGV("%s", __func__);
6090 pthread_mutex_lock(&adev->lock);
6091 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6092 !out->playback_started && out->pcm != NULL) {
6093 ret = start_output_stream(out);
6094 if (ret == 0) {
6095 out->playback_started = true;
6096 }
6097 }
6098 pthread_mutex_unlock(&adev->lock);
6099 return ret;
6100}
6101
6102/*
6103 * Modify config->period_count based on min_size_frames
6104 */
6105static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6106{
6107 int periodCountRequested = (min_size_frames + config->period_size - 1)
6108 / config->period_size;
6109 int periodCount = MMAP_PERIOD_COUNT_MIN;
6110
6111 ALOGV("%s original config.period_size = %d config.period_count = %d",
6112 __func__, config->period_size, config->period_count);
6113
6114 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6115 periodCount *= 2;
6116 }
6117 config->period_count = periodCount;
6118
6119 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6120}
6121
Phil Burkfe17efd2019-03-25 10:23:35 -07006122// Read offset for the positional timestamp from a persistent vendor property.
6123// This is to workaround apparent inaccuracies in the timing information that
6124// is used by the AAudio timing model. The inaccuracies can cause glitches.
6125static int64_t get_mmap_out_time_offset() {
6126 const int32_t kDefaultOffsetMicros = 0;
6127 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006128 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006129 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6130 return mmap_time_offset_micros * (int64_t)1000;
6131}
6132
Haynes Mathew George16081042017-05-31 17:16:49 -07006133static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6134 int32_t min_size_frames,
6135 struct audio_mmap_buffer_info *info)
6136{
6137 struct stream_out *out = (struct stream_out *)stream;
6138 struct audio_device *adev = out->dev;
6139 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006140 unsigned int offset1 = 0;
6141 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006142 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006143 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006144 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006145
Arun Mirpuri5d170872019-03-26 13:21:31 -07006146 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306147 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006148 pthread_mutex_lock(&adev->lock);
6149
Sharad Sanglec6f32552018-05-04 16:15:38 +05306150 if (CARD_STATUS_OFFLINE == out->card_status ||
6151 CARD_STATUS_OFFLINE == adev->card_status) {
6152 ALOGW("out->card_status or adev->card_status offline, try again");
6153 ret = -EIO;
6154 goto exit;
6155 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006156 if (info == NULL || min_size_frames == 0) {
6157 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6158 ret = -EINVAL;
6159 goto exit;
6160 }
6161 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6162 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6163 ret = -ENOSYS;
6164 goto exit;
6165 }
6166 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6167 if (out->pcm_device_id < 0) {
6168 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6169 __func__, out->pcm_device_id, out->usecase);
6170 ret = -EINVAL;
6171 goto exit;
6172 }
6173
6174 adjust_mmap_period_count(&out->config, min_size_frames);
6175
Arun Mirpuri5d170872019-03-26 13:21:31 -07006176 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006177 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6178 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6179 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306180 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306181 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6182 out->card_status = CARD_STATUS_OFFLINE;
6183 adev->card_status = CARD_STATUS_OFFLINE;
6184 ret = -EIO;
6185 goto exit;
6186 }
6187
Haynes Mathew George16081042017-05-31 17:16:49 -07006188 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6189 step = "open";
6190 ret = -ENODEV;
6191 goto exit;
6192 }
6193 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6194 if (ret < 0) {
6195 step = "begin";
6196 goto exit;
6197 }
6198 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006199 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006200 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006201 ret = platform_get_mmap_data_fd(adev->platform,
6202 out->pcm_device_id, 0 /*playback*/,
6203 &info->shared_memory_fd,
6204 &mmap_size);
6205 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006206 // Fall back to non exclusive mode
6207 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6208 } else {
6209 if (mmap_size < buffer_size) {
6210 step = "mmap";
6211 goto exit;
6212 }
6213 // FIXME: indicate exclusive mode support by returning a negative buffer size
6214 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006215 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006216 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006217 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006218
6219 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6220 if (ret < 0) {
6221 step = "commit";
6222 goto exit;
6223 }
6224
Phil Burkfe17efd2019-03-25 10:23:35 -07006225 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6226
Haynes Mathew George16081042017-05-31 17:16:49 -07006227 out->standby = false;
6228 ret = 0;
6229
Arun Mirpuri5d170872019-03-26 13:21:31 -07006230 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006231 __func__, info->shared_memory_address, info->buffer_size_frames);
6232
6233exit:
6234 if (ret != 0) {
6235 if (out->pcm == NULL) {
6236 ALOGE("%s: %s - %d", __func__, step, ret);
6237 } else {
6238 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6239 pcm_close(out->pcm);
6240 out->pcm = NULL;
6241 }
6242 }
6243 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306244 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006245 return ret;
6246}
6247
6248static int out_get_mmap_position(const struct audio_stream_out *stream,
6249 struct audio_mmap_position *position)
6250{
6251 struct stream_out *out = (struct stream_out *)stream;
6252 ALOGVV("%s", __func__);
6253 if (position == NULL) {
6254 return -EINVAL;
6255 }
6256 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006257 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006258 return -ENOSYS;
6259 }
6260 if (out->pcm == NULL) {
6261 return -ENOSYS;
6262 }
6263
6264 struct timespec ts = { 0, 0 };
6265 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6266 if (ret < 0) {
6267 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6268 return ret;
6269 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006270 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6271 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006272 return 0;
6273}
6274
6275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006276/** audio_stream_in implementation **/
6277static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6278{
6279 struct stream_in *in = (struct stream_in *)stream;
6280
6281 return in->config.rate;
6282}
6283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006284static int in_set_sample_rate(struct audio_stream *stream __unused,
6285 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006286{
6287 return -ENOSYS;
6288}
6289
6290static size_t in_get_buffer_size(const struct audio_stream *stream)
6291{
6292 struct stream_in *in = (struct stream_in *)stream;
6293
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006294 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6295 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006296 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6297 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306298 else if(audio_extn_cin_attached_usecase(in->usecase))
6299 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006300
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006301 return in->config.period_size * in->af_period_multiplier *
6302 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006303}
6304
6305static uint32_t in_get_channels(const struct audio_stream *stream)
6306{
6307 struct stream_in *in = (struct stream_in *)stream;
6308
6309 return in->channel_mask;
6310}
6311
6312static audio_format_t in_get_format(const struct audio_stream *stream)
6313{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006314 struct stream_in *in = (struct stream_in *)stream;
6315
6316 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006317}
6318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006319static int in_set_format(struct audio_stream *stream __unused,
6320 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006321{
6322 return -ENOSYS;
6323}
6324
6325static int in_standby(struct audio_stream *stream)
6326{
6327 struct stream_in *in = (struct stream_in *)stream;
6328 struct audio_device *adev = in->dev;
6329 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306330 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6331 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006332 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306333
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006334 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006335 if (!in->standby && in->is_st_session) {
6336 ALOGD("%s: sound trigger pcm stop lab", __func__);
6337 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006338 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006339 in->standby = 1;
6340 }
6341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006343 if (adev->adm_deregister_stream)
6344 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6345
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006346 pthread_mutex_lock(&adev->lock);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05306347
6348 amplifier_input_stream_standby((struct audio_stream_in *) stream);
6349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006350 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006351 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006352 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006353 voice_extn_compress_voip_close_input_stream(stream);
6354 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006355 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6356 do_stop = in->capture_started;
6357 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006358 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306359 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306360 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006361 }
6362
Arun Mirpuri5d170872019-03-26 13:21:31 -07006363 if (in->pcm) {
6364 ATRACE_BEGIN("pcm_in_close");
6365 pcm_close(in->pcm);
6366 ATRACE_END();
6367 in->pcm = NULL;
6368 }
6369
Carter Hsu2e429db2019-05-14 18:50:52 +08006370 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006371 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006372
6373 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006374 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006375
6376 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6377 adev->num_va_sessions--;
6378
Eric Laurent150dbfe2013-02-27 14:31:02 -08006379 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006380 }
6381 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006382 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006383 return status;
6384}
6385
Aalique Grahame22e49102018-12-18 14:23:57 -08006386static int in_dump(const struct audio_stream *stream,
6387 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006388{
Aalique Grahame22e49102018-12-18 14:23:57 -08006389 struct stream_in *in = (struct stream_in *)stream;
6390
6391 // We try to get the lock for consistency,
6392 // but it isn't necessary for these variables.
6393 // If we're not in standby, we may be blocked on a read.
6394 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6395 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6396 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6397 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6398
6399 if (locked) {
6400 pthread_mutex_unlock(&in->lock);
6401 }
6402
6403 // dump error info
6404 (void)error_log_dump(
6405 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407 return 0;
6408}
6409
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306410static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6411{
6412 if (!stream || !parms)
6413 return;
6414
6415 struct stream_in *in = (struct stream_in *)stream;
6416 struct audio_device *adev = in->dev;
6417
6418 card_status_t status;
6419 int card;
6420 if (parse_snd_card_status(parms, &card, &status) < 0)
6421 return;
6422
6423 pthread_mutex_lock(&adev->lock);
6424 bool valid_cb = (card == adev->snd_card);
6425 pthread_mutex_unlock(&adev->lock);
6426
6427 if (!valid_cb)
6428 return;
6429
6430 lock_input_stream(in);
6431 if (in->card_status != status)
6432 in->card_status = status;
6433 pthread_mutex_unlock(&in->lock);
6434
6435 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6436 use_case_table[in->usecase],
6437 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6438
6439 // a better solution would be to report error back to AF and let
6440 // it put the stream to standby
6441 if (status == CARD_STATUS_OFFLINE)
6442 in_standby(&in->stream.common);
6443
6444 return;
6445}
6446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6448{
6449 struct stream_in *in = (struct stream_in *)stream;
6450 struct audio_device *adev = in->dev;
6451 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006453 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006454
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306455 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006456 parms = str_parms_create_str(kvpairs);
6457
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306458 if (!parms)
6459 goto error;
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05306460
6461 amplifier_in_set_parameters(parms);
6462
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006463 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006464 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006465
6466 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6467 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006468 val = atoi(value);
6469 /* no audio source uses val == 0 */
6470 if ((in->source != val) && (val != 0)) {
6471 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006472 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6473 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6474 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006475 (in->config.rate == 8000 || in->config.rate == 16000 ||
6476 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006477 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006478 err = voice_extn_compress_voip_open_input_stream(in);
6479 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006480 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006481 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006482 }
6483 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006484 }
6485 }
6486
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006487 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6488 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006489 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006490 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6491
6492 // Workaround: If routing to an non existing usb device, fail gracefully
6493 // The routing request will otherwise block during 10 second
6494 int card;
6495 if (audio_is_usb_in_device(val) &&
6496 (card = get_alive_usb_card(parms)) >= 0) {
6497
6498 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6499 ret = -ENOSYS;
6500 } else {
6501
6502 in->device = val;
6503 /* If recording is in progress, change the tx device to new device */
6504 if (!in->standby && !in->is_st_session) {
6505 ALOGV("update input routing change");
6506 // inform adm before actual routing to prevent glitches.
6507 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006508 adev->adm_on_routing_change(adev->adm_data,
6509 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006510 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006511 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6512 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006513 }
6514 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006516 }
6517 }
6518
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306519 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6520 if (err >= 0) {
6521 strlcpy(in->profile, value, sizeof(in->profile));
6522 ALOGV("updating stream profile with value '%s'", in->profile);
6523 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6524 &adev->streams_input_cfg_list,
6525 in->device, in->flags, in->format,
6526 in->sample_rate, in->bit_width,
6527 in->profile, &in->app_type_cfg);
6528 }
6529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006531 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006532
6533 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306534error:
Eric Laurent994a6932013-07-17 11:51:42 -07006535 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006536 return ret;
6537}
6538
6539static char* in_get_parameters(const struct audio_stream *stream,
6540 const char *keys)
6541{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006542 struct stream_in *in = (struct stream_in *)stream;
6543 struct str_parms *query = str_parms_create_str(keys);
6544 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006545 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006546
6547 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006548 if (reply) {
6549 str_parms_destroy(reply);
6550 }
6551 if (query) {
6552 str_parms_destroy(query);
6553 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006554 ALOGE("in_get_parameters: failed to create query or reply");
6555 return NULL;
6556 }
6557
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006558 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006559
6560 voice_extn_in_get_parameters(in, query, reply);
6561
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006562 stream_get_parameter_channels(query, reply,
6563 &in->supported_channel_masks[0]);
6564 stream_get_parameter_formats(query, reply,
6565 &in->supported_formats[0]);
6566 stream_get_parameter_rates(query, reply,
6567 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006568 str = str_parms_to_str(reply);
6569 str_parms_destroy(query);
6570 str_parms_destroy(reply);
6571
6572 ALOGV("%s: exit: returns - %s", __func__, str);
6573 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006574}
6575
Aalique Grahame22e49102018-12-18 14:23:57 -08006576static int in_set_gain(struct audio_stream_in *stream,
6577 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578{
Aalique Grahame22e49102018-12-18 14:23:57 -08006579 struct stream_in *in = (struct stream_in *)stream;
6580 char mixer_ctl_name[128];
6581 struct mixer_ctl *ctl;
6582 int ctl_value;
6583
6584 ALOGV("%s: gain %f", __func__, gain);
6585
6586 if (stream == NULL)
6587 return -EINVAL;
6588
6589 /* in_set_gain() only used to silence MMAP capture for now */
6590 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6591 return -ENOSYS;
6592
6593 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6594
6595 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6596 if (!ctl) {
6597 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6598 __func__, mixer_ctl_name);
6599 return -ENOSYS;
6600 }
6601
6602 if (gain < RECORD_GAIN_MIN)
6603 gain = RECORD_GAIN_MIN;
6604 else if (gain > RECORD_GAIN_MAX)
6605 gain = RECORD_GAIN_MAX;
6606 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6607
6608 mixer_ctl_set_value(ctl, 0, ctl_value);
6609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006610 return 0;
6611}
6612
6613static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6614 size_t bytes)
6615{
6616 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306617
6618 if (in == NULL) {
6619 ALOGE("%s: stream_in ptr is NULL", __func__);
6620 return -EINVAL;
6621 }
6622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006623 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306624 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306625 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006626
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006627 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306628
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006629 if (in->is_st_session) {
6630 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6631 /* Read from sound trigger HAL */
6632 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006633 if (in->standby) {
6634 adev->num_va_sessions++;
6635 in->standby = 0;
6636 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006637 pthread_mutex_unlock(&in->lock);
6638 return bytes;
6639 }
6640
Haynes Mathew George16081042017-05-31 17:16:49 -07006641 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6642 ret = -ENOSYS;
6643 goto exit;
6644 }
6645
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006646 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6647 !in->standby && adev->adm_routing_changed) {
6648 ret = -ENOSYS;
6649 goto exit;
6650 }
6651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006652 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006653 pthread_mutex_lock(&adev->lock);
6654 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6655 ret = voice_extn_compress_voip_start_input_stream(in);
6656 else
6657 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006658 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6659 adev->num_va_sessions++;
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05306660
6661 if (ret == 0)
6662 amplifier_input_stream_start(stream);
6663
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006664 pthread_mutex_unlock(&adev->lock);
6665 if (ret != 0) {
6666 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006667 }
6668 in->standby = 0;
6669 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006670
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306671 /* Avoid read if capture_stopped is set */
6672 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6673 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6674 ret = -EINVAL;
6675 goto exit;
6676 }
6677
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006678 // what's the duration requested by the client?
6679 long ns = 0;
6680
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306681 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006682 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6683 in->config.rate;
6684
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006685 ret = request_in_focus(in, ns);
6686 if (ret != 0)
6687 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006688 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006689
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306690 if (audio_extn_cin_attached_usecase(in->usecase)) {
6691 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6692 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306693 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006694 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306695 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006696 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006697 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006698 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006699 } else if (audio_extn_ffv_get_stream() == in) {
6700 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306701 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006702 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306703 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6704 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6705 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6706 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306707 ret = -EINVAL;
6708 goto exit;
6709 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306710 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306711 ret = -errno;
6712 }
6713 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306714 /* bytes read is always set to bytes for non compress usecases */
6715 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006716 }
6717
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006718 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006720 /*
Quinn Malef6050362019-01-30 15:55:40 -08006721 * Instead of writing zeroes here, we could trust the hardware to always
6722 * provide zeroes when muted. This is also muted with voice recognition
6723 * usecases so that other clients do not have access to voice recognition
6724 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006725 */
Quinn Malef6050362019-01-30 15:55:40 -08006726 if ((ret == 0 && voice_get_mic_mute(adev) &&
6727 !voice_is_in_call_rec_stream(in) &&
6728 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6729 (adev->num_va_sessions &&
6730 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6731 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6732 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006733 memset(buffer, 0, bytes);
6734
6735exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306736 frame_size = audio_stream_in_frame_size(stream);
6737 if (frame_size > 0)
6738 in->frames_read += bytes_read/frame_size;
6739
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006740 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306741 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006742 pthread_mutex_unlock(&in->lock);
6743
6744 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306745 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306746 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306747 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306748 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306749 in->standby = true;
6750 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306751 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6752 bytes_read = bytes;
6753 memset(buffer, 0, bytes);
6754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006755 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006756 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6757 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006758 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306759 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306760 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006761 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306762 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006763}
6764
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006765static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006766{
6767 return 0;
6768}
6769
Aalique Grahame22e49102018-12-18 14:23:57 -08006770static int in_get_capture_position(const struct audio_stream_in *stream,
6771 int64_t *frames, int64_t *time)
6772{
6773 if (stream == NULL || frames == NULL || time == NULL) {
6774 return -EINVAL;
6775 }
6776 struct stream_in *in = (struct stream_in *)stream;
6777 int ret = -ENOSYS;
6778
6779 lock_input_stream(in);
6780 // note: ST sessions do not close the alsa pcm driver synchronously
6781 // on standby. Therefore, we may return an error even though the
6782 // pcm stream is still opened.
6783 if (in->standby) {
6784 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6785 "%s stream in standby but pcm not NULL for non ST session", __func__);
6786 goto exit;
6787 }
6788 if (in->pcm) {
6789 struct timespec timestamp;
6790 unsigned int avail;
6791 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6792 *frames = in->frames_read + avail;
6793 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6794 ret = 0;
6795 }
6796 }
6797exit:
6798 pthread_mutex_unlock(&in->lock);
6799 return ret;
6800}
6801
Carter Hsu2e429db2019-05-14 18:50:52 +08006802static int in_update_effect_list(bool add, effect_handle_t effect,
6803 struct listnode *head)
6804{
6805 struct listnode *node;
6806 struct in_effect_list *elist = NULL;
6807 struct in_effect_list *target = NULL;
6808 int ret = 0;
6809
6810 if (!head)
6811 return ret;
6812
6813 list_for_each(node, head) {
6814 elist = node_to_item(node, struct in_effect_list, list);
6815 if (elist->handle == effect) {
6816 target = elist;
6817 break;
6818 }
6819 }
6820
6821 if (add) {
6822 if (target) {
6823 ALOGD("effect %p already exist", effect);
6824 return ret;
6825 }
6826
6827 target = (struct in_effect_list *)
6828 calloc(1, sizeof(struct in_effect_list));
6829
6830 if (!target) {
6831 ALOGE("%s:fail to allocate memory", __func__);
6832 return -ENOMEM;
6833 }
6834
6835 target->handle = effect;
6836 list_add_tail(head, &target->list);
6837 } else {
6838 if (target) {
6839 list_remove(&target->list);
6840 free(target);
6841 }
6842 }
6843
6844 return ret;
6845}
6846
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006847static int add_remove_audio_effect(const struct audio_stream *stream,
6848 effect_handle_t effect,
6849 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006850{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006851 struct stream_in *in = (struct stream_in *)stream;
6852 int status = 0;
6853 effect_descriptor_t desc;
6854
6855 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006856 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6857
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006858 if (status != 0)
6859 return status;
6860
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006861 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006862 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006863 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006864 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6865 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006866 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006867
6868 in_update_effect_list(enable, effect, &in->aec_list);
6869 enable = !list_empty(&in->aec_list);
6870 if (enable == in->enable_aec)
6871 goto exit;
6872
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006873 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006874 ALOGD("AEC enable %d", enable);
6875
Aalique Grahame22e49102018-12-18 14:23:57 -08006876 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6877 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6878 in->dev->enable_voicerx = enable;
6879 struct audio_usecase *usecase;
6880 struct listnode *node;
6881 list_for_each(node, &in->dev->usecase_list) {
6882 usecase = node_to_item(node, struct audio_usecase, list);
6883 if (usecase->type == PCM_PLAYBACK)
6884 select_devices(in->dev, usecase->id);
6885 }
6886 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006887 if (!in->standby) {
6888 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6889 select_devices(in->dev, in->usecase);
6890 }
6891
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006892 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006893 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6894
6895 in_update_effect_list(enable, effect, &in->ns_list);
6896 enable = !list_empty(&in->ns_list);
6897 if (enable == in->enable_ns)
6898 goto exit;
6899
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006900 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006901 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006902 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006903 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6904 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006905 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6906 select_devices(in->dev, in->usecase);
6907 } else
6908 select_devices(in->dev, in->usecase);
6909 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006910 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006911exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006912 pthread_mutex_unlock(&in->dev->lock);
6913 pthread_mutex_unlock(&in->lock);
6914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006915 return 0;
6916}
6917
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006918static int in_add_audio_effect(const struct audio_stream *stream,
6919 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006920{
Eric Laurent994a6932013-07-17 11:51:42 -07006921 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006922 return add_remove_audio_effect(stream, effect, true);
6923}
6924
6925static int in_remove_audio_effect(const struct audio_stream *stream,
6926 effect_handle_t effect)
6927{
Eric Laurent994a6932013-07-17 11:51:42 -07006928 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006929 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006930}
6931
Derek Chenf939fb72018-11-13 13:34:41 -08006932streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6933 audio_io_handle_t input)
6934{
6935 struct listnode *node;
6936
6937 list_for_each(node, &dev->active_inputs_list) {
6938 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6939 streams_input_ctxt_t,
6940 list);
6941 if (in_ctxt->input->capture_handle == input) {
6942 return in_ctxt;
6943 }
6944 }
6945 return NULL;
6946}
6947
6948streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6949 audio_io_handle_t output)
6950{
6951 struct listnode *node;
6952
6953 list_for_each(node, &dev->active_outputs_list) {
6954 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6955 streams_output_ctxt_t,
6956 list);
6957 if (out_ctxt->output->handle == output) {
6958 return out_ctxt;
6959 }
6960 }
6961 return NULL;
6962}
6963
Haynes Mathew George16081042017-05-31 17:16:49 -07006964static int in_stop(const struct audio_stream_in* stream)
6965{
6966 struct stream_in *in = (struct stream_in *)stream;
6967 struct audio_device *adev = in->dev;
6968
6969 int ret = -ENOSYS;
6970 ALOGV("%s", __func__);
6971 pthread_mutex_lock(&adev->lock);
6972 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6973 in->capture_started && in->pcm != NULL) {
6974 pcm_stop(in->pcm);
6975 ret = stop_input_stream(in);
6976 in->capture_started = false;
6977 }
6978 pthread_mutex_unlock(&adev->lock);
6979 return ret;
6980}
6981
6982static int in_start(const struct audio_stream_in* stream)
6983{
6984 struct stream_in *in = (struct stream_in *)stream;
6985 struct audio_device *adev = in->dev;
6986 int ret = -ENOSYS;
6987
6988 ALOGV("%s in %p", __func__, in);
6989 pthread_mutex_lock(&adev->lock);
6990 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6991 !in->capture_started && in->pcm != NULL) {
6992 if (!in->capture_started) {
6993 ret = start_input_stream(in);
6994 if (ret == 0) {
6995 in->capture_started = true;
6996 }
6997 }
6998 }
6999 pthread_mutex_unlock(&adev->lock);
7000 return ret;
7001}
7002
Phil Burke0a86d12019-02-16 22:28:11 -08007003// Read offset for the positional timestamp from a persistent vendor property.
7004// This is to workaround apparent inaccuracies in the timing information that
7005// is used by the AAudio timing model. The inaccuracies can cause glitches.
7006static int64_t in_get_mmap_time_offset() {
7007 const int32_t kDefaultOffsetMicros = 0;
7008 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007009 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007010 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7011 return mmap_time_offset_micros * (int64_t)1000;
7012}
7013
Haynes Mathew George16081042017-05-31 17:16:49 -07007014static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7015 int32_t min_size_frames,
7016 struct audio_mmap_buffer_info *info)
7017{
7018 struct stream_in *in = (struct stream_in *)stream;
7019 struct audio_device *adev = in->dev;
7020 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007021 unsigned int offset1 = 0;
7022 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007023 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007024 uint32_t mmap_size = 0;
7025 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007026
7027 pthread_mutex_lock(&adev->lock);
7028 ALOGV("%s in %p", __func__, in);
7029
Sharad Sanglec6f32552018-05-04 16:15:38 +05307030 if (CARD_STATUS_OFFLINE == in->card_status||
7031 CARD_STATUS_OFFLINE == adev->card_status) {
7032 ALOGW("in->card_status or adev->card_status offline, try again");
7033 ret = -EIO;
7034 goto exit;
7035 }
7036
Haynes Mathew George16081042017-05-31 17:16:49 -07007037 if (info == NULL || min_size_frames == 0) {
7038 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7039 ret = -EINVAL;
7040 goto exit;
7041 }
7042 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7043 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7044 ALOGV("%s in %p", __func__, in);
7045 ret = -ENOSYS;
7046 goto exit;
7047 }
7048 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7049 if (in->pcm_device_id < 0) {
7050 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7051 __func__, in->pcm_device_id, in->usecase);
7052 ret = -EINVAL;
7053 goto exit;
7054 }
7055
7056 adjust_mmap_period_count(&in->config, min_size_frames);
7057
7058 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7059 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7060 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7061 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307062 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307063 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7064 in->card_status = CARD_STATUS_OFFLINE;
7065 adev->card_status = CARD_STATUS_OFFLINE;
7066 ret = -EIO;
7067 goto exit;
7068 }
7069
Haynes Mathew George16081042017-05-31 17:16:49 -07007070 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7071 step = "open";
7072 ret = -ENODEV;
7073 goto exit;
7074 }
7075
7076 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7077 if (ret < 0) {
7078 step = "begin";
7079 goto exit;
7080 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007081
Arun Mirpuri5d170872019-03-26 13:21:31 -07007082 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7083 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7084 info->burst_size_frames = in->config.period_size;
7085 ret = platform_get_mmap_data_fd(adev->platform,
7086 in->pcm_device_id, 1 /*capture*/,
7087 &info->shared_memory_fd,
7088 &mmap_size);
7089 if (ret < 0) {
7090 // Fall back to non exclusive mode
7091 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7092 } else {
7093 if (mmap_size < buffer_size) {
7094 step = "mmap";
7095 goto exit;
7096 }
7097 // FIXME: indicate exclusive mode support by returning a negative buffer size
7098 info->buffer_size_frames *= -1;
7099 }
7100
7101 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007102
7103 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7104 if (ret < 0) {
7105 step = "commit";
7106 goto exit;
7107 }
7108
Phil Burke0a86d12019-02-16 22:28:11 -08007109 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7110
Haynes Mathew George16081042017-05-31 17:16:49 -07007111 in->standby = false;
7112 ret = 0;
7113
7114 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7115 __func__, info->shared_memory_address, info->buffer_size_frames);
7116
7117exit:
7118 if (ret != 0) {
7119 if (in->pcm == NULL) {
7120 ALOGE("%s: %s - %d", __func__, step, ret);
7121 } else {
7122 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7123 pcm_close(in->pcm);
7124 in->pcm = NULL;
7125 }
7126 }
7127 pthread_mutex_unlock(&adev->lock);
7128 return ret;
7129}
7130
7131static int in_get_mmap_position(const struct audio_stream_in *stream,
7132 struct audio_mmap_position *position)
7133{
7134 struct stream_in *in = (struct stream_in *)stream;
7135 ALOGVV("%s", __func__);
7136 if (position == NULL) {
7137 return -EINVAL;
7138 }
7139 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7140 return -ENOSYS;
7141 }
7142 if (in->pcm == NULL) {
7143 return -ENOSYS;
7144 }
7145 struct timespec ts = { 0, 0 };
7146 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7147 if (ret < 0) {
7148 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7149 return ret;
7150 }
Phil Burke0a86d12019-02-16 22:28:11 -08007151 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7152 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007153 return 0;
7154}
7155
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307156static int in_get_active_microphones(const struct audio_stream_in *stream,
7157 struct audio_microphone_characteristic_t *mic_array,
7158 size_t *mic_count) {
7159 struct stream_in *in = (struct stream_in *)stream;
7160 struct audio_device *adev = in->dev;
7161 ALOGVV("%s", __func__);
7162
7163 lock_input_stream(in);
7164 pthread_mutex_lock(&adev->lock);
7165 int ret = platform_get_active_microphones(adev->platform,
7166 audio_channel_count_from_in_mask(in->channel_mask),
7167 in->usecase, mic_array, mic_count);
7168 pthread_mutex_unlock(&adev->lock);
7169 pthread_mutex_unlock(&in->lock);
7170
7171 return ret;
7172}
7173
7174static int adev_get_microphones(const struct audio_hw_device *dev,
7175 struct audio_microphone_characteristic_t *mic_array,
7176 size_t *mic_count) {
7177 struct audio_device *adev = (struct audio_device *)dev;
7178 ALOGVV("%s", __func__);
7179
7180 pthread_mutex_lock(&adev->lock);
7181 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7182 pthread_mutex_unlock(&adev->lock);
7183
7184 return ret;
7185}
juyuchendb308c22019-01-21 11:57:17 -07007186
7187static void in_update_sink_metadata(struct audio_stream_in *stream,
7188 const struct sink_metadata *sink_metadata) {
7189
7190 if (stream == NULL
7191 || sink_metadata == NULL
7192 || sink_metadata->tracks == NULL) {
7193 return;
7194 }
7195
7196 int error = 0;
7197 struct stream_in *in = (struct stream_in *)stream;
7198 struct audio_device *adev = in->dev;
7199 audio_devices_t device = AUDIO_DEVICE_NONE;
7200
7201 if (sink_metadata->track_count != 0)
7202 device = sink_metadata->tracks->dest_device;
7203
7204 lock_input_stream(in);
7205 pthread_mutex_lock(&adev->lock);
7206 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7207
7208 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7209 && device != AUDIO_DEVICE_NONE
7210 && adev->voice_tx_output != NULL) {
7211 /* Use the rx device from afe-proxy record to route voice call because
7212 there is no routing if tx device is on primary hal and rx device
7213 is on other hal during voice call. */
7214 adev->voice_tx_output->devices = device;
7215
7216 if (!voice_is_call_state_active(adev)) {
7217 if (adev->mode == AUDIO_MODE_IN_CALL) {
7218 adev->current_call_output = adev->voice_tx_output;
7219 error = voice_start_call(adev);
7220 if (error != 0)
7221 ALOGE("%s: start voice call failed %d", __func__, error);
7222 }
7223 } else {
7224 adev->current_call_output = adev->voice_tx_output;
7225 voice_update_devices_for_all_voice_usecases(adev);
7226 }
7227 }
7228
7229 pthread_mutex_unlock(&adev->lock);
7230 pthread_mutex_unlock(&in->lock);
7231}
7232
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307233int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007234 audio_io_handle_t handle,
7235 audio_devices_t devices,
7236 audio_output_flags_t flags,
7237 struct audio_config *config,
7238 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007239 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007240{
7241 struct audio_device *adev = (struct audio_device *)dev;
7242 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307243 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007244 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007245 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307246 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007247 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7248 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7249 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7250 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007251 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007252 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7253 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007254 bool force_haptic_path =
7255 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007256 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007257
kunleizdff872d2018-08-20 14:40:33 +08007258 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007259 is_usb_dev = false;
7260 devices = AUDIO_DEVICE_OUT_SPEAKER;
7261 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7262 __func__, devices);
7263 }
7264
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007265 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307266
Rahul Sharma99770982019-03-06 17:05:26 +05307267 pthread_mutex_lock(&adev->lock);
7268 if (out_get_stream(adev, handle) != NULL) {
7269 ALOGW("%s, output stream already opened", __func__);
7270 ret = -EEXIST;
7271 }
7272 pthread_mutex_unlock(&adev->lock);
7273 if (ret)
7274 return ret;
7275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007276 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7277
Mingming Yin3a941d42016-02-17 18:08:05 -08007278 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007279 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7280 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307281
7282
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007283 if (!out) {
7284 return -ENOMEM;
7285 }
7286
Haynes Mathew George204045b2015-02-25 20:32:03 -08007287 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007288 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307289 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007290 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007291 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007293 if (devices == AUDIO_DEVICE_NONE)
7294 devices = AUDIO_DEVICE_OUT_SPEAKER;
7295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007296 out->flags = flags;
7297 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007298 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007299 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007300 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307301 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307302 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7303 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7304 else
7305 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007306 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007307 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007308 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307309 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307310 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307311 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007312 out->hal_output_suspend_supported = 0;
7313 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307314 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307315 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307316 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007317
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307318 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307319 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007320 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7321
Aalique Grahame22e49102018-12-18 14:23:57 -08007322 if (direct_dev &&
7323 (audio_is_linear_pcm(out->format) ||
7324 config->format == AUDIO_FORMAT_DEFAULT) &&
7325 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7326 audio_format_t req_format = config->format;
7327 audio_channel_mask_t req_channel_mask = config->channel_mask;
7328 uint32_t req_sample_rate = config->sample_rate;
7329
7330 pthread_mutex_lock(&adev->lock);
7331 if (is_hdmi) {
7332 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7333 ret = read_hdmi_sink_caps(out);
7334 if (config->sample_rate == 0)
7335 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7336 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7337 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7338 if (config->format == AUDIO_FORMAT_DEFAULT)
7339 config->format = AUDIO_FORMAT_PCM_16_BIT;
7340 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007341 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7342 &config->format,
7343 &out->supported_formats[0],
7344 MAX_SUPPORTED_FORMATS,
7345 &config->channel_mask,
7346 &out->supported_channel_masks[0],
7347 MAX_SUPPORTED_CHANNEL_MASKS,
7348 &config->sample_rate,
7349 &out->supported_sample_rates[0],
7350 MAX_SUPPORTED_SAMPLE_RATES);
7351 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007352 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007353
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007354 pthread_mutex_unlock(&adev->lock);
7355 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007356 if (ret == -ENOSYS) {
7357 /* ignore and go with default */
7358 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007359 }
7360 // For MMAP NO IRQ, allow conversions in ADSP
7361 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7362 goto error_open;
7363 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007364 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007365 goto error_open;
7366 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007367
7368 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7369 config->sample_rate = req_sample_rate;
7370 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7371 config->channel_mask = req_channel_mask;
7372 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7373 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007374 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007375
7376 out->sample_rate = config->sample_rate;
7377 out->channel_mask = config->channel_mask;
7378 out->format = config->format;
7379 if (is_hdmi) {
7380 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7381 out->config = pcm_config_hdmi_multi;
7382 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7383 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7384 out->config = pcm_config_mmap_playback;
7385 out->stream.start = out_start;
7386 out->stream.stop = out_stop;
7387 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7388 out->stream.get_mmap_position = out_get_mmap_position;
7389 } else {
7390 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7391 out->config = pcm_config_hifi;
7392 }
7393
7394 out->config.rate = out->sample_rate;
7395 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7396 if (is_hdmi) {
7397 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7398 audio_bytes_per_sample(out->format));
7399 }
7400 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007401 }
7402
Derek Chenf6318be2017-06-12 17:16:24 -04007403 /* validate bus device address */
7404 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7405 /* extract car audio stream index */
7406 out->car_audio_stream =
7407 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7408 if (out->car_audio_stream < 0) {
7409 ALOGE("%s: invalid car audio stream %x",
7410 __func__, out->car_audio_stream);
7411 ret = -EINVAL;
7412 goto error_open;
7413 }
7414 /* save car audio stream and address for bus device */
7415 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7416 ALOGV("%s: address %s, car_audio_stream %x",
7417 __func__, out->address, out->car_audio_stream);
7418 }
7419
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007420 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007421 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007422 if (!voice_extn_is_compress_voip_supported()) {
7423 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7424 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007425 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7426 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007427 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7428 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007429 out->volume_l = INVALID_OUT_VOLUME;
7430 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007431
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007432 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007433 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007434 uint32_t channel_count =
7435 audio_channel_count_from_out_mask(out->channel_mask);
7436 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7437 out->sample_rate, out->format,
7438 channel_count, false);
7439 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7440 if (frame_size != 0)
7441 out->config.period_size = buffer_size / frame_size;
7442 else
7443 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007444 }
7445 } else {
7446 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7447 voice_extn_compress_voip_is_active(out->dev)) &&
7448 (voice_extn_compress_voip_is_config_supported(config))) {
7449 ret = voice_extn_compress_voip_open_output_stream(out);
7450 if (ret != 0) {
7451 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7452 __func__, ret);
7453 goto error_open;
7454 }
Sujin Panickerabaf5ad2019-09-16 18:28:06 +05307455 } else {
7456 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7457 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007458 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007459 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007460 } else if (audio_is_linear_pcm(out->format) &&
7461 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7462 out->channel_mask = config->channel_mask;
7463 out->sample_rate = config->sample_rate;
7464 out->format = config->format;
7465 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7466 // does this change?
7467 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7468 out->config.rate = config->sample_rate;
7469 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7470 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7471 audio_bytes_per_sample(config->format));
7472 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007473 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307474 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307475 pthread_mutex_lock(&adev->lock);
7476 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7477 pthread_mutex_unlock(&adev->lock);
7478
7479 // reject offload during card offline to allow
7480 // fallback to s/w paths
7481 if (offline) {
7482 ret = -ENODEV;
7483 goto error_open;
7484 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007486 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7487 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7488 ALOGE("%s: Unsupported Offload information", __func__);
7489 ret = -EINVAL;
7490 goto error_open;
7491 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007492
Atul Khare3fa6e542017-08-09 00:56:17 +05307493 if (config->offload_info.format == 0)
7494 config->offload_info.format = config->format;
7495 if (config->offload_info.sample_rate == 0)
7496 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007497
Mingming Yin90310102013-11-13 16:57:00 -08007498 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307499 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007500 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007501 ret = -EINVAL;
7502 goto error_open;
7503 }
7504
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007505 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7506 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7507 (audio_extn_passthru_is_passthrough_stream(out)) &&
7508 !((config->sample_rate == 48000) ||
7509 (config->sample_rate == 96000) ||
7510 (config->sample_rate == 192000))) {
7511 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7512 __func__, config->sample_rate, config->offload_info.format);
7513 ret = -EINVAL;
7514 goto error_open;
7515 }
7516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007517 out->compr_config.codec = (struct snd_codec *)
7518 calloc(1, sizeof(struct snd_codec));
7519
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007520 if (!out->compr_config.codec) {
7521 ret = -ENOMEM;
7522 goto error_open;
7523 }
7524
Dhananjay Kumarac341582017-02-23 23:42:25 +05307525 out->stream.pause = out_pause;
7526 out->stream.resume = out_resume;
7527 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307528 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307529 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007530 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307531 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007532 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307533 } else {
7534 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7535 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007536 }
vivek mehta446c3962015-09-14 10:57:35 -07007537
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307538 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7539 ALOGD("%s: Setting latency mode to true", __func__);
7540 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7541 }
7542
vivek mehta446c3962015-09-14 10:57:35 -07007543 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007544 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7545 config->format == 0 && config->sample_rate == 0 &&
7546 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007547 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007548 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7549 } else {
7550 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7551 ret = -EEXIST;
7552 goto error_open;
7553 }
vivek mehta446c3962015-09-14 10:57:35 -07007554 }
7555
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007556 if (config->offload_info.channel_mask)
7557 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007558 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007559 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007560 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007561 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307562 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007563 ret = -EINVAL;
7564 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007565 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007566
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007567 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007568 out->sample_rate = config->offload_info.sample_rate;
7569
Mingming Yin3ee55c62014-08-04 14:23:35 -07007570 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007571
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307572 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307573 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307574 audio_extn_dolby_send_ddp_endp_params(adev);
7575 audio_extn_dolby_set_dmid(adev);
7576 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007577
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007578 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007579 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007580 out->compr_config.codec->bit_rate =
7581 config->offload_info.bit_rate;
7582 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307583 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007584 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307585 /* Update bit width only for non passthrough usecases.
7586 * For passthrough usecases, the output will always be opened @16 bit
7587 */
7588 if (!audio_extn_passthru_is_passthrough_stream(out))
7589 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307590
7591 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7592 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7593 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7594
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007595 /*TODO: Do we need to change it for passthrough */
7596 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007597
Manish Dewangana6fc5442015-08-24 20:30:31 +05307598 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7599 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307600 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307601 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307602 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7603 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307604
7605 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7606 AUDIO_FORMAT_PCM) {
7607
7608 /*Based on platform support, configure appropriate alsa format for corresponding
7609 *hal input format.
7610 */
7611 out->compr_config.codec->format = hal_format_to_alsa(
7612 config->offload_info.format);
7613
Ashish Jain83a6cc22016-06-28 14:34:17 +05307614 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307615 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307616 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307617
Dhananjay Kumarac341582017-02-23 23:42:25 +05307618 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307619 *hal input format and alsa format might differ based on platform support.
7620 */
7621 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307622 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307623
7624 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7625
Deeraj Soman65358ab2019-02-07 15:40:49 +05307626 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7627 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7628 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7629
Ashish Jainf1eaa582016-05-23 20:54:24 +05307630 /* Check if alsa session is configured with the same format as HAL input format,
7631 * if not then derive correct fragment size needed to accomodate the
7632 * conversion of HAL input format to alsa format.
7633 */
7634 audio_extn_utils_update_direct_pcm_fragment_size(out);
7635
7636 /*if hal input and output fragment size is different this indicates HAL input format is
7637 *not same as the alsa format
7638 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307639 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307640 /*Allocate a buffer to convert input data to the alsa configured format.
7641 *size of convert buffer is equal to the size required to hold one fragment size
7642 *worth of pcm data, this is because flinger does not write more than fragment_size
7643 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307644 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7645 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307646 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7647 ret = -ENOMEM;
7648 goto error_open;
7649 }
7650 }
7651 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7652 out->compr_config.fragment_size =
7653 audio_extn_passthru_get_buffer_size(&config->offload_info);
7654 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7655 } else {
7656 out->compr_config.fragment_size =
7657 platform_get_compress_offload_buffer_size(&config->offload_info);
7658 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7659 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007660
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307661 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7662 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7663 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007664 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307665 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007666
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307667 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7668 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7669 }
7670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007671 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7672 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007673
Manish Dewangan69426c82017-01-30 17:35:36 +05307674 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7675 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7676 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7677 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7678 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7679 } else {
7680 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7681 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007682
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307683 memset(&out->channel_map_param, 0,
7684 sizeof(struct audio_out_channel_map_param));
7685
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007686 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307687 out->send_next_track_params = false;
7688 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007689 out->offload_state = OFFLOAD_STATE_IDLE;
7690 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007691 out->writeAt.tv_sec = 0;
7692 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007693
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007694 audio_extn_dts_create_state_notifier_node(out->usecase);
7695
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007696 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7697 __func__, config->offload_info.version,
7698 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307699
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307700 /* Check if DSD audio format is supported in codec
7701 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307702 */
7703
7704 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307705 (!platform_check_codec_dsd_support(adev->platform) ||
7706 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307707 ret = -EINVAL;
7708 goto error_open;
7709 }
7710
Ashish Jain5106d362016-05-11 19:23:33 +05307711 /* Disable gapless if any of the following is true
7712 * passthrough playback
7713 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307714 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307715 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307716 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307717 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007718 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307719 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307720 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307721 check_and_set_gapless_mode(adev, false);
7722 } else
7723 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007724
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307725 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007726 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7727 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307728 if (config->format == AUDIO_FORMAT_DSD) {
7729 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7730 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7731 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007732
7733 create_offload_callback_thread(out);
7734
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007735 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007736 switch (config->sample_rate) {
7737 case 0:
7738 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7739 break;
7740 case 8000:
7741 case 16000:
7742 case 48000:
7743 out->sample_rate = config->sample_rate;
7744 break;
7745 default:
7746 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7747 config->sample_rate);
7748 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7749 ret = -EINVAL;
7750 goto error_open;
7751 }
7752 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7753 switch (config->channel_mask) {
7754 case AUDIO_CHANNEL_NONE:
7755 case AUDIO_CHANNEL_OUT_STEREO:
7756 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7757 break;
7758 default:
7759 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7760 config->channel_mask);
7761 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7762 ret = -EINVAL;
7763 goto error_open;
7764 }
7765 switch (config->format) {
7766 case AUDIO_FORMAT_DEFAULT:
7767 case AUDIO_FORMAT_PCM_16_BIT:
7768 out->format = AUDIO_FORMAT_PCM_16_BIT;
7769 break;
7770 default:
7771 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7772 config->format);
7773 config->format = AUDIO_FORMAT_PCM_16_BIT;
7774 ret = -EINVAL;
7775 goto error_open;
7776 }
7777
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307778 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007779 if (ret != 0) {
7780 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007781 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007782 goto error_open;
7783 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007784 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007785 switch (config->sample_rate) {
7786 case 0:
7787 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7788 break;
7789 case 8000:
7790 case 16000:
7791 case 48000:
7792 out->sample_rate = config->sample_rate;
7793 break;
7794 default:
7795 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7796 config->sample_rate);
7797 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7798 ret = -EINVAL;
7799 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007800 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007801 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7802 switch (config->channel_mask) {
7803 case AUDIO_CHANNEL_NONE:
7804 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7805 break;
7806 case AUDIO_CHANNEL_OUT_STEREO:
7807 out->channel_mask = config->channel_mask;
7808 break;
7809 default:
7810 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7811 config->channel_mask);
7812 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7813 ret = -EINVAL;
7814 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007815 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007816 switch (config->format) {
7817 case AUDIO_FORMAT_DEFAULT:
7818 out->format = AUDIO_FORMAT_PCM_16_BIT;
7819 break;
7820 case AUDIO_FORMAT_PCM_16_BIT:
7821 out->format = config->format;
7822 break;
7823 default:
7824 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7825 config->format);
7826 config->format = AUDIO_FORMAT_PCM_16_BIT;
7827 ret = -EINVAL;
7828 break;
7829 }
7830 if (ret != 0)
7831 goto error_open;
7832
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007833 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7834 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007835 out->config.rate = out->sample_rate;
7836 out->config.channels =
7837 audio_channel_count_from_out_mask(out->channel_mask);
7838 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007839 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007840 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307841 unsigned int channels = 0;
7842 /*Update config params to default if not set by the caller*/
7843 if (config->sample_rate == 0)
7844 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7845 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7846 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7847 if (config->format == AUDIO_FORMAT_DEFAULT)
7848 config->format = AUDIO_FORMAT_PCM_16_BIT;
7849
7850 channels = audio_channel_count_from_out_mask(out->channel_mask);
7851
Varun Balaraje49253e2017-07-06 19:48:56 +05307852 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7853 out->usecase = get_interactive_usecase(adev);
7854 out->config = pcm_config_low_latency;
7855 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307856 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007857 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7858 out->flags);
7859 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007860 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7861 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7862 out->config = pcm_config_mmap_playback;
7863 out->stream.start = out_start;
7864 out->stream.stop = out_stop;
7865 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7866 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307867 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7868 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007869 out->hal_output_suspend_supported =
7870 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7871 out->dynamic_pm_qos_config_supported =
7872 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7873 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007874 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7875 } else {
7876 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7877 //the mixer path will be a string similar to "low-latency-playback resume"
7878 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7879 strlcat(out->pm_qos_mixer_path,
7880 " resume", MAX_MIXER_PATH_LEN);
7881 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7882 out->pm_qos_mixer_path);
7883 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307884 out->config = pcm_config_low_latency;
7885 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7886 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7887 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307888 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7889 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7890 if (out->config.period_size <= 0) {
7891 ALOGE("Invalid configuration period size is not valid");
7892 ret = -EINVAL;
7893 goto error_open;
7894 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007895 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7896 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7897 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007898 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7899 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7900 out->config = pcm_config_haptics_audio;
7901 if (force_haptic_path)
7902 adev->haptics_config = pcm_config_haptics_audio;
7903 else
7904 adev->haptics_config = pcm_config_haptics;
7905
7906 out->config.channels =
7907 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7908
7909 if (force_haptic_path) {
7910 out->config.channels = 1;
7911 adev->haptics_config.channels = 1;
7912 } else
7913 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007914 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7915 ret = audio_extn_auto_hal_open_output_stream(out);
7916 if (ret) {
7917 ALOGE("%s: Failed to open output stream for bus device", __func__);
7918 ret = -EINVAL;
7919 goto error_open;
7920 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307921 } else {
7922 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007923 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7924 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307925 }
7926 out->hal_ip_format = format = out->format;
7927 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7928 out->hal_op_format = pcm_format_to_hal(out->config.format);
7929 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7930 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007931 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307932 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307933 if (out->hal_ip_format != out->hal_op_format) {
7934 uint32_t buffer_size = out->config.period_size *
7935 format_to_bitwidth_table[out->hal_op_format] *
7936 out->config.channels;
7937 out->convert_buffer = calloc(1, buffer_size);
7938 if (out->convert_buffer == NULL){
7939 ALOGE("Allocation failed for convert buffer for size %d",
7940 out->compr_config.fragment_size);
7941 ret = -ENOMEM;
7942 goto error_open;
7943 }
7944 ALOGD("Convert buffer allocated of size %d", buffer_size);
7945 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007946 }
7947
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007948 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7949 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307950
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007951 /* TODO remove this hardcoding and check why width is zero*/
7952 if (out->bit_width == 0)
7953 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307954 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007955 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007956 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307957 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307958 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007959 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007960 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7961 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007962 if(adev->primary_output == NULL)
7963 adev->primary_output = out;
7964 else {
7965 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007966 ret = -EEXIST;
7967 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007968 }
7969 }
7970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007971 /* Check if this usecase is already existing */
7972 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007973 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7974 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007975 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007976 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007977 ret = -EEXIST;
7978 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007979 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007981 pthread_mutex_unlock(&adev->lock);
7982
7983 out->stream.common.get_sample_rate = out_get_sample_rate;
7984 out->stream.common.set_sample_rate = out_set_sample_rate;
7985 out->stream.common.get_buffer_size = out_get_buffer_size;
7986 out->stream.common.get_channels = out_get_channels;
7987 out->stream.common.get_format = out_get_format;
7988 out->stream.common.set_format = out_set_format;
7989 out->stream.common.standby = out_standby;
7990 out->stream.common.dump = out_dump;
7991 out->stream.common.set_parameters = out_set_parameters;
7992 out->stream.common.get_parameters = out_get_parameters;
7993 out->stream.common.add_audio_effect = out_add_audio_effect;
7994 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7995 out->stream.get_latency = out_get_latency;
7996 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007997#ifdef NO_AUDIO_OUT
7998 out->stream.write = out_write_for_no_output;
7999#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008000 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008001#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008002 out->stream.get_render_position = out_get_render_position;
8003 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008004 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008005
Haynes Mathew George16081042017-05-31 17:16:49 -07008006 if (out->realtime)
8007 out->af_period_multiplier = af_period_multiplier;
8008 else
8009 out->af_period_multiplier = 1;
8010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008011 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008012 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008013 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008014
8015 config->format = out->stream.common.get_format(&out->stream.common);
8016 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8017 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308018 register_format(out->format, out->supported_formats);
8019 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8020 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008021
Aalique Grahame22e49102018-12-18 14:23:57 -08008022 out->error_log = error_log_create(
8023 ERROR_LOG_ENTRIES,
8024 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8025
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308026 /*
8027 By locking output stream before registering, we allow the callback
8028 to update stream's state only after stream's initial state is set to
8029 adev state.
8030 */
8031 lock_output_stream(out);
8032 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8033 pthread_mutex_lock(&adev->lock);
8034 out->card_status = adev->card_status;
8035 pthread_mutex_unlock(&adev->lock);
8036 pthread_mutex_unlock(&out->lock);
8037
Aalique Grahame22e49102018-12-18 14:23:57 -08008038 stream_app_type_cfg_init(&out->app_type_cfg);
8039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008040 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308041 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008042 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008043
8044 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8045 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8046 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008047 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308048 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008049 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008050 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308051 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8052 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008053 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8054 out->usecase, PCM_PLAYBACK);
8055 hdlr_stream_cfg.flags = out->flags;
8056 hdlr_stream_cfg.type = PCM_PLAYBACK;
8057 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8058 &hdlr_stream_cfg);
8059 if (ret) {
8060 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8061 out->adsp_hdlr_stream_handle = NULL;
8062 }
8063 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308064 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8065 is_direct_passthough, false);
8066 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8067 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008068 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008069 if (ret < 0) {
8070 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8071 out->ip_hdlr_handle = NULL;
8072 }
8073 }
Derek Chenf939fb72018-11-13 13:34:41 -08008074
8075 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8076 calloc(1, sizeof(streams_output_ctxt_t));
8077 if (out_ctxt == NULL) {
8078 ALOGE("%s fail to allocate output ctxt", __func__);
8079 ret = -ENOMEM;
8080 goto error_open;
8081 }
8082 out_ctxt->output = out;
8083
8084 pthread_mutex_lock(&adev->lock);
8085 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8086 pthread_mutex_unlock(&adev->lock);
8087
Eric Laurent994a6932013-07-17 11:51:42 -07008088 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008089 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008090
8091error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308092 if (out->convert_buffer)
8093 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008094 free(out);
8095 *stream_out = NULL;
8096 ALOGD("%s: exit: ret %d", __func__, ret);
8097 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008098}
8099
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308100void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008101 struct audio_stream_out *stream)
8102{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008103 struct stream_out *out = (struct stream_out *)stream;
8104 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008105 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008106
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008107 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308108
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308109 // must deregister from sndmonitor first to prevent races
8110 // between the callback and close_stream
8111 audio_extn_snd_mon_unregister_listener(out);
8112
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008113 /* close adsp hdrl session before standby */
8114 if (out->adsp_hdlr_stream_handle) {
8115 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8116 if (ret)
8117 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8118 out->adsp_hdlr_stream_handle = NULL;
8119 }
8120
Manish Dewangan21a850a2017-08-14 12:03:55 +05308121 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008122 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8123 out->ip_hdlr_handle = NULL;
8124 }
8125
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008126 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308127 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008128 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308129 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308130 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008131 if(ret != 0)
8132 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8133 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008134 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008135 out_standby(&stream->common);
8136
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008137 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008138 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008139 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008140 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008141 if (out->compr_config.codec != NULL)
8142 free(out->compr_config.codec);
8143 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008144
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308145 out->a2dp_compress_mute = false;
8146
Varun Balaraje49253e2017-07-06 19:48:56 +05308147 if (is_interactive_usecase(out->usecase))
8148 free_interactive_usecase(adev, out->usecase);
8149
Ashish Jain83a6cc22016-06-28 14:34:17 +05308150 if (out->convert_buffer != NULL) {
8151 free(out->convert_buffer);
8152 out->convert_buffer = NULL;
8153 }
8154
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008155 if (adev->voice_tx_output == out)
8156 adev->voice_tx_output = NULL;
8157
Aalique Grahame22e49102018-12-18 14:23:57 -08008158 error_log_destroy(out->error_log);
8159 out->error_log = NULL;
8160
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308161 if (adev->primary_output == out)
8162 adev->primary_output = NULL;
8163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008164 pthread_cond_destroy(&out->cond);
8165 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008166
8167 pthread_mutex_lock(&adev->lock);
8168 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8169 if (out_ctxt != NULL) {
8170 list_remove(&out_ctxt->list);
8171 free(out_ctxt);
8172 } else {
8173 ALOGW("%s, output stream already closed", __func__);
8174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008175 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008176 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008177 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008178}
8179
8180static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8181{
8182 struct audio_device *adev = (struct audio_device *)dev;
8183 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008184 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008185 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008186 int ret;
8187 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008188 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008189 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008190
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008191 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008192 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008193
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308194 if (!parms)
8195 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308196
Derek Chen6f293672019-04-01 01:40:24 -07008197 /* notify adev and input/output streams on the snd card status */
8198 adev_snd_mon_cb((void *)adev, parms);
8199
8200 list_for_each(node, &adev->active_outputs_list) {
8201 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8202 streams_output_ctxt_t,
8203 list);
8204 out_snd_mon_cb((void *)out_ctxt->output, parms);
8205 }
8206
8207 list_for_each(node, &adev->active_inputs_list) {
8208 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8209 streams_input_ctxt_t,
8210 list);
8211 in_snd_mon_cb((void *)in_ctxt->input, parms);
8212 }
8213
Zhou Songd6d71752019-05-21 18:08:51 +08008214 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308215 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8216 if (ret >= 0) {
8217 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008218 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308219 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008220 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308221 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008222 audio_extn_sco_reset_configuration();
Kunlei Zhang136e6742019-08-27 16:33:29 +08008223 }
8224 }
8225
8226 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8227 if (ret>=0) {
8228 if (!strncmp(value, "false", 5) &&
8229 audio_extn_a2dp_source_is_suspended()) {
8230 struct audio_usecase *usecase;
8231 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008232 list_for_each(node, &adev->usecase_list) {
8233 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhang136e6742019-08-27 16:33:29 +08008234 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
8235 ((usecase->stream.in->device & ~AUDIO_DEVICE_BIT_IN) &
8236 AUDIO_DEVICE_IN_ALL_SCO)) {
8237 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Zhou Songd6d71752019-05-21 18:08:51 +08008238 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
Kunlei Zhang136e6742019-08-27 16:33:29 +08008239 select_devices(adev, usecase->id);
8240 }
Zhou Songd6d71752019-05-21 18:08:51 +08008241 }
8242 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308243 }
8244
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008245 status = voice_set_parameters(adev, parms);
8246 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008247 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008248
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008249 status = platform_set_parameters(adev->platform, parms);
8250 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008251 goto done;
8252
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8254 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008255 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008256 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8257 adev->bluetooth_nrec = true;
8258 else
8259 adev->bluetooth_nrec = false;
8260 }
8261
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008262 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8263 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008264 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8265 adev->screen_off = false;
8266 else
8267 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008268 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008269 }
8270
Eric Laurent4b084132018-10-19 17:33:43 -07008271 ret = str_parms_get_int(parms, "rotation", &val);
8272 if (ret >= 0) {
8273 bool reverse_speakers = false;
8274 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8275 switch (val) {
8276 // FIXME: note that the code below assumes that the speakers are in the correct placement
8277 // relative to the user when the device is rotated 90deg from its default rotation. This
8278 // assumption is device-specific, not platform-specific like this code.
8279 case 270:
8280 reverse_speakers = true;
8281 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8282 break;
8283 case 0:
8284 case 180:
8285 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8286 break;
8287 case 90:
8288 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8289 break;
8290 default:
8291 ALOGE("%s: unexpected rotation of %d", __func__, val);
8292 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008293 }
Eric Laurent4b084132018-10-19 17:33:43 -07008294 if (status == 0) {
8295 // check and set swap
8296 // - check if orientation changed and speaker active
8297 // - set rotation and cache the rotation value
8298 adev->camera_orientation =
8299 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8300 if (!audio_extn_is_maxx_audio_enabled())
8301 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8302 }
8303 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008304
Mingming Yin514a8bc2014-07-29 15:22:21 -07008305 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8306 if (ret >= 0) {
8307 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8308 adev->bt_wb_speech_enabled = true;
8309 else
8310 adev->bt_wb_speech_enabled = false;
8311 }
8312
Zhou Song12c29502019-03-16 10:37:18 +08008313 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8314 if (ret >= 0) {
8315 val = atoi(value);
8316 adev->swb_speech_mode = val;
8317 }
8318
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008319 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8320 if (ret >= 0) {
8321 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308322 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008323 if (audio_is_output_device(val) &&
8324 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008325 ALOGV("cache new ext disp type and edid");
8326 ret = platform_get_ext_disp_type(adev->platform);
8327 if (ret < 0) {
8328 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308329 } else {
8330 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008331 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308332 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008333 /*
8334 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8335 * Per AudioPolicyManager, USB device is higher priority than WFD.
8336 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8337 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8338 * starting voice call on USB
8339 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008340 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308341 if (ret >= 0)
8342 audio_extn_usb_add_device(device, atoi(value));
8343
Zhou Song6f862822017-11-06 17:27:57 +08008344 if (!audio_extn_usb_is_tunnel_supported()) {
8345 ALOGV("detected USB connect .. disable proxy");
8346 adev->allow_afe_proxy_usage = false;
8347 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008348 }
8349 }
8350
8351 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8352 if (ret >= 0) {
8353 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308354 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008355 /*
8356 * The HDMI / Displayport disconnect handling has been moved to
8357 * audio extension to ensure that its parameters are not
8358 * invalidated prior to updating sysfs of the disconnect event
8359 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8360 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308361 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008362 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308363 if (ret >= 0)
8364 audio_extn_usb_remove_device(device, atoi(value));
8365
Zhou Song6f862822017-11-06 17:27:57 +08008366 if (!audio_extn_usb_is_tunnel_supported()) {
8367 ALOGV("detected USB disconnect .. enable proxy");
8368 adev->allow_afe_proxy_usage = true;
8369 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008370 }
8371 }
8372
Aalique Grahame22e49102018-12-18 14:23:57 -08008373 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008374 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008375
8376 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008377 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308378 struct audio_usecase *usecase;
8379 struct listnode *node;
8380 list_for_each(node, &adev->usecase_list) {
8381 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308382 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008383 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308384 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008385 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308386 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008387 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308388 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308389 ALOGD("Switching to speaker and muting the stream before select_devices");
8390 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308391 //force device switch to re configure encoder
8392 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308393 ALOGD("Unmuting the stream after select_devices");
8394 usecase->stream.out->a2dp_compress_mute = false;
8395 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 +05308396 audio_extn_a2dp_set_handoff_mode(false);
8397 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308398 break;
8399 }
8400 }
8401 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008402
8403 //handle vr audio setparam
8404 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8405 value, sizeof(value));
8406 if (ret >= 0) {
8407 ALOGI("Setting vr mode to be %s", value);
8408 if (!strncmp(value, "true", 4)) {
8409 adev->vr_audio_mode_enabled = true;
8410 ALOGI("Setting vr mode to true");
8411 } else if (!strncmp(value, "false", 5)) {
8412 adev->vr_audio_mode_enabled = false;
8413 ALOGI("Setting vr mode to false");
8414 } else {
8415 ALOGI("wrong vr mode set");
8416 }
8417 }
8418
Eric Laurent4b084132018-10-19 17:33:43 -07008419 //FIXME: to be replaced by proper video capture properties API
8420 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8421 if (ret >= 0) {
8422 int camera_facing = CAMERA_FACING_BACK;
8423 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8424 camera_facing = CAMERA_FACING_FRONT;
8425 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8426 camera_facing = CAMERA_FACING_BACK;
8427 else {
8428 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8429 goto done;
8430 }
8431 adev->camera_orientation =
8432 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8433 struct audio_usecase *usecase;
8434 struct listnode *node;
8435 list_for_each(node, &adev->usecase_list) {
8436 usecase = node_to_item(node, struct audio_usecase, list);
8437 struct stream_in *in = usecase->stream.in;
8438 if (usecase->type == PCM_CAPTURE && in != NULL &&
8439 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8440 select_devices(adev, in->usecase);
8441 }
8442 }
8443 }
8444
Balázs Triszkaa68afd52017-05-11 03:19:29 +02008445 ret = str_parms_get_int(parms, "ultrasound-sensor", &val);
8446 if (ret >= 0) {
8447 if (val == 1) {
8448 us_start();
8449 } else {
8450 us_stop();
8451 }
8452 }
8453
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05308454 amplifier_set_parameters(parms);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308455 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008456done:
8457 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008458 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308459error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008460 ALOGV("%s: exit with code(%d)", __func__, status);
8461 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008462}
8463
8464static char* adev_get_parameters(const struct audio_hw_device *dev,
8465 const char *keys)
8466{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308467 ALOGD("%s:%s", __func__, keys);
8468
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008469 struct audio_device *adev = (struct audio_device *)dev;
8470 struct str_parms *reply = str_parms_create();
8471 struct str_parms *query = str_parms_create_str(keys);
8472 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308473 char value[256] = {0};
8474 int ret = 0;
8475
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008476 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008477 if (reply) {
8478 str_parms_destroy(reply);
8479 }
8480 if (query) {
8481 str_parms_destroy(query);
8482 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008483 ALOGE("adev_get_parameters: failed to create query or reply");
8484 return NULL;
8485 }
8486
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008487 //handle vr audio getparam
8488
8489 ret = str_parms_get_str(query,
8490 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8491 value, sizeof(value));
8492
8493 if (ret >= 0) {
8494 bool vr_audio_enabled = false;
8495 pthread_mutex_lock(&adev->lock);
8496 vr_audio_enabled = adev->vr_audio_mode_enabled;
8497 pthread_mutex_unlock(&adev->lock);
8498
8499 ALOGI("getting vr mode to %d", vr_audio_enabled);
8500
8501 if (vr_audio_enabled) {
8502 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8503 "true");
8504 goto exit;
8505 } else {
8506 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8507 "false");
8508 goto exit;
8509 }
8510 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008511
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008512 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008513 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008514 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008515 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008516 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308517 pthread_mutex_unlock(&adev->lock);
8518
Naresh Tannirud7205b62014-06-20 02:54:48 +05308519exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008520 str = str_parms_to_str(reply);
8521 str_parms_destroy(query);
8522 str_parms_destroy(reply);
8523
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308524 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008525 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008526}
8527
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008528static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529{
8530 return 0;
8531}
8532
8533static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8534{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008535 int ret;
8536 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008537
8538 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8539
Haynes Mathew George5191a852013-09-11 14:19:36 -07008540 pthread_mutex_lock(&adev->lock);
8541 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008542 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008543 pthread_mutex_unlock(&adev->lock);
8544 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008545}
8546
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008547static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8548 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008549{
8550 return -ENOSYS;
8551}
8552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008553static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8554 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008555{
8556 return -ENOSYS;
8557}
8558
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008559static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8560 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008561{
8562 return -ENOSYS;
8563}
8564
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008565static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8566 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008567{
8568 return -ENOSYS;
8569}
8570
8571static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8572{
8573 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008574 struct listnode *node;
8575 struct audio_usecase *usecase = NULL;
8576 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008578 pthread_mutex_lock(&adev->lock);
8579 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008580 ALOGD("%s: mode %d\n", __func__, mode);
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05308581 if (amplifier_set_mode(mode) != 0)
8582 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008583 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008584 if (voice_is_in_call(adev) &&
8585 (mode == AUDIO_MODE_NORMAL ||
8586 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008587 list_for_each(node, &adev->usecase_list) {
8588 usecase = node_to_item(node, struct audio_usecase, list);
8589 if (usecase->type == VOICE_CALL)
8590 break;
8591 }
8592 if (usecase &&
8593 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8594 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8595 true);
8596 if (ret != 0) {
8597 /* default service interval was successfully updated,
8598 reopen USB backend with new service interval */
8599 check_usecases_codec_backend(adev,
8600 usecase,
8601 usecase->out_snd_device);
8602 }
8603 }
8604
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008605 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008606 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008607 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008608 // restore device for other active usecases after stop call
8609 list_for_each(node, &adev->usecase_list) {
8610 usecase = node_to_item(node, struct audio_usecase, list);
8611 select_devices(adev, usecase->id);
8612 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008613 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008614 }
8615 pthread_mutex_unlock(&adev->lock);
8616 return 0;
8617}
8618
8619static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8620{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008621 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008622 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008623
8624 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008625 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008626 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008627
Derek Chend2530072014-11-24 12:39:14 -08008628 if (adev->ext_hw_plugin)
8629 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008630
8631 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008632 pthread_mutex_unlock(&adev->lock);
8633
8634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008635}
8636
8637static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8638{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008639 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008640 return 0;
8641}
8642
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008643static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008644 const struct audio_config *config)
8645{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008646 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008647
Aalique Grahame22e49102018-12-18 14:23:57 -08008648 /* Don't know if USB HIFI in this context so use true to be conservative */
8649 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8650 true /*is_usb_hifi */) != 0)
8651 return 0;
8652
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008653 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8654 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008655}
8656
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008657static bool adev_input_allow_hifi_record(struct audio_device *adev,
8658 audio_devices_t devices,
8659 audio_input_flags_t flags,
8660 audio_source_t source) {
8661 const bool allowed = true;
8662
8663 if (!audio_is_usb_in_device(devices))
8664 return !allowed;
8665
8666 switch (flags) {
8667 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008668 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008669 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8670 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008671 default:
8672 return !allowed;
8673 }
8674
8675 switch (source) {
8676 case AUDIO_SOURCE_DEFAULT:
8677 case AUDIO_SOURCE_MIC:
8678 case AUDIO_SOURCE_UNPROCESSED:
8679 break;
8680 default:
8681 return !allowed;
8682 }
8683
8684 switch (adev->mode) {
8685 case 0:
8686 break;
8687 default:
8688 return !allowed;
8689 }
8690
8691 return allowed;
8692}
8693
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008694static int adev_update_voice_comm_input_stream(struct stream_in *in,
8695 struct audio_config *config)
8696{
8697 bool valid_rate = (config->sample_rate == 8000 ||
8698 config->sample_rate == 16000 ||
8699 config->sample_rate == 32000 ||
8700 config->sample_rate == 48000);
8701 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8702
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008703 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008704 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008705 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8706 in->config = default_pcm_config_voip_copp;
8707 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8708 DEFAULT_VOIP_BUF_DURATION_MS,
8709 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008710 } else {
8711 ALOGW("%s No valid input in voip, use defaults"
8712 "sample rate %u, channel mask 0x%X",
8713 __func__, config->sample_rate, in->channel_mask);
8714 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008715 in->config.rate = config->sample_rate;
8716 in->sample_rate = config->sample_rate;
8717 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008718 //XXX needed for voice_extn_compress_voip_open_input_stream
8719 in->config.rate = config->sample_rate;
8720 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathacd1de7d2019-08-23 15:13:46 +05308721 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008722 voice_extn_compress_voip_is_active(in->dev)) &&
8723 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8724 valid_rate && valid_ch) {
8725 voice_extn_compress_voip_open_input_stream(in);
8726 // update rate entries to match config from AF
8727 in->config.rate = config->sample_rate;
8728 in->sample_rate = config->sample_rate;
8729 } else {
8730 ALOGW("%s compress voip not active, use defaults", __func__);
8731 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008732 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008733 return 0;
8734}
8735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008736static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008737 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008738 audio_devices_t devices,
8739 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008740 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308741 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008742 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008743 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008744{
8745 struct audio_device *adev = (struct audio_device *)dev;
8746 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008747 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008748 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008749 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308750 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008751 bool is_usb_dev = audio_is_usb_in_device(devices);
8752 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8753 devices,
8754 flags,
8755 source);
Andy Hung94320602018-10-29 18:31:12 -07008756 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8757 " sample_rate %u, channel_mask %#x, format %#x",
8758 __func__, flags, is_usb_dev, may_use_hifi_record,
8759 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308760
kunleizdff872d2018-08-20 14:40:33 +08008761 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008762 is_usb_dev = false;
8763 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8764 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8765 __func__, devices);
8766 }
8767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008768 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008769
8770 if (!(is_usb_dev && may_use_hifi_record)) {
8771 if (config->sample_rate == 0)
8772 config->sample_rate = 48000;
8773 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8774 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8775 if (config->format == AUDIO_FORMAT_DEFAULT)
8776 config->format = AUDIO_FORMAT_PCM_16_BIT;
8777
8778 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8779
Aalique Grahame22e49102018-12-18 14:23:57 -08008780 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8781 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008782 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008784
Rahul Sharma99770982019-03-06 17:05:26 +05308785 pthread_mutex_lock(&adev->lock);
8786 if (in_get_stream(adev, handle) != NULL) {
8787 ALOGW("%s, input stream already opened", __func__);
8788 ret = -EEXIST;
8789 }
8790 pthread_mutex_unlock(&adev->lock);
8791 if (ret)
8792 return ret;
8793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008794 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008795
8796 if (!in) {
8797 ALOGE("failed to allocate input stream");
8798 return -ENOMEM;
8799 }
8800
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308801 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308802 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8803 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008804 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008805 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008807 in->stream.common.get_sample_rate = in_get_sample_rate;
8808 in->stream.common.set_sample_rate = in_set_sample_rate;
8809 in->stream.common.get_buffer_size = in_get_buffer_size;
8810 in->stream.common.get_channels = in_get_channels;
8811 in->stream.common.get_format = in_get_format;
8812 in->stream.common.set_format = in_set_format;
8813 in->stream.common.standby = in_standby;
8814 in->stream.common.dump = in_dump;
8815 in->stream.common.set_parameters = in_set_parameters;
8816 in->stream.common.get_parameters = in_get_parameters;
8817 in->stream.common.add_audio_effect = in_add_audio_effect;
8818 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8819 in->stream.set_gain = in_set_gain;
8820 in->stream.read = in_read;
8821 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008822 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308823 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008824 in->stream.set_microphone_direction = in_set_microphone_direction;
8825 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008826 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008827
8828 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008829 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008830 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008831 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008832 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008833 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008834 in->bit_width = 16;
8835 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008836 in->direction = MIC_DIRECTION_UNSPECIFIED;
8837 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008838 list_init(&in->aec_list);
8839 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008840
Andy Hung94320602018-10-29 18:31:12 -07008841 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008842 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8843 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8844 /* Force channel config requested to mono if incall
8845 record is being requested for only uplink/downlink */
8846 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8847 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8848 ret = -EINVAL;
8849 goto err_open;
8850 }
8851 }
8852
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008853 if (is_usb_dev && may_use_hifi_record) {
8854 /* HiFi record selects an appropriate format, channel, rate combo
8855 depending on sink capabilities*/
8856 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8857 &config->format,
8858 &in->supported_formats[0],
8859 MAX_SUPPORTED_FORMATS,
8860 &config->channel_mask,
8861 &in->supported_channel_masks[0],
8862 MAX_SUPPORTED_CHANNEL_MASKS,
8863 &config->sample_rate,
8864 &in->supported_sample_rates[0],
8865 MAX_SUPPORTED_SAMPLE_RATES);
8866 if (ret != 0) {
8867 ret = -EINVAL;
8868 goto err_open;
8869 }
8870 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008871 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308872 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308873 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8874 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8875 in->config.format = PCM_FORMAT_S32_LE;
8876 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308877 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8878 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8879 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8880 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8881 bool ret_error = false;
8882 in->bit_width = 24;
8883 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8884 from HAL is 24_packed and 8_24
8885 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8886 24_packed return error indicating supported format is 24_packed
8887 *> In case of any other source requesting 24 bit or float return error
8888 indicating format supported is 16 bit only.
8889
8890 on error flinger will retry with supported format passed
8891 */
8892 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8893 (source != AUDIO_SOURCE_CAMCORDER)) {
8894 config->format = AUDIO_FORMAT_PCM_16_BIT;
8895 if (config->sample_rate > 48000)
8896 config->sample_rate = 48000;
8897 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008898 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8899 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308900 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8901 ret_error = true;
8902 }
8903
8904 if (ret_error) {
8905 ret = -EINVAL;
8906 goto err_open;
8907 }
8908 }
8909
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008910 in->channel_mask = config->channel_mask;
8911 in->format = config->format;
8912
8913 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308914
8915 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8916 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8917 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8918 else {
8919 ret = -EINVAL;
8920 goto err_open;
8921 }
8922 }
8923
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008924 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308925 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8926 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008927 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8928 is_low_latency = true;
8929#if LOW_LATENCY_CAPTURE_USE_CASE
8930 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8931#endif
8932 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008933 if (!in->realtime) {
8934 in->config = pcm_config_audio_capture;
8935 frame_size = audio_stream_in_frame_size(&in->stream);
8936 buffer_size = get_input_buffer_size(config->sample_rate,
8937 config->format,
8938 channel_count,
8939 is_low_latency);
8940 in->config.period_size = buffer_size / frame_size;
8941 in->config.rate = config->sample_rate;
8942 in->af_period_multiplier = 1;
8943 } else {
8944 // period size is left untouched for rt mode playback
8945 in->config = pcm_config_audio_capture_rt;
8946 in->af_period_multiplier = af_period_multiplier;
8947 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008948 }
8949
8950 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8951 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8952 in->realtime = 0;
8953 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8954 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008955 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008956 in->stream.start = in_start;
8957 in->stream.stop = in_stop;
8958 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8959 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008960 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8961 } else if (in->realtime) {
8962 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008963 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008964 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008965 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008966 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8967 in->config = pcm_config_audio_capture;
8968 frame_size = audio_stream_in_frame_size(&in->stream);
8969 buffer_size = get_input_buffer_size(config->sample_rate,
8970 config->format,
8971 channel_count,
8972 false /*is_low_latency*/);
8973 in->config.period_size = buffer_size / frame_size;
8974 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008975 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008976 switch (config->format) {
8977 case AUDIO_FORMAT_PCM_32_BIT:
8978 in->bit_width = 32;
8979 break;
8980 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8981 case AUDIO_FORMAT_PCM_8_24_BIT:
8982 in->bit_width = 24;
8983 break;
8984 default:
8985 in->bit_width = 16;
8986 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008987 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308988 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008989 if (config->sample_rate == 0)
8990 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8991 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8992 config->sample_rate != 8000) {
8993 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8994 ret = -EINVAL;
8995 goto err_open;
8996 }
8997 if (config->format == AUDIO_FORMAT_DEFAULT)
8998 config->format = AUDIO_FORMAT_PCM_16_BIT;
8999 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9000 config->format = AUDIO_FORMAT_PCM_16_BIT;
9001 ret = -EINVAL;
9002 goto err_open;
9003 }
9004
9005 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9006 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009007 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009008 in->af_period_multiplier = 1;
9009 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunatha8a17fe32020-01-03 15:00:14 +05309010 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009011 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9012 (config->sample_rate == 8000 ||
9013 config->sample_rate == 16000 ||
9014 config->sample_rate == 32000 ||
9015 config->sample_rate == 48000) &&
9016 channel_count == 1) {
9017 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9018 in->config = pcm_config_audio_capture;
9019 frame_size = audio_stream_in_frame_size(&in->stream);
9020 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9021 config->sample_rate,
9022 config->format,
9023 channel_count, false /*is_low_latency*/);
9024 in->config.period_size = buffer_size / frame_size;
9025 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9026 in->config.rate = config->sample_rate;
9027 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009028 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309029 int ret_val;
9030 pthread_mutex_lock(&adev->lock);
9031 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9032 in, config, &channel_mask_updated);
9033 pthread_mutex_unlock(&adev->lock);
9034
9035 if (!ret_val) {
9036 if (channel_mask_updated == true) {
9037 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9038 __func__, config->channel_mask);
9039 ret = -EINVAL;
9040 goto err_open;
9041 }
9042 ALOGD("%s: created multi-channel session succesfully",__func__);
9043 } else if (audio_extn_compr_cap_enabled() &&
9044 audio_extn_compr_cap_format_supported(config->format) &&
9045 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9046 audio_extn_compr_cap_init(in);
9047 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309048 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309049 if (ret)
9050 goto err_open;
9051 } else {
9052 in->config = pcm_config_audio_capture;
9053 in->config.rate = config->sample_rate;
9054 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309055 in->format = config->format;
9056 frame_size = audio_stream_in_frame_size(&in->stream);
9057 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009058 config->format,
9059 channel_count,
9060 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009061 /* prevent division-by-zero */
9062 if (frame_size == 0) {
9063 ALOGE("%s: Error frame_size==0", __func__);
9064 ret = -EINVAL;
9065 goto err_open;
9066 }
9067
Revathi Uddarajud2634032017-12-07 14:42:34 +05309068 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009069 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009070
Revathi Uddarajud2634032017-12-07 14:42:34 +05309071 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9072 /* optionally use VOIP usecase depending on config(s) */
9073 ret = adev_update_voice_comm_input_stream(in, config);
9074 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009075
Revathi Uddarajud2634032017-12-07 14:42:34 +05309076 if (ret) {
9077 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9078 goto err_open;
9079 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009080 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309081 if (audio_extn_is_concurrent_capture_enabled()) {
9082 /* Acquire lock to avoid two concurrent use cases initialized to
9083 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009084
Samyak Jainc37062f2019-04-25 18:41:06 +05309085 if (in->usecase == USECASE_AUDIO_RECORD) {
9086 pthread_mutex_lock(&adev->lock);
9087 if (!(adev->pcm_record_uc_state)) {
9088 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9089 adev->pcm_record_uc_state = 1;
9090 pthread_mutex_unlock(&adev->lock);
9091 } else {
9092 pthread_mutex_unlock(&adev->lock);
9093 /* Assign compress record use case for second record */
9094 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9095 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9096 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9097 if (audio_extn_cin_applicable_stream(in)) {
9098 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309099 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309100 if (ret)
9101 goto err_open;
9102 }
9103 }
9104 }
kunleiz28c73e72019-03-27 17:24:04 +08009105 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009106 }
Ramjee Singh8b09cc12019-08-21 16:31:33 +05309107 if (audio_extn_ssr_get_stream() != in)
9108 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009109
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009110 in->sample_rate = in->config.rate;
9111
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309112 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9113 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009114 devices, flags, in->format,
9115 in->sample_rate, in->bit_width,
9116 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309117 register_format(in->format, in->supported_formats);
9118 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9119 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309120
Aalique Grahame22e49102018-12-18 14:23:57 -08009121 in->error_log = error_log_create(
9122 ERROR_LOG_ENTRIES,
9123 1000000000 /* aggregate consecutive identical errors within one second */);
9124
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009125 /* This stream could be for sound trigger lab,
9126 get sound trigger pcm if present */
9127 audio_extn_sound_trigger_check_and_get_session(in);
9128
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309129 lock_input_stream(in);
9130 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9131 pthread_mutex_lock(&adev->lock);
9132 in->card_status = adev->card_status;
9133 pthread_mutex_unlock(&adev->lock);
9134 pthread_mutex_unlock(&in->lock);
9135
Aalique Grahame22e49102018-12-18 14:23:57 -08009136 stream_app_type_cfg_init(&in->app_type_cfg);
9137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009138 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009139
9140 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9141 calloc(1, sizeof(streams_input_ctxt_t));
9142 if (in_ctxt == NULL) {
9143 ALOGE("%s fail to allocate input ctxt", __func__);
9144 ret = -ENOMEM;
9145 goto err_open;
9146 }
9147 in_ctxt->input = in;
9148
9149 pthread_mutex_lock(&adev->lock);
9150 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9151 pthread_mutex_unlock(&adev->lock);
9152
Eric Laurent994a6932013-07-17 11:51:42 -07009153 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009155
9156err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309157 if (in->usecase == USECASE_AUDIO_RECORD) {
9158 pthread_mutex_lock(&adev->lock);
9159 adev->pcm_record_uc_state = 0;
9160 pthread_mutex_unlock(&adev->lock);
9161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009162 free(in);
9163 *stream_in = NULL;
9164 return ret;
9165}
9166
9167static void adev_close_input_stream(struct audio_hw_device *dev,
9168 struct audio_stream_in *stream)
9169{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009170 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009171 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009172 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309173
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309174 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009175
kunleiz70e57612018-12-28 17:50:23 +08009176 /* must deregister from sndmonitor first to prevent races
9177 * between the callback and close_stream
9178 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309179 audio_extn_snd_mon_unregister_listener(stream);
9180
kunleiz70e57612018-12-28 17:50:23 +08009181 /* Disable echo reference if there are no active input, hfp call
9182 * and sound trigger while closing input stream
9183 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009184 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009185 !audio_extn_hfp_is_active(adev) &&
9186 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009187 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009188 else
9189 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309190
Pallavid7c7a272018-01-16 11:22:55 +05309191 if (in == NULL) {
9192 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9193 return;
9194 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009195 error_log_destroy(in->error_log);
9196 in->error_log = NULL;
9197
Pallavid7c7a272018-01-16 11:22:55 +05309198
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009199 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309200 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009201 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309202 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009203 if (ret != 0)
9204 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9205 __func__, ret);
9206 } else
9207 in_standby(&stream->common);
9208
Revathi Uddarajud2634032017-12-07 14:42:34 +05309209 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309210 if (in->usecase == USECASE_AUDIO_RECORD) {
9211 adev->pcm_record_uc_state = 0;
9212 }
9213
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009214 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009215 audio_extn_ssr_deinit();
9216 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009217
Garmond Leunge2433c32017-09-28 21:51:22 -07009218 if (audio_extn_ffv_get_stream() == in) {
9219 audio_extn_ffv_stream_deinit();
9220 }
9221
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309222 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009223 audio_extn_compr_cap_format_supported(in->config.format))
9224 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309225
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309226 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309227 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009228
Mingming Yinfd7607b2016-01-22 12:48:44 -08009229 if (in->is_st_session) {
9230 ALOGV("%s: sound trigger pcm stop lab", __func__);
9231 audio_extn_sound_trigger_stop_lab(in);
9232 }
Derek Chenf939fb72018-11-13 13:34:41 -08009233 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9234 if (in_ctxt != NULL) {
9235 list_remove(&in_ctxt->list);
9236 free(in_ctxt);
9237 } else {
9238 ALOGW("%s, input stream already closed", __func__);
9239 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009240 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309241 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009242 return;
9243}
9244
Aalique Grahame22e49102018-12-18 14:23:57 -08009245/* verifies input and output devices and their capabilities.
9246 *
9247 * This verification is required when enabling extended bit-depth or
9248 * sampling rates, as not all qcom products support it.
9249 *
9250 * Suitable for calling only on initialization such as adev_open().
9251 * It fills the audio_device use_case_table[] array.
9252 *
9253 * Has a side-effect that it needs to configure audio routing / devices
9254 * in order to power up the devices and read the device parameters.
9255 * It does not acquire any hw device lock. Should restore the devices
9256 * back to "normal state" upon completion.
9257 */
9258static int adev_verify_devices(struct audio_device *adev)
9259{
9260 /* enumeration is a bit difficult because one really wants to pull
9261 * the use_case, device id, etc from the hidden pcm_device_table[].
9262 * In this case there are the following use cases and device ids.
9263 *
9264 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9265 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9266 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9267 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9268 * [USECASE_AUDIO_RECORD] = {0, 0},
9269 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9270 * [USECASE_VOICE_CALL] = {2, 2},
9271 *
9272 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9273 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9274 */
9275
9276 /* should be the usecases enabled in adev_open_input_stream() */
9277 static const int test_in_usecases[] = {
9278 USECASE_AUDIO_RECORD,
9279 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9280 };
9281 /* should be the usecases enabled in adev_open_output_stream()*/
9282 static const int test_out_usecases[] = {
9283 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9284 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9285 };
9286 static const usecase_type_t usecase_type_by_dir[] = {
9287 PCM_PLAYBACK,
9288 PCM_CAPTURE,
9289 };
9290 static const unsigned flags_by_dir[] = {
9291 PCM_OUT,
9292 PCM_IN,
9293 };
9294
9295 size_t i;
9296 unsigned dir;
9297 const unsigned card_id = adev->snd_card;
9298
9299 for (dir = 0; dir < 2; ++dir) {
9300 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9301 const unsigned flags_dir = flags_by_dir[dir];
9302 const size_t testsize =
9303 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9304 const int *testcases =
9305 dir ? test_in_usecases : test_out_usecases;
9306 const audio_devices_t audio_device =
9307 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9308
9309 for (i = 0; i < testsize; ++i) {
9310 const audio_usecase_t audio_usecase = testcases[i];
9311 int device_id;
9312 struct pcm_params **pparams;
9313 struct stream_out out;
9314 struct stream_in in;
9315 struct audio_usecase uc_info;
9316 int retval;
9317
9318 pparams = &adev->use_case_table[audio_usecase];
9319 pcm_params_free(*pparams); /* can accept null input */
9320 *pparams = NULL;
9321
9322 /* find the device ID for the use case (signed, for error) */
9323 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9324 if (device_id < 0)
9325 continue;
9326
9327 /* prepare structures for device probing */
9328 memset(&uc_info, 0, sizeof(uc_info));
9329 uc_info.id = audio_usecase;
9330 uc_info.type = usecase_type;
9331 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009332 memset(&in, 0, sizeof(in));
9333 in.device = audio_device;
9334 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9335 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009336 }
9337 memset(&out, 0, sizeof(out));
9338 out.devices = audio_device; /* only field needed in select_devices */
9339 uc_info.stream.out = &out;
9340 uc_info.devices = audio_device;
9341 uc_info.in_snd_device = SND_DEVICE_NONE;
9342 uc_info.out_snd_device = SND_DEVICE_NONE;
9343 list_add_tail(&adev->usecase_list, &uc_info.list);
9344
9345 /* select device - similar to start_(in/out)put_stream() */
9346 retval = select_devices(adev, audio_usecase);
9347 if (retval >= 0) {
9348 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9349#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009350 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009351 if (*pparams) {
9352 ALOGV("%s: (%s) card %d device %d", __func__,
9353 dir ? "input" : "output", card_id, device_id);
9354 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9355 } else {
9356 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9357 }
9358#endif
9359 }
9360
9361 /* deselect device - similar to stop_(in/out)put_stream() */
9362 /* 1. Get and set stream specific mixer controls */
9363 retval = disable_audio_route(adev, &uc_info);
9364 /* 2. Disable the rx device */
9365 retval = disable_snd_device(adev,
9366 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9367 list_remove(&uc_info.list);
9368 }
9369 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009370 return 0;
9371}
9372
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309373int adev_create_audio_patch(struct audio_hw_device *dev,
9374 unsigned int num_sources,
9375 const struct audio_port_config *sources,
9376 unsigned int num_sinks,
9377 const struct audio_port_config *sinks,
9378 audio_patch_handle_t *handle)
9379{
Derek Chenf939fb72018-11-13 13:34:41 -08009380 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309381
Derek Chenf939fb72018-11-13 13:34:41 -08009382 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9383 num_sources,
9384 sources,
9385 num_sinks,
9386 sinks,
9387 handle);
9388 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9389 num_sources,
9390 sources,
9391 num_sinks,
9392 sinks,
9393 handle);
9394 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309395}
9396
9397int adev_release_audio_patch(struct audio_hw_device *dev,
9398 audio_patch_handle_t handle)
9399{
Derek Chenf939fb72018-11-13 13:34:41 -08009400 int ret;
9401
9402 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9403 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9404 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309405}
9406
9407int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9408{
Derek Chenf13dd492018-11-13 14:53:51 -08009409 int ret = 0;
9410
9411 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9412 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9413 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309414}
9415
9416int adev_set_audio_port_config(struct audio_hw_device *dev,
9417 const struct audio_port_config *config)
9418{
Derek Chenf13dd492018-11-13 14:53:51 -08009419 int ret = 0;
9420
9421 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9422 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9423 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309424}
9425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009426static int adev_dump(const audio_hw_device_t *device __unused,
9427 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009428{
9429 return 0;
9430}
9431
9432static int adev_close(hw_device_t *device)
9433{
Aalique Grahame22e49102018-12-18 14:23:57 -08009434 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309435 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009436
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309437 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009438 return 0;
9439
9440 pthread_mutex_lock(&adev_init_lock);
9441
9442 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309443 if (audio_extn_spkr_prot_is_enabled())
9444 audio_extn_spkr_prot_deinit();
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05309445 if (amplifier_close() != 0)
9446 ALOGE("Amplifier close failed");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309447 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009448 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009449 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009450 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009451 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309452 audio_extn_utils_release_streams_cfg_lists(
9453 &adev->streams_output_cfg_list,
9454 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309455 if (audio_extn_qap_is_enabled())
9456 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309457 if (audio_extn_qaf_is_enabled())
9458 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009459 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009460 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009461 free(adev->snd_dev_ref_cnt);
9462 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009463 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9464 pcm_params_free(adev->use_case_table[i]);
9465 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009466 if (adev->adm_deinit)
9467 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309468 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009469 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309470 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309471 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009472 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309473 if (adev->device_cfg_params) {
9474 free(adev->device_cfg_params);
9475 adev->device_cfg_params = NULL;
9476 }
Derek Chend2530072014-11-24 12:39:14 -08009477 if(adev->ext_hw_plugin)
9478 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009479 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009480 free(device);
9481 adev = NULL;
9482 }
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009483
9484 us_deinit();
9485
Kiran Kandi910e1862013-10-29 13:29:42 -07009486 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309487 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009488 return 0;
9489}
9490
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009491/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9492 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9493 * just that it _might_ work.
9494 */
9495static int period_size_is_plausible_for_low_latency(int period_size)
9496{
9497 switch (period_size) {
9498 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009499 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009500 case 240:
9501 case 320:
9502 case 480:
9503 return 1;
9504 default:
9505 return 0;
9506 }
9507}
9508
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309509static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9510{
9511 bool is_snd_card_status = false;
9512 bool is_ext_device_status = false;
9513 char value[32];
9514 int card = -1;
9515 card_status_t status;
9516
9517 if (cookie != adev || !parms)
9518 return;
9519
9520 if (!parse_snd_card_status(parms, &card, &status)) {
9521 is_snd_card_status = true;
9522 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9523 is_ext_device_status = true;
9524 } else {
9525 // not a valid event
9526 return;
9527 }
9528
9529 pthread_mutex_lock(&adev->lock);
9530 if (card == adev->snd_card || is_ext_device_status) {
9531 if (is_snd_card_status && adev->card_status != status) {
9532 adev->card_status = status;
9533 platform_snd_card_update(adev->platform, status);
9534 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009535 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song5f7908f2019-07-02 00:32:23 +08009536 if (status == CARD_STATUS_OFFLINE)
9537 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309538 } else if (is_ext_device_status) {
9539 platform_set_parameters(adev->platform, parms);
9540 }
9541 }
9542 pthread_mutex_unlock(&adev->lock);
9543 return;
9544}
9545
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309546/* out and adev lock held */
9547static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9548{
9549 struct audio_usecase *uc_info;
9550 float left_p;
9551 float right_p;
9552 audio_devices_t devices;
9553
9554 uc_info = get_usecase_from_list(adev, out->usecase);
9555 if (uc_info == NULL) {
9556 ALOGE("%s: Could not find the usecase (%d) in the list",
9557 __func__, out->usecase);
9558 return -EINVAL;
9559 }
9560
9561 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9562 out->usecase, use_case_table[out->usecase]);
9563
9564 if (restore) {
9565 // restore A2DP device for active usecases and unmute if required
9566 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9567 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9568 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9569 select_devices(adev, uc_info->id);
9570 pthread_mutex_lock(&out->compr_mute_lock);
9571 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05309572 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309573 out->a2dp_compress_mute = false;
9574 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9575 }
9576 pthread_mutex_unlock(&out->compr_mute_lock);
9577 }
9578 } else {
Zhou Song28023002019-09-09 14:17:40 +08009579 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
9580 // mute compress stream if suspended
9581 pthread_mutex_lock(&out->compr_mute_lock);
9582 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309583 ALOGD("%s: selecting speaker and muting stream", __func__);
9584 devices = out->devices;
9585 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9586 left_p = out->volume_l;
9587 right_p = out->volume_r;
9588 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9589 compress_pause(out->compr);
9590 out_set_compr_volume(&out->stream, (float)0, (float)0);
9591 out->a2dp_compress_mute = true;
9592 select_devices(adev, out->usecase);
9593 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9594 compress_resume(out->compr);
9595 out->devices = devices;
9596 out->volume_l = left_p;
9597 out->volume_r = right_p;
9598 }
Zhou Song28023002019-09-09 14:17:40 +08009599 pthread_mutex_unlock(&out->compr_mute_lock);
9600 } else {
9601 // tear down a2dp path for non offloaded streams
9602 if (audio_extn_a2dp_source_is_suspended())
9603 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309604 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309605 }
9606 ALOGV("%s: exit", __func__);
9607 return 0;
9608}
9609
9610int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9611{
9612 int ret = 0;
9613
9614 lock_output_stream(out);
9615 pthread_mutex_lock(&adev->lock);
9616
9617 ret = check_a2dp_restore_l(adev, out, restore);
9618
9619 pthread_mutex_unlock(&adev->lock);
9620 pthread_mutex_unlock(&out->lock);
9621 return ret;
9622}
9623
Haynes Mathew George01156f92018-04-13 15:29:54 -07009624void adev_on_battery_status_changed(bool charging)
9625{
9626 pthread_mutex_lock(&adev->lock);
9627 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9628 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009629 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009630 pthread_mutex_unlock(&adev->lock);
9631}
9632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009633static int adev_open(const hw_module_t *module, const char *name,
9634 hw_device_t **device)
9635{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309636 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009637 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309638 char mixer_ctl_name[128] = {0};
9639 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309640
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009641 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009642 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9643
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009644 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009645 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009646 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009647 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009648 ALOGD("%s: returning existing instance of adev", __func__);
9649 ALOGD("%s: exit", __func__);
9650 pthread_mutex_unlock(&adev_init_lock);
9651 return 0;
9652 }
9653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009654 adev = calloc(1, sizeof(struct audio_device));
9655
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009656 if (!adev) {
9657 pthread_mutex_unlock(&adev_init_lock);
9658 return -ENOMEM;
9659 }
9660
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009661 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9662
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009663 // register audio ext hidl at the earliest
9664 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309665#ifdef DYNAMIC_LOG_ENABLED
9666 register_for_dynamic_logging("hal");
9667#endif
9668
Derek Chenf939fb72018-11-13 13:34:41 -08009669 /* default audio HAL major version */
9670 uint32_t maj_version = 2;
9671 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9672 maj_version = atoi(value);
9673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009674 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009675 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009676 adev->device.common.module = (struct hw_module_t *)module;
9677 adev->device.common.close = adev_close;
9678
9679 adev->device.init_check = adev_init_check;
9680 adev->device.set_voice_volume = adev_set_voice_volume;
9681 adev->device.set_master_volume = adev_set_master_volume;
9682 adev->device.get_master_volume = adev_get_master_volume;
9683 adev->device.set_master_mute = adev_set_master_mute;
9684 adev->device.get_master_mute = adev_get_master_mute;
9685 adev->device.set_mode = adev_set_mode;
9686 adev->device.set_mic_mute = adev_set_mic_mute;
9687 adev->device.get_mic_mute = adev_get_mic_mute;
9688 adev->device.set_parameters = adev_set_parameters;
9689 adev->device.get_parameters = adev_get_parameters;
9690 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9691 adev->device.open_output_stream = adev_open_output_stream;
9692 adev->device.close_output_stream = adev_close_output_stream;
9693 adev->device.open_input_stream = adev_open_input_stream;
9694 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309695 adev->device.create_audio_patch = adev_create_audio_patch;
9696 adev->device.release_audio_patch = adev_release_audio_patch;
9697 adev->device.get_audio_port = adev_get_audio_port;
9698 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009699 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309700 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009701
9702 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009703 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009704 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009705 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009706 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009707 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009708 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309709 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009710 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009711 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009712 /* Init audio and voice feature */
9713 audio_extn_feature_init();
9714 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009715 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009716 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009717 list_init(&adev->active_inputs_list);
9718 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +05309719 list_init(&adev->audio_patch_record_list);
9720 adev->audio_patch_index = 0;
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009721 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009722 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309723 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309724 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309725 adev->perf_lock_opts[0] = 0x101;
9726 adev->perf_lock_opts[1] = 0x20E;
9727 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009728 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009729 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309730 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009731 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009733 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009734 adev->platform = platform_init(adev);
9735 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009736 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009737 free(adev->snd_dev_ref_cnt);
9738 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009739 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009740 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9741 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009742 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009743 return -EINVAL;
9744 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009745
Aalique Grahame22e49102018-12-18 14:23:57 -08009746 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309747 if (audio_extn_qap_is_enabled()) {
9748 ret = audio_extn_qap_init(adev);
9749 if (ret < 0) {
9750 pthread_mutex_destroy(&adev->lock);
9751 free(adev);
9752 adev = NULL;
9753 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9754 *device = NULL;
9755 pthread_mutex_unlock(&adev_init_lock);
9756 return ret;
9757 }
9758 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
9759 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
9760 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009761
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309762 if (audio_extn_qaf_is_enabled()) {
9763 ret = audio_extn_qaf_init(adev);
9764 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009765 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309766 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009767 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309768 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9769 *device = NULL;
9770 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309771 return ret;
9772 }
9773
9774 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9775 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9776 }
9777
Derek Chenae7b0342019-02-08 15:17:04 -08009778 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009779 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9780
Eric Laurentc4aef752013-09-12 17:45:53 -07009781 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9782 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9783 if (adev->visualizer_lib == NULL) {
9784 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9785 } else {
9786 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9787 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009788 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009789 "visualizer_hal_start_output");
9790 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009791 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009792 "visualizer_hal_stop_output");
9793 }
9794 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309795 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009796 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009797 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009798 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309799 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009800 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009801
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009802 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9803 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9804 if (adev->offload_effects_lib == NULL) {
9805 ALOGE("%s: DLOPEN failed for %s", __func__,
9806 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9807 } else {
9808 ALOGV("%s: DLOPEN successful for %s", __func__,
9809 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9810 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309811 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009812 "offload_effects_bundle_hal_start_output");
9813 adev->offload_effects_stop_output =
9814 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9815 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009816 adev->offload_effects_set_hpx_state =
9817 (int (*)(bool))dlsym(adev->offload_effects_lib,
9818 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309819 adev->offload_effects_get_parameters =
9820 (void (*)(struct str_parms *, struct str_parms *))
9821 dlsym(adev->offload_effects_lib,
9822 "offload_effects_bundle_get_parameters");
9823 adev->offload_effects_set_parameters =
9824 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9825 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009826 }
9827 }
9828
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009829 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9830 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9831 if (adev->adm_lib == NULL) {
9832 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9833 } else {
9834 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9835 adev->adm_init = (adm_init_t)
9836 dlsym(adev->adm_lib, "adm_init");
9837 adev->adm_deinit = (adm_deinit_t)
9838 dlsym(adev->adm_lib, "adm_deinit");
9839 adev->adm_register_input_stream = (adm_register_input_stream_t)
9840 dlsym(adev->adm_lib, "adm_register_input_stream");
9841 adev->adm_register_output_stream = (adm_register_output_stream_t)
9842 dlsym(adev->adm_lib, "adm_register_output_stream");
9843 adev->adm_deregister_stream = (adm_deregister_stream_t)
9844 dlsym(adev->adm_lib, "adm_deregister_stream");
9845 adev->adm_request_focus = (adm_request_focus_t)
9846 dlsym(adev->adm_lib, "adm_request_focus");
9847 adev->adm_abandon_focus = (adm_abandon_focus_t)
9848 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009849 adev->adm_set_config = (adm_set_config_t)
9850 dlsym(adev->adm_lib, "adm_set_config");
9851 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9852 dlsym(adev->adm_lib, "adm_request_focus_v2");
9853 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9854 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9855 adev->adm_on_routing_change = (adm_on_routing_change_t)
9856 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009857 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9858 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009859 }
9860 }
9861
Aalique Grahame22e49102018-12-18 14:23:57 -08009862 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009863 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009864 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009865 //initialize this to false for now,
9866 //this will be set to true through set param
9867 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009868
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009869 audio_extn_ds2_enable(adev);
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009870
Daniel Hillenbrandc16d8dd2013-05-23 10:10:00 +05309871 if (amplifier_open(adev) != 0)
9872 ALOGE("Amplifier initialization failed");
9873
Balázs Triszkaa68afd52017-05-11 03:19:29 +02009874 us_init(adev);
9875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009876 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009877
9878 if (k_enable_extended_precision)
9879 adev_verify_devices(adev);
9880
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009881 adev->dsp_bit_width_enforce_mode =
9882 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009883
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309884 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9885 &adev->streams_output_cfg_list,
9886 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009887
Kiran Kandi910e1862013-10-29 13:29:42 -07009888 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009889
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009890 int trial;
Manisha Agarwalbce6f6a2019-12-06 18:48:25 +05309891 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009892 trial = atoi(value);
9893 if (period_size_is_plausible_for_low_latency(trial)) {
9894 pcm_config_low_latency.period_size = trial;
9895 pcm_config_low_latency.start_threshold = trial / 4;
9896 pcm_config_low_latency.avail_min = trial / 4;
9897 configured_low_latency_capture_period_size = trial;
9898 }
9899 }
Michael Bestas5dcabd22020-03-14 19:36:11 +02009900 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009901 trial = atoi(value);
9902 if (period_size_is_plausible_for_low_latency(trial)) {
9903 configured_low_latency_capture_period_size = trial;
9904 }
9905 }
9906
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009907 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9908
Eric Laurent4b084132018-10-19 17:33:43 -07009909 adev->camera_orientation = CAMERA_DEFAULT;
9910
Manisha Agarwalbce6f6a2019-12-06 18:48:25 +05309911 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009912 af_period_multiplier = atoi(value);
9913 if (af_period_multiplier < 0)
9914 af_period_multiplier = 2;
9915 else if (af_period_multiplier > 4)
9916 af_period_multiplier = 4;
9917
9918 ALOGV("new period_multiplier = %d", af_period_multiplier);
9919 }
9920
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009921 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009922
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009923 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009924 pthread_mutex_unlock(&adev_init_lock);
9925
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009926 if (adev->adm_init)
9927 adev->adm_data = adev->adm_init();
9928
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309929 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309930 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009931 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309932
9933 audio_extn_snd_mon_init();
9934 pthread_mutex_lock(&adev->lock);
9935 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9936 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009937 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9938 /*
9939 * if the battery state callback happens before charging can be queried,
9940 * it will be guarded with the adev->lock held in the cb function and so
9941 * the callback value will reflect the latest state
9942 */
9943 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309944 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009945 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009946 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009947 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309948 /* Allocate memory for Device config params */
9949 adev->device_cfg_params = (struct audio_device_config_param*)
9950 calloc(platform_get_max_codec_backend(),
9951 sizeof(struct audio_device_config_param));
9952 if (adev->device_cfg_params == NULL)
9953 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309954
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309955 /*
9956 * Check if new PSPD matrix mixer control is supported. If not
9957 * supported, then set flag so that old mixer ctrl is sent while
9958 * sending pspd coefficients on older kernel version. Query mixer
9959 * control for default pcm id and channel value one.
9960 */
9961 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9962 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9963
9964 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9965 if (!ctl) {
9966 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9967 __func__, mixer_ctl_name);
9968 adev->use_old_pspd_mix_ctrl = true;
9969 }
9970
Eric Laurent994a6932013-07-17 11:51:42 -07009971 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009972 return 0;
9973}
9974
9975static struct hw_module_methods_t hal_module_methods = {
9976 .open = adev_open,
9977};
9978
9979struct audio_module HAL_MODULE_INFO_SYM = {
9980 .common = {
9981 .tag = HARDWARE_MODULE_TAG,
9982 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9983 .hal_api_version = HARDWARE_HAL_API_VERSION,
9984 .id = AUDIO_HARDWARE_MODULE_ID,
9985 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009986 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009987 .methods = &hal_module_methods,
9988 },
9989};