blob: 50e505b64ad8b3c361d81e9b74c1e223f08554c6 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053076#include "ip_hdlr_intf.h"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080077#include "audio_feature_manager.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053093#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053094#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070095
Aalique Grahame22e49102018-12-18 14:23:57 -080096#define RECORD_GAIN_MIN 0.0f
97#define RECORD_GAIN_MAX 1.0f
98#define RECORD_VOLUME_CTL_MAX 0x2000
99
100/* treat as unsigned Q1.13 */
101#define APP_TYPE_GAIN_DEFAULT 0x2000
102
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700103#define PROXY_OPEN_RETRY_COUNT 100
104#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800105
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800106#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
107 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
108 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
109#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
110 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800111
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700112#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700113#define DEFAULT_VOIP_BUF_DURATION_MS 20
114#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
115#define DEFAULT_VOIP_SAMP_RATE 48000
116
117#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
118
119struct pcm_config default_pcm_config_voip_copp = {
120 .channels = 1,
121 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
122 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
123 .period_count = 2,
124 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800125 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
126 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700127};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700128
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700129#define MIN_CHANNEL_COUNT 1
130#define DEFAULT_CHANNEL_COUNT 2
131#define MAX_HIFI_CHANNEL_COUNT 8
132
Aalique Grahame22e49102018-12-18 14:23:57 -0800133#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
134#define MAX_CHANNEL_COUNT 1
135#else
136#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
137#define XSTR(x) STR(x)
138#define STR(x) #x
139#endif
140
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700141static unsigned int configured_low_latency_capture_period_size =
142 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
143
Haynes Mathew George16081042017-05-31 17:16:49 -0700144#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
145#define MMAP_PERIOD_COUNT_MIN 32
146#define MMAP_PERIOD_COUNT_MAX 512
147#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
148
Aalique Grahame22e49102018-12-18 14:23:57 -0800149/* This constant enables extended precision handling.
150 * TODO The flag is off until more testing is done.
151 */
152static const bool k_enable_extended_precision = false;
153
Eric Laurentb23d5282013-05-14 15:27:20 -0700154struct pcm_config pcm_config_deep_buffer = {
155 .channels = 2,
156 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
157 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
158 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
161 .stop_threshold = INT_MAX,
162 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
163};
164
165struct pcm_config pcm_config_low_latency = {
166 .channels = 2,
167 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
168 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
169 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
172 .stop_threshold = INT_MAX,
173 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
174};
175
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800176struct pcm_config pcm_config_haptics_audio = {
177 .channels = 1,
178 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
179 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
180 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
183 .stop_threshold = INT_MAX,
184 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185};
186
187struct pcm_config pcm_config_haptics = {
188 .channels = 1,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
191 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .stop_threshold = INT_MAX,
195 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
196};
197
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700198static int af_period_multiplier = 4;
199struct pcm_config pcm_config_rt = {
200 .channels = 2,
201 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
202 .period_size = ULL_PERIOD_SIZE, //1 ms
203 .period_count = 512, //=> buffer size is 512ms
204 .format = PCM_FORMAT_S16_LE,
205 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
206 .stop_threshold = INT_MAX,
207 .silence_threshold = 0,
208 .silence_size = 0,
209 .avail_min = ULL_PERIOD_SIZE, //1 ms
210};
211
Eric Laurentb23d5282013-05-14 15:27:20 -0700212struct pcm_config pcm_config_hdmi_multi = {
213 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
215 .period_size = HDMI_MULTI_PERIOD_SIZE,
216 .period_count = HDMI_MULTI_PERIOD_COUNT,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = 0,
219 .stop_threshold = INT_MAX,
220 .avail_min = 0,
221};
222
Haynes Mathew George16081042017-05-31 17:16:49 -0700223struct pcm_config pcm_config_mmap_playback = {
224 .channels = 2,
225 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
226 .period_size = MMAP_PERIOD_SIZE,
227 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
228 .format = PCM_FORMAT_S16_LE,
229 .start_threshold = MMAP_PERIOD_SIZE*8,
230 .stop_threshold = INT32_MAX,
231 .silence_threshold = 0,
232 .silence_size = 0,
233 .avail_min = MMAP_PERIOD_SIZE, //1 ms
234};
235
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700236struct pcm_config pcm_config_hifi = {
237 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
238 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
239 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
240 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
241 .format = PCM_FORMAT_S24_3LE,
242 .start_threshold = 0,
243 .stop_threshold = INT_MAX,
244 .avail_min = 0,
245};
246
Eric Laurentb23d5282013-05-14 15:27:20 -0700247struct pcm_config pcm_config_audio_capture = {
248 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700249 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251};
252
Haynes Mathew George16081042017-05-31 17:16:49 -0700253struct pcm_config pcm_config_mmap_capture = {
254 .channels = 2,
255 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
256 .period_size = MMAP_PERIOD_SIZE,
257 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
258 .format = PCM_FORMAT_S16_LE,
259 .start_threshold = 0,
260 .stop_threshold = INT_MAX,
261 .silence_threshold = 0,
262 .silence_size = 0,
263 .avail_min = MMAP_PERIOD_SIZE, //1 ms
264};
265
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700266#define AFE_PROXY_CHANNEL_COUNT 2
267#define AFE_PROXY_SAMPLING_RATE 48000
268
269#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
270#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
271
272struct pcm_config pcm_config_afe_proxy_playback = {
273 .channels = AFE_PROXY_CHANNEL_COUNT,
274 .rate = AFE_PROXY_SAMPLING_RATE,
275 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
276 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
277 .format = PCM_FORMAT_S16_LE,
278 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
279 .stop_threshold = INT_MAX,
280 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281};
282
283#define AFE_PROXY_RECORD_PERIOD_SIZE 768
284#define AFE_PROXY_RECORD_PERIOD_COUNT 4
285
Aalique Grahame22e49102018-12-18 14:23:57 -0800286struct pcm_config pcm_config_audio_capture_rt = {
287 .channels = 2,
288 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
289 .period_size = ULL_PERIOD_SIZE,
290 .period_count = 512,
291 .format = PCM_FORMAT_S16_LE,
292 .start_threshold = 0,
293 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
294 .silence_threshold = 0,
295 .silence_size = 0,
296 .avail_min = ULL_PERIOD_SIZE, //1 ms
297};
298
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700299struct pcm_config pcm_config_afe_proxy_record = {
300 .channels = AFE_PROXY_CHANNEL_COUNT,
301 .rate = AFE_PROXY_SAMPLING_RATE,
302 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
303 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
304 .format = PCM_FORMAT_S16_LE,
305 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
306 .stop_threshold = INT_MAX,
307 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
308};
309
Ashish Jainf1eaa582016-05-23 20:54:24 +0530310#define AUDIO_MAX_PCM_FORMATS 7
311
312const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
313 [AUDIO_FORMAT_DEFAULT] = 0,
314 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
315 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
316 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
317 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
318 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
319 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
320};
321
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800322const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700323 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
324 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800325 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700326 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
327 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700328 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700329 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700330 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
331 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
332 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
333 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700338 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
339 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700340 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800341 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700342
Eric Laurentb23d5282013-05-14 15:27:20 -0700343 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700344 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530345 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
346 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
347 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530348 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
349 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700350 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700351 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700352 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700353 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700354
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800355 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800356 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700357 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700358
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700359 [USECASE_VOICE2_CALL] = "voice2-call",
360 [USECASE_VOLTE_CALL] = "volte-call",
361 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800362 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800363 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
364 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800365 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700366 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
367 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
368 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800369 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
370 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
371 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
372
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700373 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
374 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700375 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
376 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700377
378 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
379 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530380 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700381
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530382 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530383 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
384 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700385
386 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
387 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530388 /* For Interactive Audio Streams */
389 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
390 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
391 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700397
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800398 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
399
400 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700401};
402
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700403static const audio_usecase_t offload_usecases[] = {
404 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700405 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
406 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
407 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
408 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700413};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800414
Varun Balaraje49253e2017-07-06 19:48:56 +0530415static const audio_usecase_t interactive_usecases[] = {
416 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
417 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
418 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
424};
425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800426#define STRING_TO_ENUM(string) { #string, string }
427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428struct string_to_enum {
429 const char *name;
430 uint32_t value;
431};
432
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700433static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800435 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
436 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700442 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
443 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
444 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
445 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
446 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
447 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800453};
454
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455static const struct string_to_enum formats_name_to_enum_table[] = {
456 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
457 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
458 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700459 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
460 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
461 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700462 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800463 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
464 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700465 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800466};
467
468//list of all supported sample rates by HDMI specification.
469static const int out_hdmi_sample_rates[] = {
470 32000, 44100, 48000, 88200, 96000, 176400, 192000,
471};
472
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700473static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800474 STRING_TO_ENUM(32000),
475 STRING_TO_ENUM(44100),
476 STRING_TO_ENUM(48000),
477 STRING_TO_ENUM(88200),
478 STRING_TO_ENUM(96000),
479 STRING_TO_ENUM(176400),
480 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700481};
482
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700483static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700484static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700485static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700486//cache last MBDRC cal step level
487static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700488
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530489static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
490static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800491static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530492static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530493
Vatsal Buchac09ae062018-11-14 13:25:08 +0530494#ifdef AUDIO_FEATURE_ENABLED_GCOV
495extern void __gcov_flush();
496static void enable_gcov()
497{
498 __gcov_flush();
499}
500#else
501static void enable_gcov()
502{
503}
504#endif
505
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700506static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
507 int flags __unused)
508{
509 int dir = 0;
510 switch (uc_id) {
511 case USECASE_AUDIO_RECORD_LOW_LATENCY:
512 dir = 1;
513 case USECASE_AUDIO_PLAYBACK_ULL:
514 break;
515 default:
516 return false;
517 }
518
519 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
520 PCM_PLAYBACK : PCM_CAPTURE);
521 if (adev->adm_is_noirq_avail)
522 return adev->adm_is_noirq_avail(adev->adm_data,
523 adev->snd_card, dev_id, dir);
524 return false;
525}
526
527static void register_out_stream(struct stream_out *out)
528{
529 struct audio_device *adev = out->dev;
530 if (is_offload_usecase(out->usecase) ||
531 !adev->adm_register_output_stream)
532 return;
533
534 // register stream first for backward compatibility
535 adev->adm_register_output_stream(adev->adm_data,
536 out->handle,
537 out->flags);
538
539 if (!adev->adm_set_config)
540 return;
541
542 if (out->realtime)
543 adev->adm_set_config(adev->adm_data,
544 out->handle,
545 out->pcm, &out->config);
546}
547
548static void register_in_stream(struct stream_in *in)
549{
550 struct audio_device *adev = in->dev;
551 if (!adev->adm_register_input_stream)
552 return;
553
554 adev->adm_register_input_stream(adev->adm_data,
555 in->capture_handle,
556 in->flags);
557
558 if (!adev->adm_set_config)
559 return;
560
561 if (in->realtime)
562 adev->adm_set_config(adev->adm_data,
563 in->capture_handle,
564 in->pcm,
565 &in->config);
566}
567
568static void request_out_focus(struct stream_out *out, long ns)
569{
570 struct audio_device *adev = out->dev;
571
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700572 if (adev->adm_request_focus_v2)
573 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
574 else if (adev->adm_request_focus)
575 adev->adm_request_focus(adev->adm_data, out->handle);
576}
577
578static void request_in_focus(struct stream_in *in, long ns)
579{
580 struct audio_device *adev = in->dev;
581
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700582 if (adev->adm_request_focus_v2)
583 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
584 else if (adev->adm_request_focus)
585 adev->adm_request_focus(adev->adm_data, in->capture_handle);
586}
587
588static void release_out_focus(struct stream_out *out)
589{
590 struct audio_device *adev = out->dev;
591
592 if (adev->adm_abandon_focus)
593 adev->adm_abandon_focus(adev->adm_data, out->handle);
594}
595
596static void release_in_focus(struct stream_in *in)
597{
598 struct audio_device *adev = in->dev;
599 if (adev->adm_abandon_focus)
600 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
601}
602
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530603static int parse_snd_card_status(struct str_parms *parms, int *card,
604 card_status_t *status)
605{
606 char value[32]={0};
607 char state[32]={0};
608
609 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
610 if (ret < 0)
611 return -1;
612
613 // sscanf should be okay as value is of max length 32.
614 // same as sizeof state.
615 if (sscanf(value, "%d,%s", card, state) < 2)
616 return -1;
617
618 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
619 CARD_STATUS_OFFLINE;
620 return 0;
621}
622
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700623static inline void adjust_frames_for_device_delay(struct stream_out *out,
624 uint32_t *dsp_frames) {
625 // Adjustment accounts for A2dp encoder latency with offload usecases
626 // Note: Encoder latency is returned in ms.
627 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
628 unsigned long offset =
629 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
630 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
631 }
632}
633
vivek mehtaa76401a2015-04-24 14:12:15 -0700634__attribute__ ((visibility ("default")))
635bool audio_hw_send_gain_dep_calibration(int level) {
636 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700637 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700638
639 pthread_mutex_lock(&adev_init_lock);
640
641 if (adev != NULL && adev->platform != NULL) {
642 pthread_mutex_lock(&adev->lock);
643 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700644
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530645 // cache level info for any of the use case which
646 // was not started.
647 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700648
vivek mehtaa76401a2015-04-24 14:12:15 -0700649 pthread_mutex_unlock(&adev->lock);
650 } else {
651 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
652 }
653
654 pthread_mutex_unlock(&adev_init_lock);
655
656 return ret_val;
657}
658
Ashish Jain5106d362016-05-11 19:23:33 +0530659static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
660{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800661 bool gapless_enabled = false;
662 const char *mixer_ctl_name = "Compress Gapless Playback";
663 struct mixer_ctl *ctl;
664
665 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700666 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530667
668 /*Disable gapless if its AV playback*/
669 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800670
671 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
672 if (!ctl) {
673 ALOGE("%s: Could not get ctl for mixer cmd - %s",
674 __func__, mixer_ctl_name);
675 return -EINVAL;
676 }
677
678 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
679 ALOGE("%s: Could not set gapless mode %d",
680 __func__, gapless_enabled);
681 return -EINVAL;
682 }
683 return 0;
684}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700685
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700686__attribute__ ((visibility ("default")))
687int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
688 int table_size) {
689 int ret_val = 0;
690 ALOGV("%s: enter ... ", __func__);
691
692 pthread_mutex_lock(&adev_init_lock);
693 if (adev == NULL) {
694 ALOGW("%s: adev is NULL .... ", __func__);
695 goto done;
696 }
697
698 pthread_mutex_lock(&adev->lock);
699 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
700 pthread_mutex_unlock(&adev->lock);
701done:
702 pthread_mutex_unlock(&adev_init_lock);
703 ALOGV("%s: exit ... ", __func__);
704 return ret_val;
705}
706
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800707bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800708{
709 bool ret = false;
710 ALOGV("%s: enter ...", __func__);
711
712 pthread_mutex_lock(&adev_init_lock);
713
714 if (adev != NULL && adev->platform != NULL) {
715 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800716 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800717 pthread_mutex_unlock(&adev->lock);
718 }
719
720 pthread_mutex_unlock(&adev_init_lock);
721
722 ALOGV("%s: exit with ret %d", __func__, ret);
723 return ret;
724}
Aalique Grahame22e49102018-12-18 14:23:57 -0800725
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700726static bool is_supported_format(audio_format_t format)
727{
Eric Laurent86e17132013-09-12 17:49:30 -0700728 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530729 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530730 format == AUDIO_FORMAT_AAC_LC ||
731 format == AUDIO_FORMAT_AAC_HE_V1 ||
732 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530733 format == AUDIO_FORMAT_AAC_ADTS_LC ||
734 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
735 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530736 format == AUDIO_FORMAT_AAC_LATM_LC ||
737 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
738 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530739 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
740 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530741 format == AUDIO_FORMAT_PCM_FLOAT ||
742 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700743 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530744 format == AUDIO_FORMAT_AC3 ||
745 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700746 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530747 format == AUDIO_FORMAT_DTS ||
748 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800749 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530750 format == AUDIO_FORMAT_ALAC ||
751 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530752 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530753 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800754 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530755 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700756 format == AUDIO_FORMAT_APTX ||
757 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800758 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700759
760 return false;
761}
762
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700763static inline bool is_mmap_usecase(audio_usecase_t uc_id)
764{
765 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
766 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
767}
768
Avinash Vaish71a8b972014-07-24 15:36:33 +0530769static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
770 struct audio_usecase *uc_info)
771{
772 struct listnode *node;
773 struct audio_usecase *usecase;
774
775 if (uc_info == NULL)
776 return -EINVAL;
777
778 /* Re-route all voice usecases on the shared backend other than the
779 specified usecase to new snd devices */
780 list_for_each(node, &adev->usecase_list) {
781 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800782 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530783 enable_audio_route(adev, usecase);
784 }
785 return 0;
786}
787
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530788static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530789{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530790 ALOGV("%s", __func__);
791 audio_route_apply_and_update_path(adev->audio_route,
792 "asrc-mode");
793 adev->asrc_mode_enabled = true;
794}
795
796static void disable_asrc_mode(struct audio_device *adev)
797{
798 ALOGV("%s", __func__);
799 audio_route_reset_and_update_path(adev->audio_route,
800 "asrc-mode");
801 adev->asrc_mode_enabled = false;
802}
803
804/*
805 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
806 * 44.1 or Native DSD backends are enabled for any of current use case.
807 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
808 * - Disable current mix path use case(Headphone backend) and re-enable it with
809 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
810 * e.g. Naitve DSD or Headphone 44.1 -> + 48
811 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530812static void check_and_set_asrc_mode(struct audio_device *adev,
813 struct audio_usecase *uc_info,
814 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530815{
816 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530817 int i, num_new_devices = 0;
818 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
819 /*
820 *Split snd device for new combo use case
821 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
822 */
823 if (platform_split_snd_device(adev->platform,
824 snd_device,
825 &num_new_devices,
826 split_new_snd_devices) == 0) {
827 for (i = 0; i < num_new_devices; i++)
828 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
829 } else {
830 int new_backend_idx = platform_get_backend_index(snd_device);
831 if (((new_backend_idx == HEADPHONE_BACKEND) ||
832 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
833 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
834 !adev->asrc_mode_enabled) {
835 struct listnode *node = NULL;
836 struct audio_usecase *uc = NULL;
837 struct stream_out *curr_out = NULL;
838 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
839 int i, num_devices, ret = 0;
840 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530841
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530842 list_for_each(node, &adev->usecase_list) {
843 uc = node_to_item(node, struct audio_usecase, list);
844 curr_out = (struct stream_out*) uc->stream.out;
845 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
846 /*
847 *Split snd device for existing combo use case
848 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
849 */
850 ret = platform_split_snd_device(adev->platform,
851 uc->out_snd_device,
852 &num_devices,
853 split_snd_devices);
854 if (ret < 0 || num_devices == 0) {
855 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
856 split_snd_devices[0] = uc->out_snd_device;
857 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800858 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530859 for (i = 0; i < num_devices; i++) {
860 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
861 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
862 if((new_backend_idx == HEADPHONE_BACKEND) &&
863 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
864 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
865 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
866 __func__);
867 enable_asrc_mode(adev);
868 break;
869 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
870 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
871 (usecase_backend_idx == HEADPHONE_BACKEND)) {
872 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
873 __func__);
874 disable_audio_route(adev, uc);
875 disable_snd_device(adev, uc->out_snd_device);
876 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
877 if (new_backend_idx == DSD_NATIVE_BACKEND)
878 audio_route_apply_and_update_path(adev->audio_route,
879 "hph-true-highquality-mode");
880 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
881 (curr_out->bit_width >= 24))
882 audio_route_apply_and_update_path(adev->audio_route,
883 "hph-highquality-mode");
884 enable_asrc_mode(adev);
885 enable_snd_device(adev, uc->out_snd_device);
886 enable_audio_route(adev, uc);
887 break;
888 }
889 }
890 // reset split devices count
891 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800892 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530893 if (adev->asrc_mode_enabled)
894 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530895 }
896 }
897 }
898}
899
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700900static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
901 struct audio_effect_config effect_config,
902 unsigned int param_value)
903{
904 char mixer_ctl_name[] = "Audio Effect";
905 struct mixer_ctl *ctl;
906 long set_values[6];
907 struct stream_in *in = adev->active_input;
908
909 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
910 if (!ctl) {
911 ALOGE("%s: Could not get mixer ctl - %s",
912 __func__, mixer_ctl_name);
913 return -EINVAL;
914 }
915
916 set_values[0] = 1; //0:Rx 1:Tx
917 set_values[1] = in->app_type_cfg.app_type;
918 set_values[2] = (long)effect_config.module_id;
919 set_values[3] = (long)effect_config.instance_id;
920 set_values[4] = (long)effect_config.param_id;
921 set_values[5] = param_value;
922
923 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
924
925 return 0;
926
927}
928
929static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
930 int effect_type, unsigned int *param_value)
931{
932 int ret = 0;
933 struct audio_effect_config other_effect_config;
934 struct audio_usecase *usecase = NULL;
935 struct stream_in *in = adev->active_input;
936
937 usecase = get_usecase_from_list(adev, in->usecase);
938 if (!usecase)
939 return -EINVAL;
940
941 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
942 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
943 if (ret < 0) {
944 ALOGE("%s Failed to get effect params %d", __func__, ret);
945 return ret;
946 }
947
948 if (module_id == other_effect_config.module_id) {
949 //Same module id for AEC/NS. Values need to be combined
950 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
951 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
952 *param_value |= other_effect_config.param_value;
953 }
954 }
955
956 return ret;
957}
958
959static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800960{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700961 struct audio_effect_config effect_config;
962 struct audio_usecase *usecase = NULL;
963 int ret = 0;
964 unsigned int param_value = 0;
965 struct stream_in *in = adev->active_input;
966
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800967 if(!voice_extn_is_dynamic_ecns_enabled())
968 return ENOSYS;
969
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700970 if (!in) {
971 ALOGE("%s: Invalid input stream", __func__);
972 return -EINVAL;
973 }
974
975 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
976
977 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800978 if (usecase == NULL) {
979 ALOGE("%s: Could not find the usecase (%d) in the list",
980 __func__, in->usecase);
981 return -EINVAL;
982 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700983
984 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
985 if (ret < 0) {
986 ALOGE("%s Failed to get module id %d", __func__, ret);
987 return ret;
988 }
989 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
990 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
991
992 if(enable)
993 param_value = effect_config.param_value;
994
995 /*Special handling for AEC & NS effects Param values need to be
996 updated if module ids are same*/
997
998 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
999 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1000 if (ret < 0)
1001 return ret;
1002 }
1003
1004 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1005
1006 return ret;
1007}
1008
1009static void check_and_enable_effect(struct audio_device *adev)
1010{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001011 if(!voice_extn_is_dynamic_ecns_enabled())
1012 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001013
1014 if (adev->active_input->enable_aec) {
1015 enable_disable_effect(adev, EFFECT_AEC, true);
1016 }
1017
1018 if (adev->active_input->enable_ns &&
1019 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1020 enable_disable_effect(adev, EFFECT_NS, true);
1021 }
1022}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001023
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001024int pcm_ioctl(struct pcm *pcm, int request, ...)
1025{
1026 va_list ap;
1027 void * arg;
1028 int pcm_fd = *(int*)pcm;
1029
1030 va_start(ap, request);
1031 arg = va_arg(ap, void *);
1032 va_end(ap);
1033
1034 return ioctl(pcm_fd, request, arg);
1035}
1036
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001037int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001038 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001041 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301042 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301043 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001044
1045 if (usecase == NULL)
1046 return -EINVAL;
1047
1048 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1049
Surendar Karka93cd25a2018-08-28 14:21:37 +05301050 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001052 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001053 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001054
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001055#ifdef DS1_DOLBY_DAP_ENABLED
1056 audio_extn_dolby_set_dmid(adev);
1057 audio_extn_dolby_set_endpoint(adev);
1058#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001059 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001060 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301061 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001062 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301063 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301064 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1065 out = usecase->stream.out;
1066 if (out && out->compr)
1067 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1068 }
1069
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001070 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001071 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001072 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301073 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1074 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1075 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1076 if (parms) {
1077 audio_extn_fm_set_parameters(adev, parms);
1078 str_parms_destroy(parms);
1079 }
1080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081 ALOGV("%s: exit", __func__);
1082 return 0;
1083}
1084
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001085int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001089 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001090
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301091 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001092 return -EINVAL;
1093
1094 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301095 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 snd_device = usecase->in_snd_device;
1097 else
1098 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001099 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001100 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001101 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001102 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001103 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301104 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 ALOGV("%s: exit", __func__);
1106 return 0;
1107}
1108
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001109int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001110 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301112 int i, num_devices = 0;
1113 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001114 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1115
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001116 if (snd_device < SND_DEVICE_MIN ||
1117 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001118 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001119 return -EINVAL;
1120 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121
1122 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001123
1124 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1125 ALOGE("%s: Invalid sound device returned", __func__);
1126 return -EINVAL;
1127 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001129 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001130 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 return 0;
1132 }
1133
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301134
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001135 if (audio_extn_spkr_prot_is_enabled())
1136 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001137
Aalique Grahame22e49102018-12-18 14:23:57 -08001138 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1139
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001140 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1141 audio_extn_spkr_prot_is_enabled()) {
1142 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001143 adev->snd_dev_ref_cnt[snd_device]--;
1144 return -EINVAL;
1145 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001146 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001147 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001148 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001149 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001150 return -EINVAL;
1151 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001152 } else if (platform_split_snd_device(adev->platform,
1153 snd_device,
1154 &num_devices,
1155 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301156 for (i = 0; i < num_devices; i++) {
1157 enable_snd_device(adev, new_snd_devices[i]);
1158 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001159 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001160 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001161 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301162
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301163
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301164 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1165 (audio_extn_a2dp_start_playback() < 0)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02001166 ALOGE(" fail to configure A2dp Source control path ");
1167 return -EINVAL;
1168 }
1169
1170 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1171 (audio_extn_a2dp_start_capture() < 0)) {
1172 ALOGE(" fail to configure A2dp Sink control path ");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301173 return -EINVAL;
1174 }
1175
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001176 /* due to the possibility of calibration overwrite between listen
1177 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001178 audio_extn_sound_trigger_update_device_status(snd_device,
1179 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301180 audio_extn_listen_update_device_status(snd_device,
1181 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001182 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001183 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001184 audio_extn_sound_trigger_update_device_status(snd_device,
1185 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301186 audio_extn_listen_update_device_status(snd_device,
1187 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001188 return -EINVAL;
1189 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001190 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001191 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301192
1193 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1194 !adev->native_playback_enabled &&
1195 audio_is_true_native_stream_active(adev)) {
1196 ALOGD("%s: %d: napb: enabling native mode in hardware",
1197 __func__, __LINE__);
1198 audio_route_apply_and_update_path(adev->audio_route,
1199 "true-native-mode");
1200 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301201 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301202 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1203 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001204 (audio_extn_ffv_get_stream() == adev->active_input)) {
1205 ALOGD("%s: init ec ref loopback", __func__);
1206 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 return 0;
1210}
1211
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001212int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001213 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301215 int i, num_devices = 0;
1216 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001217 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1218
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001219 if (snd_device < SND_DEVICE_MIN ||
1220 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001221 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001222 return -EINVAL;
1223 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1225 ALOGE("%s: device ref cnt is already 0", __func__);
1226 return -EINVAL;
1227 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001228
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001229 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001230
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001231 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1232 ALOGE("%s: Invalid sound device returned", __func__);
1233 return -EINVAL;
1234 }
1235
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001237 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301238
Aalique Grahame22e49102018-12-18 14:23:57 -08001239 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1240
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001241 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1242 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001243 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001244
1245 // when speaker device is disabled, reset swap.
1246 // will be renabled on usecase start
1247 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001248 } else if (platform_split_snd_device(adev->platform,
1249 snd_device,
1250 &num_devices,
1251 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301252 for (i = 0; i < num_devices; i++) {
1253 disable_snd_device(adev, new_snd_devices[i]);
1254 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001255 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001256 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001257 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001258 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001259
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301260 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1261 audio_extn_a2dp_stop_playback();
1262
Florian Pfister1a84f312018-07-19 14:38:18 +02001263 if (SND_DEVICE_IN_BT_A2DP == snd_device)
1264 audio_extn_a2dp_stop_capture();
1265
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001266 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301267 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301268 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1269 adev->native_playback_enabled) {
1270 ALOGD("%s: %d: napb: disabling native mode in hardware",
1271 __func__, __LINE__);
1272 audio_route_reset_and_update_path(adev->audio_route,
1273 "true-native-mode");
1274 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301275 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1276 adev->asrc_mode_enabled) {
1277 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301278 disable_asrc_mode(adev);
1279 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301280 }
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301281 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1282 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001283 (audio_extn_ffv_get_stream() == adev->active_input)) {
1284 ALOGD("%s: deinit ec ref loopback", __func__);
1285 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1286 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001287 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001288 audio_extn_sound_trigger_update_device_status(snd_device,
1289 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301290 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001291 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294 return 0;
1295}
1296
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001297/*
1298 legend:
1299 uc - existing usecase
1300 new_uc - new usecase
1301 d1, d11, d2 - SND_DEVICE enums
1302 a1, a2 - corresponding ANDROID device enums
1303 B1, B2 - backend strings
1304
1305case 1
1306 uc->dev d1 (a1) B1
1307 new_uc->dev d1 (a1), d2 (a2) B1, B2
1308
1309 resolution: disable and enable uc->dev on d1
1310
1311case 2
1312 uc->dev d1 (a1) B1
1313 new_uc->dev d11 (a1) B1
1314
1315 resolution: need to switch uc since d1 and d11 are related
1316 (e.g. speaker and voice-speaker)
1317 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1318
1319case 3
1320 uc->dev d1 (a1) B1
1321 new_uc->dev d2 (a2) B2
1322
1323 resolution: no need to switch uc
1324
1325case 4
1326 uc->dev d1 (a1) B1
1327 new_uc->dev d2 (a2) B1
1328
1329 resolution: disable enable uc-dev on d2 since backends match
1330 we cannot enable two streams on two different devices if they
1331 share the same backend. e.g. if offload is on speaker device using
1332 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1333 using the same backend, offload must also be switched to voice-handset.
1334
1335case 5
1336 uc->dev d1 (a1) B1
1337 new_uc->dev d1 (a1), d2 (a2) B1
1338
1339 resolution: disable enable uc-dev on d2 since backends match
1340 we cannot enable two streams on two different devices if they
1341 share the same backend.
1342
1343case 6
1344 uc->dev d1 (a1) B1
1345 new_uc->dev d2 (a1) B2
1346
1347 resolution: no need to switch
1348
1349case 7
1350 uc->dev d1 (a1), d2 (a2) B1, B2
1351 new_uc->dev d1 (a1) B1
1352
1353 resolution: no need to switch
1354
Zhou Song4ba65882018-07-09 14:48:07 +08001355case 8
1356 uc->dev d1 (a1) B1
1357 new_uc->dev d11 (a1), d2 (a2) B1, B2
1358 resolution: compared to case 1, for this case, d1 and d11 are related
1359 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001360*/
1361static snd_device_t derive_playback_snd_device(void * platform,
1362 struct audio_usecase *uc,
1363 struct audio_usecase *new_uc,
1364 snd_device_t new_snd_device)
1365{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301366 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001367
1368 snd_device_t d1 = uc->out_snd_device;
1369 snd_device_t d2 = new_snd_device;
1370
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301371 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301372 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301373 a1 = uc->stream.inout->out_config.devices;
1374 a2 = new_uc->stream.inout->out_config.devices;
1375 break;
1376 default :
1377 a1 = uc->stream.out->devices;
1378 a2 = new_uc->stream.out->devices;
1379 break;
1380 }
1381
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001382 // Treat as a special case when a1 and a2 are not disjoint
1383 if ((a1 != a2) && (a1 & a2)) {
1384 snd_device_t d3[2];
1385 int num_devices = 0;
1386 int ret = platform_split_snd_device(platform,
1387 popcount(a1) > 1 ? d1 : d2,
1388 &num_devices,
1389 d3);
1390 if (ret < 0) {
1391 if (ret != -ENOSYS) {
1392 ALOGW("%s failed to split snd_device %d",
1393 __func__,
1394 popcount(a1) > 1 ? d1 : d2);
1395 }
1396 goto end;
1397 }
1398
1399 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1400 // But if it does happen, we need to give priority to d2 if
1401 // the combo devices active on the existing usecase share a backend.
1402 // This is because we cannot have a usecase active on a combo device
1403 // and a new usecase requests one device in this combo pair.
1404 if (platform_check_backends_match(d3[0], d3[1])) {
1405 return d2; // case 5
1406 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001407 // check if d1 is related to any of d3's
1408 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001409 return d1; // case 1
1410 else
1411 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001412 }
1413 } else {
1414 if (platform_check_backends_match(d1, d2)) {
1415 return d2; // case 2, 4
1416 } else {
1417 return d1; // case 6, 3
1418 }
1419 }
1420
1421end:
1422 return d2; // return whatever was calculated before.
1423}
1424
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301426 struct audio_usecase *uc_info,
1427 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001428{
1429 struct listnode *node;
1430 struct audio_usecase *usecase;
1431 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301432 snd_device_t uc_derive_snd_device;
1433 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001435 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301436 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001437 /*
1438 * This function is to make sure that all the usecases that are active on
1439 * the hardware codec backend are always routed to any one device that is
1440 * handled by the hardware codec.
1441 * For example, if low-latency and deep-buffer usecases are currently active
1442 * on speaker and out_set_parameters(headset) is received on low-latency
1443 * output, then we have to make sure deep-buffer is also switched to headset,
1444 * because of the limitation that both the devices cannot be enabled
1445 * at the same time as they share the same backend.
1446 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001447 /*
1448 * This call is to check if we need to force routing for a particular stream
1449 * If there is a backend configuration change for the device when a
1450 * new stream starts, then ADM needs to be closed and re-opened with the new
1451 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001452 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001453 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001454 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1455 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301456 /* For a2dp device reconfigure all active sessions
1457 * with new AFE encoder format based on a2dp state
1458 */
1459 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1460 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1461 audio_extn_a2dp_is_force_device_switch()) {
1462 force_routing = true;
1463 force_restart_session = true;
1464 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301465 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001468 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001469 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1471 switch_device[i] = false;
1472
1473 list_for_each(node, &adev->usecase_list) {
1474 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001475
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301476 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1477 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301478 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301479 platform_get_snd_device_name(usecase->out_snd_device),
1480 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301481 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1482 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1483 usecase, uc_info, snd_device);
1484 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1485 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1486 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1487 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001488 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301489 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1490 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1491 ((force_restart_session) ||
1492 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301493 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1494 __func__, use_case_table[usecase->id],
1495 platform_get_snd_device_name(usecase->out_snd_device));
1496 disable_audio_route(adev, usecase);
1497 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301498 /* Enable existing usecase on derived playback device */
1499 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301500 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 }
1503 }
1504
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301505 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1506 num_uc_to_switch);
1507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001509 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001510
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301511 /* Make sure the previous devices to be disabled first and then enable the
1512 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513 list_for_each(node, &adev->usecase_list) {
1514 usecase = node_to_item(node, struct audio_usecase, list);
1515 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001516 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 }
1518 }
1519
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001520 list_for_each(node, &adev->usecase_list) {
1521 usecase = node_to_item(node, struct audio_usecase, list);
1522 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301523 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001524 }
1525 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 /* Re-route all the usecases on the shared backend other than the
1528 specified usecase to new snd devices */
1529 list_for_each(node, &adev->usecase_list) {
1530 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301531 /* Update the out_snd_device only before enabling the audio route */
1532 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301533 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301534 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301535 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301536 use_case_table[usecase->id],
1537 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001538 /* Update voc calibration before enabling VoIP route */
1539 if (usecase->type == VOIP_CALL)
1540 status = platform_switch_voice_call_device_post(adev->platform,
1541 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001542 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301543 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001544 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1545 out_set_voip_volume(&usecase->stream.out->stream,
1546 usecase->stream.out->volume_l,
1547 usecase->stream.out->volume_r);
1548 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301549 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001550 }
1551 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552 }
1553}
1554
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301555static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001556 struct audio_usecase *uc_info,
1557 snd_device_t snd_device)
1558{
1559 struct listnode *node;
1560 struct audio_usecase *usecase;
1561 bool switch_device[AUDIO_USECASE_MAX];
1562 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301563 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001564 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001565
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301566 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1567 snd_device);
1568 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301569
1570 /*
1571 * Make sure out devices is checked against out codec backend device and
1572 * also in devices against in codec backend. Checking out device against in
1573 * codec backend or vice versa causes issues.
1574 */
1575 if (uc_info->type == PCM_CAPTURE)
1576 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001577 /*
1578 * This function is to make sure that all the active capture usecases
1579 * are always routed to the same input sound device.
1580 * For example, if audio-record and voice-call usecases are currently
1581 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1582 * is received for voice call then we have to make sure that audio-record
1583 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1584 * because of the limitation that two devices cannot be enabled
1585 * at the same time if they share the same backend.
1586 */
1587 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1588 switch_device[i] = false;
1589
1590 list_for_each(node, &adev->usecase_list) {
1591 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301592 /*
1593 * TODO: Enhance below condition to handle BT sco/USB multi recording
1594 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001595 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001596 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301597 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301598 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301599 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301600 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001601 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001602 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1603 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001604 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001605 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001606 switch_device[usecase->id] = true;
1607 num_uc_to_switch++;
1608 }
1609 }
1610
1611 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001612 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001613
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301614 /* Make sure the previous devices to be disabled first and then enable the
1615 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001616 list_for_each(node, &adev->usecase_list) {
1617 usecase = node_to_item(node, struct audio_usecase, list);
1618 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001619 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001620 }
1621 }
1622
1623 list_for_each(node, &adev->usecase_list) {
1624 usecase = node_to_item(node, struct audio_usecase, list);
1625 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001626 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001627 }
1628 }
1629
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001630 /* Re-route all the usecases on the shared backend other than the
1631 specified usecase to new snd devices */
1632 list_for_each(node, &adev->usecase_list) {
1633 usecase = node_to_item(node, struct audio_usecase, list);
1634 /* Update the in_snd_device only before enabling the audio route */
1635 if (switch_device[usecase->id] ) {
1636 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001637 if (usecase->type != VOICE_CALL) {
1638 /* Update voc calibration before enabling VoIP route */
1639 if (usecase->type == VOIP_CALL)
1640 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001641 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001642 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301643 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001644 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001645 }
1646 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001647 }
1648}
1649
Mingming Yin3a941d42016-02-17 18:08:05 -08001650static void reset_hdmi_sink_caps(struct stream_out *out) {
1651 int i = 0;
1652
1653 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1654 out->supported_channel_masks[i] = 0;
1655 }
1656 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1657 out->supported_formats[i] = 0;
1658 }
1659 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1660 out->supported_sample_rates[i] = 0;
1661 }
1662}
1663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001665static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666{
Mingming Yin3a941d42016-02-17 18:08:05 -08001667 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001668 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669
Mingming Yin3a941d42016-02-17 18:08:05 -08001670 reset_hdmi_sink_caps(out);
1671
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001672 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001673 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001674 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001675 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001676 }
1677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001680 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001681 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001682 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1683 case 6:
1684 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1685 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1686 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1687 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1688 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1689 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690 break;
1691 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001692 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001693 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 break;
1695 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001696
1697 // check channel format caps
1698 i = 0;
1699 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1700 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1701 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1702 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1703 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1704 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1705 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1706 }
1707
Ben Romberger1aaaf862017-04-06 17:49:46 -07001708 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1709 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1710 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1711 }
1712
Mingming Yin3a941d42016-02-17 18:08:05 -08001713 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1714 ALOGV(":%s HDMI supports DTS format", __func__);
1715 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1716 }
1717
1718 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1719 ALOGV(":%s HDMI supports DTS HD format", __func__);
1720 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1721 }
1722
Naresh Tanniru928f0862017-04-07 16:44:23 -07001723 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1724 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1725 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1726 }
1727
Mingming Yin3a941d42016-02-17 18:08:05 -08001728
1729 // check sample rate caps
1730 i = 0;
1731 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1732 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1733 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1734 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1735 }
1736 }
1737
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001738 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739}
1740
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001741static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1742 uint32_t *supported_sample_rates __unused,
1743 uint32_t max_rates __unused)
1744{
1745 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1746 supported_sample_rates,
1747 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301748 ssize_t i = 0;
1749
1750 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001751 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1752 supported_sample_rates[i]);
1753 }
1754 return count;
1755}
1756
1757static inline int read_usb_sup_channel_masks(bool is_playback,
1758 audio_channel_mask_t *supported_channel_masks,
1759 uint32_t max_masks)
1760{
1761 int channels = audio_extn_usb_get_max_channels(is_playback);
1762 int channel_count;
1763 uint32_t num_masks = 0;
1764 if (channels > MAX_HIFI_CHANNEL_COUNT)
1765 channels = MAX_HIFI_CHANNEL_COUNT;
1766
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301767 channel_count = DEFAULT_CHANNEL_COUNT;
1768
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001769 if (is_playback) {
1770 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001771 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301772 // above 2 but we want indexed masks here.
1773 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001774 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001775 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1776 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301777 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001778 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301779
1780 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1781 (num_masks < max_masks)); channel_count--) {
1782 supported_channel_masks[num_masks++] =
1783 audio_channel_mask_for_index_assignment_from_count(channel_count);
1784 }
1785
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001786 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1787 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1788 return num_masks;
1789}
1790
1791static inline int read_usb_sup_formats(bool is_playback __unused,
1792 audio_format_t *supported_formats,
1793 uint32_t max_formats __unused)
1794{
1795 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1796 switch (bitwidth) {
1797 case 24:
1798 // XXX : usb.c returns 24 for s24 and s24_le?
1799 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1800 break;
1801 case 32:
1802 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1803 break;
1804 case 16:
1805 default :
1806 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1807 break;
1808 }
1809 ALOGV("%s: %s supported format %d", __func__,
1810 is_playback ? "P" : "C", bitwidth);
1811 return 1;
1812}
1813
1814static inline int read_usb_sup_params_and_compare(bool is_playback,
1815 audio_format_t *format,
1816 audio_format_t *supported_formats,
1817 uint32_t max_formats,
1818 audio_channel_mask_t *mask,
1819 audio_channel_mask_t *supported_channel_masks,
1820 uint32_t max_masks,
1821 uint32_t *rate,
1822 uint32_t *supported_sample_rates,
1823 uint32_t max_rates) {
1824 int ret = 0;
1825 int num_formats;
1826 int num_masks;
1827 int num_rates;
1828 int i;
1829
1830 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1831 max_formats);
1832 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1833 max_masks);
1834
1835 num_rates = read_usb_sup_sample_rates(is_playback,
1836 supported_sample_rates, max_rates);
1837
1838#define LUT(table, len, what, dflt) \
1839 for (i=0; i<len && (table[i] != what); i++); \
1840 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1841
1842 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1843 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1844 LUT(supported_sample_rates, num_rates, *rate, 0);
1845
1846#undef LUT
1847 return ret < 0 ? -EINVAL : 0; // HACK TBD
1848}
1849
Alexy Josephb1379942016-01-29 15:49:38 -08001850audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001851 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001852{
1853 struct audio_usecase *usecase;
1854 struct listnode *node;
1855
1856 list_for_each(node, &adev->usecase_list) {
1857 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001858 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001859 ALOGV("%s: usecase id %d", __func__, usecase->id);
1860 return usecase->id;
1861 }
1862 }
1863 return USECASE_INVALID;
1864}
1865
Alexy Josephb1379942016-01-29 15:49:38 -08001866struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001867 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868{
1869 struct audio_usecase *usecase;
1870 struct listnode *node;
1871
1872 list_for_each(node, &adev->usecase_list) {
1873 usecase = node_to_item(node, struct audio_usecase, list);
1874 if (usecase->id == uc_id)
1875 return usecase;
1876 }
1877 return NULL;
1878}
1879
Dhananjay Kumard4833242016-10-06 22:09:12 +05301880struct stream_in *get_next_active_input(const struct audio_device *adev)
1881{
1882 struct audio_usecase *usecase;
1883 struct listnode *node;
1884
1885 list_for_each_reverse(node, &adev->usecase_list) {
1886 usecase = node_to_item(node, struct audio_usecase, list);
1887 if (usecase->type == PCM_CAPTURE)
1888 return usecase->stream.in;
1889 }
1890 return NULL;
1891}
1892
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301893/*
1894 * is a true native playback active
1895 */
1896bool audio_is_true_native_stream_active(struct audio_device *adev)
1897{
1898 bool active = false;
1899 int i = 0;
1900 struct listnode *node;
1901
1902 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1903 ALOGV("%s:napb: not in true mode or non hdphones device",
1904 __func__);
1905 active = false;
1906 goto exit;
1907 }
1908
1909 list_for_each(node, &adev->usecase_list) {
1910 struct audio_usecase *uc;
1911 uc = node_to_item(node, struct audio_usecase, list);
1912 struct stream_out *curr_out =
1913 (struct stream_out*) uc->stream.out;
1914
1915 if (curr_out && PCM_PLAYBACK == uc->type) {
1916 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1917 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1918 uc->id, curr_out->sample_rate,
1919 curr_out->bit_width,
1920 platform_get_snd_device_name(uc->out_snd_device));
1921
1922 if (is_offload_usecase(uc->id) &&
1923 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1924 active = true;
1925 ALOGD("%s:napb:native stream detected", __func__);
1926 }
1927 }
1928 }
1929exit:
1930 return active;
1931}
1932
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001933uint32_t adev_get_dsp_bit_width_enforce_mode()
1934{
1935 if (adev == NULL) {
1936 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1937 return 0;
1938 }
1939 return adev->dsp_bit_width_enforce_mode;
1940}
1941
1942static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1943{
1944 char value[PROPERTY_VALUE_MAX];
1945 int trial;
1946 uint32_t dsp_bit_width_enforce_mode = 0;
1947
1948 if (!mixer) {
1949 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1950 __func__);
1951 return 0;
1952 }
1953
1954 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1955 value, NULL) > 0) {
1956 trial = atoi(value);
1957 switch (trial) {
1958 case 16:
1959 dsp_bit_width_enforce_mode = 16;
1960 break;
1961 case 24:
1962 dsp_bit_width_enforce_mode = 24;
1963 break;
1964 case 32:
1965 dsp_bit_width_enforce_mode = 32;
1966 break;
1967 default:
1968 dsp_bit_width_enforce_mode = 0;
1969 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1970 break;
1971 }
1972 }
1973
1974 return dsp_bit_width_enforce_mode;
1975}
1976
1977static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1978 uint32_t enforce_mode,
1979 bool enable)
1980{
1981 struct mixer_ctl *ctl = NULL;
1982 const char *mixer_ctl_name = "ASM Bit Width";
1983 uint32_t asm_bit_width_mode = 0;
1984
1985 if (enforce_mode == 0) {
1986 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1987 return;
1988 }
1989
1990 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1991 if (!ctl) {
1992 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1993 __func__, mixer_ctl_name);
1994 return;
1995 }
1996
1997 if (enable)
1998 asm_bit_width_mode = enforce_mode;
1999 else
2000 asm_bit_width_mode = 0;
2001
2002 ALOGV("%s DSP bit width feature status is %d width=%d",
2003 __func__, enable, asm_bit_width_mode);
2004 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2005 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2006 asm_bit_width_mode);
2007
2008 return;
2009}
2010
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302011/*
2012 * if native DSD playback active
2013 */
2014bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2015{
2016 bool active = false;
2017 struct listnode *node = NULL;
2018 struct audio_usecase *uc = NULL;
2019 struct stream_out *curr_out = NULL;
2020
2021 list_for_each(node, &adev->usecase_list) {
2022 uc = node_to_item(node, struct audio_usecase, list);
2023 curr_out = (struct stream_out*) uc->stream.out;
2024
2025 if (curr_out && PCM_PLAYBACK == uc->type &&
2026 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2027 active = true;
2028 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302029 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302030 }
2031 }
2032 return active;
2033}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302034
2035static bool force_device_switch(struct audio_usecase *usecase)
2036{
2037 bool ret = false;
2038 bool is_it_true_mode = false;
2039
Zhou Song30f2c3e2018-02-08 14:02:15 +08002040 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302041 usecase->type == TRANSCODE_LOOPBACK_RX ||
2042 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002043 return false;
2044 }
2045
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002046 if(usecase->stream.out == NULL) {
2047 ALOGE("%s: stream.out is NULL", __func__);
2048 return false;
2049 }
2050
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302051 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002052 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2053 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2054 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302055 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2056 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2057 (!is_it_true_mode && adev->native_playback_enabled)){
2058 ret = true;
2059 ALOGD("napb: time to toggle native mode");
2060 }
2061 }
2062
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302063 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302064 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2065 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002066 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302067 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302068 ALOGD("Force a2dp device switch to update new encoder config");
2069 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002070 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302071
Florian Pfister1a84f312018-07-19 14:38:18 +02002072 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302073 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2074 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002075 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302076 return ret;
2077}
2078
Aalique Grahame22e49102018-12-18 14:23:57 -08002079static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2080{
2081 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2082}
2083
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302084bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2085{
2086 bool ret=false;
2087 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2088 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2089 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2090 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2091 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2092 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2093 ret = true;
2094
2095 return ret;
2096}
2097
2098bool is_a2dp_device(snd_device_t out_snd_device)
2099{
2100 bool ret=false;
2101 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2102 ret = true;
2103
2104 return ret;
2105}
2106
2107bool is_bt_soc_on(struct audio_device *adev)
2108{
2109 struct mixer_ctl *ctl;
2110 char *mixer_ctl_name = "BT SOC status";
2111 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2112 bool bt_soc_status = true;
2113 if (!ctl) {
2114 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2115 __func__, mixer_ctl_name);
2116 /*This is to ensure we dont break targets which dont have the kernel change*/
2117 return true;
2118 }
2119 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2120 ALOGD("BT SOC status: %d",bt_soc_status);
2121 return bt_soc_status;
2122}
2123
2124int out_standby_l(struct audio_stream *stream);
2125
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002126int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002128 snd_device_t out_snd_device = SND_DEVICE_NONE;
2129 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002130 struct audio_usecase *usecase = NULL;
2131 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002132 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002133 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302134 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002135 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002136 int status = 0;
Jhansi Konathala902fc412018-09-05 13:21:44 +05302137 audio_devices_t audio_device = AUDIO_DEVICE_NONE;
2138 audio_channel_mask_t channel_mask = AUDIO_CHANNEL_NONE;
2139 int sample_rate = 0;
2140 int acdb_id = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302142 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2143
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002144 usecase = get_usecase_from_list(adev, uc_id);
2145 if (usecase == NULL) {
2146 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2147 return -EINVAL;
2148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002150 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002151 (usecase->type == VOIP_CALL) ||
2152 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302153 if(usecase->stream.out == NULL) {
2154 ALOGE("%s: stream.out is NULL", __func__);
2155 return -EINVAL;
2156 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002157 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002158 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002159 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302161 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302162 if (usecase->stream.inout == NULL) {
2163 ALOGE("%s: stream.inout is NULL", __func__);
2164 return -EINVAL;
2165 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302166 stream_out.devices = usecase->stream.inout->out_config.devices;
2167 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2168 stream_out.format = usecase->stream.inout->out_config.format;
2169 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2170 out_snd_device = platform_get_output_snd_device(adev->platform,
2171 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302172 usecase->devices = out_snd_device;
2173 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2174 if (usecase->stream.inout == NULL) {
2175 ALOGE("%s: stream.inout is NULL", __func__);
2176 return -EINVAL;
2177 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302178 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302179 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002180 } else {
2181 /*
2182 * If the voice call is active, use the sound devices of voice call usecase
2183 * so that it would not result any device switch. All the usecases will
2184 * be switched to new device when select_devices() is called for voice call
2185 * usecase. This is to avoid switching devices for voice call when
2186 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002187 * choose voice call device only if the use case device is
2188 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002189 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002190 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002191 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002192 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002193 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2194 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302195 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2196 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002197 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002198 in_snd_device = vc_usecase->in_snd_device;
2199 out_snd_device = vc_usecase->out_snd_device;
2200 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002201 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002202 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002203 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002204 if ((voip_usecase != NULL) &&
2205 (usecase->type == PCM_PLAYBACK) &&
2206 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002207 out_snd_device_backend_match = platform_check_backends_match(
2208 voip_usecase->out_snd_device,
2209 platform_get_output_snd_device(
2210 adev->platform,
2211 usecase->stream.out));
2212 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002213 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002214 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2215 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002216 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002217 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002218 in_snd_device = voip_usecase->in_snd_device;
2219 out_snd_device = voip_usecase->out_snd_device;
2220 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002221 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002222 hfp_ucid = audio_extn_hfp_get_usecase();
2223 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002224 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002225 in_snd_device = hfp_usecase->in_snd_device;
2226 out_snd_device = hfp_usecase->out_snd_device;
2227 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002228 }
2229 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302230 if (usecase->stream.out == NULL) {
2231 ALOGE("%s: stream.out is NULL", __func__);
2232 return -EINVAL;
2233 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002234 usecase->devices = usecase->stream.out->devices;
2235 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002236 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002237 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002238 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002239 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002240 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002241 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2242
2243 if ((usecase->stream.out != NULL &&
2244 voip_usecase != NULL &&
2245 usecase->stream.out->usecase == voip_usecase->id) &&
2246 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002247 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2248 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002249 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002250 select_devices(adev, adev->active_input->usecase);
2251 }
2252 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302254 if (usecase->stream.in == NULL) {
2255 ALOGE("%s: stream.in is NULL", __func__);
2256 return -EINVAL;
2257 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002258 usecase->devices = usecase->stream.in->device;
2259 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002260 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002261 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002262 if (adev->active_input &&
2263 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302264 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002265 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2266 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2267 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2268 out_device = voip_usecase->stream.out->devices;
2269 else if (adev->primary_output && !adev->primary_output->standby)
2270 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002271 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002272 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2273 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002274 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002275 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002276 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 }
2278 }
2279
2280 if (out_snd_device == usecase->out_snd_device &&
2281 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302282
2283 if (!force_device_switch(usecase))
2284 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 }
2286
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302287 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002288 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302289 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2290 return 0;
2291 }
2292
Aalique Grahame22e49102018-12-18 14:23:57 -08002293 if (out_snd_device != SND_DEVICE_NONE &&
2294 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2295 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2296 __func__,
2297 use_case_table[uc_id],
2298 adev->last_logged_snd_device[uc_id][0],
2299 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2300 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2301 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2302 -1,
2303 out_snd_device,
2304 platform_get_snd_device_name(out_snd_device),
2305 platform_get_snd_device_acdb_id(out_snd_device));
2306 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2307 }
2308 if (in_snd_device != SND_DEVICE_NONE &&
2309 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2310 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2311 __func__,
2312 use_case_table[uc_id],
2313 adev->last_logged_snd_device[uc_id][1],
2314 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2315 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2316 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2317 -1,
2318 in_snd_device,
2319 platform_get_snd_device_name(in_snd_device),
2320 platform_get_snd_device_acdb_id(in_snd_device));
2321 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2322 }
2323
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325 /*
2326 * Limitation: While in call, to do a device switch we need to disable
2327 * and enable both RX and TX devices though one of them is same as current
2328 * device.
2329 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002330 if ((usecase->type == VOICE_CALL) &&
2331 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2332 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002333 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002334 }
2335
2336 if (((usecase->type == VOICE_CALL) ||
2337 (usecase->type == VOIP_CALL)) &&
2338 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2339 /* Disable sidetone only if voice/voip call already exists */
2340 if (voice_is_call_state_active(adev) ||
2341 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002342 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002343
2344 /* Disable aanc only if voice call exists */
2345 if (voice_is_call_state_active(adev))
2346 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002347 }
2348
Aalique Grahame22e49102018-12-18 14:23:57 -08002349 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2350 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002351 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302352 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002353 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2354 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2355 else
2356 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302357 }
2358
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002359 /* Disable current sound devices */
2360 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002361 disable_audio_route(adev, usecase);
2362 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 }
2364
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002365 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002366 disable_audio_route(adev, usecase);
2367 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 }
2369
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002370 /* Applicable only on the targets that has external modem.
2371 * New device information should be sent to modem before enabling
2372 * the devices to reduce in-call device switch time.
2373 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002374 if ((usecase->type == VOICE_CALL) &&
2375 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2376 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002377 status = platform_switch_voice_call_enable_device_config(adev->platform,
2378 out_snd_device,
2379 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002380 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002381
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002382 /* Enable new sound devices */
2383 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002384 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302385 if (platform_check_codec_asrc_support(adev->platform))
2386 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002387 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 }
2389
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002390 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302391 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002392 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002393 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394
Avinash Vaish71a8b972014-07-24 15:36:33 +05302395 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002396 status = platform_switch_voice_call_device_post(adev->platform,
2397 out_snd_device,
2398 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302399 enable_audio_route_for_voice_usecases(adev, usecase);
2400 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002401
sangwoo170731f2013-06-08 15:36:36 +09002402 usecase->in_snd_device = in_snd_device;
2403 usecase->out_snd_device = out_snd_device;
2404
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302405 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2406 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302407 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002408 if ((24 == usecase->stream.out->bit_width) &&
2409 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2410 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2411 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2412 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2413 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2414 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2415 /*
2416 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2417 * configured device sample rate, if not update the COPP rate to be equal to the
2418 * device sample rate, else open COPP at stream sample rate
2419 */
2420 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2421 usecase->stream.out->sample_rate,
2422 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302423 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2424 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002425 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2426 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2427 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2428 }
2429
Weiyin Jiang5d608082018-02-01 17:24:33 +08002430 /* Cache stream information to be notified to gef clients */
2431 audio_device = usecase->stream.out->devices;
2432 channel_mask = usecase->stream.out->channel_mask;
2433 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2434 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302435 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002436 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002437
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002438 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002439
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002440 /* If input stream is already running then effect needs to be
2441 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002442 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2443 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002444 check_and_enable_effect(adev);
2445
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002446 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002447 /* Enable aanc only if voice call exists */
2448 if (voice_is_call_state_active(adev))
2449 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2450
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002451 /* Enable sidetone only if other voice/voip call already exists */
2452 if (voice_is_call_state_active(adev) ||
2453 voice_extn_compress_voip_is_started(adev))
2454 voice_set_sidetone(adev, out_snd_device, true);
2455 }
2456
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002457 /* Applicable only on the targets that has external modem.
2458 * Enable device command should be sent to modem only after
2459 * enabling voice call mixer controls
2460 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002461 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002462 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2463 out_snd_device,
2464 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302465
2466 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2467
2468 if (usecase->type == VOIP_CALL) {
2469 if (adev->active_input != NULL &&
2470 !adev->active_input->standby) {
2471 if (is_bt_soc_on(adev) == false){
2472 ALOGD("BT SCO MIC disconnected while in connection");
2473 if (adev->active_input->pcm != NULL)
2474 pcm_stop(adev->active_input->pcm);
2475 }
2476 }
2477 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2478 && usecase->stream.out->started) {
2479 if (is_bt_soc_on(adev) == false) {
2480 ALOGD("BT SCO/A2DP disconnected while in connection");
2481 out_standby_l(&usecase->stream.out->stream.common);
2482 }
2483 }
2484 } else if ((usecase->stream.out != NULL) &&
2485 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302486 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2487 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302488 usecase->stream.out->started) {
2489 if (is_bt_soc_on(adev) == false) {
2490 ALOGD("BT SCO/A2dp disconnected while in connection");
2491 out_standby_l(&usecase->stream.out->stream.common);
2492 }
2493 }
2494 }
2495
Weiyin Jiang5d608082018-02-01 17:24:33 +08002496 /* Notify device change info to effect clients registered
2497 * NOTE: device lock has to be unlock temporarily here.
2498 * To the worst case, we notify stale info to clients.
2499 */
2500 if (usecase->type == PCM_PLAYBACK) {
2501 pthread_mutex_unlock(&adev->lock);
2502 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2503 pthread_mutex_lock(&adev->lock);
2504 }
2505
Aalique Grahame22e49102018-12-18 14:23:57 -08002506 if (usecase == voip_usecase) {
2507 struct stream_out *voip_out = voip_usecase->stream.out;
2508 audio_extn_utils_send_app_type_gain(adev,
2509 voip_out->app_type_cfg.app_type,
2510 &voip_out->app_type_cfg.gain[0]);
2511 }
2512
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302513 ALOGD("%s: done",__func__);
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 return status;
2516}
2517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518static int stop_input_stream(struct stream_in *in)
2519{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302520 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302522
2523 if (in == NULL) {
2524 ALOGE("%s: stream_in ptr is NULL", __func__);
2525 return -EINVAL;
2526 }
2527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 struct audio_device *adev = in->dev;
2529
Eric Laurent994a6932013-07-17 11:51:42 -07002530 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002531 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 uc_info = get_usecase_from_list(adev, in->usecase);
2533 if (uc_info == NULL) {
2534 ALOGE("%s: Could not find the usecase (%d) in the list",
2535 __func__, in->usecase);
2536 return -EINVAL;
2537 }
2538
Derek Chenea197282019-01-07 17:35:01 -08002539 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2540 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002541
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002542 /* Close in-call recording streams */
2543 voice_check_and_stop_incall_rec_usecase(adev, in);
2544
Eric Laurent150dbfe2013-02-27 14:31:02 -08002545 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002546 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002547
2548 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002549 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002551 list_remove(&uc_info->list);
2552 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002554 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302555 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002556 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 return ret;
2558}
2559
2560int start_input_stream(struct stream_in *in)
2561{
2562 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302565
2566 if (in == NULL) {
2567 ALOGE("%s: stream_in ptr is NULL", __func__);
2568 return -EINVAL;
2569 }
2570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002572 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002573 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574
Mingming Yin2664a5b2015-09-03 10:53:11 -07002575 if (get_usecase_from_list(adev, usecase) == NULL)
2576 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302577 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2578 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002579
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302580 if (CARD_STATUS_OFFLINE == in->card_status||
2581 CARD_STATUS_OFFLINE == adev->card_status) {
2582 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302583 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302584 goto error_config;
2585 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302587 if (audio_is_bluetooth_sco_device(in->device)) {
2588 if (!adev->bt_sco_on) {
2589 ALOGE("%s: SCO profile is not ready, return error", __func__);
2590 ret = -EIO;
2591 goto error_config;
2592 }
2593 }
2594
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002595 /* Check if source matches incall recording usecase criteria */
2596 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2597 if (ret)
2598 goto error_config;
2599 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002600 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2601
2602 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2603 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2604 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002605 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002606 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002607
Eric Laurentb23d5282013-05-14 15:27:20 -07002608 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 if (in->pcm_device_id < 0) {
2610 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2611 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002612 ret = -EINVAL;
2613 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002615
2616 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002618
2619 if (!uc_info) {
2620 ret = -ENOMEM;
2621 goto error_config;
2622 }
2623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 uc_info->id = in->usecase;
2625 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002626 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002627 uc_info->devices = in->device;
2628 uc_info->in_snd_device = SND_DEVICE_NONE;
2629 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002631 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302632 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2633 adev->perf_lock_opts,
2634 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002635 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
Derek Chenea197282019-01-07 17:35:01 -08002637 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2638 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002639
Haynes Mathew George16081042017-05-31 17:16:49 -07002640 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302641 ret = audio_extn_cin_start_input_stream(in);
2642 if (ret)
2643 goto error_open;
2644 else
2645 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002646 }
2647
Haynes Mathew George16081042017-05-31 17:16:49 -07002648 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002649 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002650 ALOGE("%s: pcm stream not ready", __func__);
2651 goto error_open;
2652 }
2653 ret = pcm_start(in->pcm);
2654 if (ret < 0) {
2655 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2656 goto error_open;
2657 }
2658 } else {
2659 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2660 unsigned int pcm_open_retry_count = 0;
2661
2662 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2663 flags |= PCM_MMAP | PCM_NOIRQ;
2664 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2665 } else if (in->realtime) {
2666 flags |= PCM_MMAP | PCM_NOIRQ;
2667 }
2668
Garmond Leunge2433c32017-09-28 21:51:22 -07002669 if (audio_extn_ffv_get_stream() == in) {
2670 ALOGD("%s: ffv stream, update pcm config", __func__);
2671 audio_extn_ffv_update_pcm_config(&config);
2672 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002673 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2674 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2675
2676 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002677 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002678 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002679 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002680 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302681 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302682 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2683 adev->card_status = CARD_STATUS_OFFLINE;
2684 in->card_status = CARD_STATUS_OFFLINE;
2685 ret = -EIO;
2686 goto error_open;
2687 }
2688
Haynes Mathew George16081042017-05-31 17:16:49 -07002689 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2690 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2691 if (in->pcm != NULL) {
2692 pcm_close(in->pcm);
2693 in->pcm = NULL;
2694 }
2695 if (pcm_open_retry_count-- == 0) {
2696 ret = -EIO;
2697 goto error_open;
2698 }
2699 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2700 continue;
2701 }
2702 break;
2703 }
2704
2705 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002706 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002707 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002708 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002709 if (ret < 0) {
2710 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2711 pcm_close(in->pcm);
2712 in->pcm = NULL;
2713 goto error_open;
2714 }
2715 register_in_stream(in);
2716 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002717 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002718 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002719 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002720 if (ret < 0) {
2721 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002722 pcm_close(in->pcm);
2723 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002724 goto error_open;
2725 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002726 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002727 }
2728
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002729 check_and_enable_effect(adev);
2730
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302731done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302732 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002733 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302734 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002735 return ret;
2736
2737error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302738 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002740error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302741 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302742 /*
2743 * sleep 50ms to allow sufficient time for kernel
2744 * drivers to recover incases like SSR.
2745 */
2746 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002747 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302748 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002749 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750}
2751
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002752void lock_input_stream(struct stream_in *in)
2753{
2754 pthread_mutex_lock(&in->pre_lock);
2755 pthread_mutex_lock(&in->lock);
2756 pthread_mutex_unlock(&in->pre_lock);
2757}
2758
2759void lock_output_stream(struct stream_out *out)
2760{
2761 pthread_mutex_lock(&out->pre_lock);
2762 pthread_mutex_lock(&out->lock);
2763 pthread_mutex_unlock(&out->pre_lock);
2764}
2765
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766/* must be called with out->lock locked */
2767static int send_offload_cmd_l(struct stream_out* out, int command)
2768{
2769 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2770
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002771 if (!cmd) {
2772 ALOGE("failed to allocate mem for command 0x%x", command);
2773 return -ENOMEM;
2774 }
2775
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 ALOGVV("%s %d", __func__, command);
2777
2778 cmd->cmd = command;
2779 list_add_tail(&out->offload_cmd_list, &cmd->node);
2780 pthread_cond_signal(&out->offload_cond);
2781 return 0;
2782}
2783
2784/* must be called iwth out->lock locked */
2785static void stop_compressed_output_l(struct stream_out *out)
2786{
2787 out->offload_state = OFFLOAD_STATE_IDLE;
2788 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002789 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002790 if (out->compr != NULL) {
2791 compress_stop(out->compr);
2792 while (out->offload_thread_blocked) {
2793 pthread_cond_wait(&out->cond, &out->lock);
2794 }
2795 }
2796}
2797
Varun Balaraje49253e2017-07-06 19:48:56 +05302798bool is_interactive_usecase(audio_usecase_t uc_id)
2799{
2800 unsigned int i;
2801 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2802 if (uc_id == interactive_usecases[i])
2803 return true;
2804 }
2805 return false;
2806}
2807
2808static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2809{
2810 audio_usecase_t ret_uc = USECASE_INVALID;
2811 unsigned int intract_uc_index;
2812 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2813
2814 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2815 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2816 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2817 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2818 ret_uc = interactive_usecases[intract_uc_index];
2819 break;
2820 }
2821 }
2822
2823 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2824 return ret_uc;
2825}
2826
2827static void free_interactive_usecase(struct audio_device *adev,
2828 audio_usecase_t uc_id)
2829{
2830 unsigned int interact_uc_index;
2831 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2832
2833 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2834 if (interactive_usecases[interact_uc_index] == uc_id) {
2835 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2836 break;
2837 }
2838 }
2839 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2840}
2841
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002842bool is_offload_usecase(audio_usecase_t uc_id)
2843{
2844 unsigned int i;
2845 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2846 if (uc_id == offload_usecases[i])
2847 return true;
2848 }
2849 return false;
2850}
2851
Dhananjay Kumarac341582017-02-23 23:42:25 +05302852static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002853{
vivek mehta446c3962015-09-14 10:57:35 -07002854 audio_usecase_t ret_uc = USECASE_INVALID;
2855 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002856 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002857 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302858 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002859 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2860 else
2861 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002862
vivek mehta446c3962015-09-14 10:57:35 -07002863 pthread_mutex_lock(&adev->lock);
2864 if (get_usecase_from_list(adev, ret_uc) != NULL)
2865 ret_uc = USECASE_INVALID;
2866 pthread_mutex_unlock(&adev->lock);
2867
2868 return ret_uc;
2869 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002870
2871 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002872 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2873 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2874 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2875 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002876 break;
2877 }
2878 }
vivek mehta446c3962015-09-14 10:57:35 -07002879
2880 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2881 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002882}
2883
2884static void free_offload_usecase(struct audio_device *adev,
2885 audio_usecase_t uc_id)
2886{
vivek mehta446c3962015-09-14 10:57:35 -07002887 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002888 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002889
2890 if (!adev->multi_offload_enable)
2891 return;
2892
2893 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2894 if (offload_usecases[offload_uc_index] == uc_id) {
2895 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002896 break;
2897 }
2898 }
2899 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2900}
2901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902static void *offload_thread_loop(void *context)
2903{
2904 struct stream_out *out = (struct stream_out *) context;
2905 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002906 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002909 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2911
2912 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002913 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 for (;;) {
2915 struct offload_cmd *cmd = NULL;
2916 stream_callback_event_t event;
2917 bool send_callback = false;
2918
2919 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2920 __func__, list_empty(&out->offload_cmd_list),
2921 out->offload_state);
2922 if (list_empty(&out->offload_cmd_list)) {
2923 ALOGV("%s SLEEPING", __func__);
2924 pthread_cond_wait(&out->offload_cond, &out->lock);
2925 ALOGV("%s RUNNING", __func__);
2926 continue;
2927 }
2928
2929 item = list_head(&out->offload_cmd_list);
2930 cmd = node_to_item(item, struct offload_cmd, node);
2931 list_remove(item);
2932
2933 ALOGVV("%s STATE %d CMD %d out->compr %p",
2934 __func__, out->offload_state, cmd->cmd, out->compr);
2935
2936 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2937 free(cmd);
2938 break;
2939 }
2940
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002941 // allow OFFLOAD_CMD_ERROR reporting during standby
2942 // this is needed to handle failures during compress_open
2943 // Note however that on a pause timeout, the stream is closed
2944 // and no offload usecase will be active. Therefore this
2945 // special case is needed for compress_open failures alone
2946 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2947 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002948 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002949 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950 pthread_cond_signal(&out->cond);
2951 continue;
2952 }
2953 out->offload_thread_blocked = true;
2954 pthread_mutex_unlock(&out->lock);
2955 send_callback = false;
2956 switch(cmd->cmd) {
2957 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002958 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002960 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002961 send_callback = true;
2962 event = STREAM_CBK_EVENT_WRITE_READY;
2963 break;
2964 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002965 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302966 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002967 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302968 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002969 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302970 if (ret < 0)
2971 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302972 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302973 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002974 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002975 else
2976 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002977 if (-ENETRESET != ret && !(-EINTR == ret &&
2978 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302979 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302980 pthread_mutex_lock(&out->lock);
2981 out->send_new_metadata = 1;
2982 out->send_next_track_params = true;
2983 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302984 event = STREAM_CBK_EVENT_DRAIN_READY;
2985 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2986 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302987 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002988 break;
2989 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002990 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002991 ret = compress_drain(out->compr);
2992 ALOGD("copl(%p):out of compress_drain", out);
2993 // EINTR check avoids drain interruption due to SSR
2994 if (-ENETRESET != ret && !(-EINTR == ret &&
2995 CARD_STATUS_OFFLINE == out->card_status)) {
2996 send_callback = true;
2997 event = STREAM_CBK_EVENT_DRAIN_READY;
2998 } else
2999 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303001 case OFFLOAD_CMD_ERROR:
3002 ALOGD("copl(%p): sending error callback to AF", out);
3003 send_callback = true;
3004 event = STREAM_CBK_EVENT_ERROR;
3005 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 default:
3007 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3008 break;
3009 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003010 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 out->offload_thread_blocked = false;
3012 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003013 if (send_callback && out->client_callback) {
3014 ALOGVV("%s: sending client_callback event %d", __func__, event);
3015 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003016 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017 free(cmd);
3018 }
3019
3020 pthread_cond_signal(&out->cond);
3021 while (!list_empty(&out->offload_cmd_list)) {
3022 item = list_head(&out->offload_cmd_list);
3023 list_remove(item);
3024 free(node_to_item(item, struct offload_cmd, node));
3025 }
3026 pthread_mutex_unlock(&out->lock);
3027
3028 return NULL;
3029}
3030
3031static int create_offload_callback_thread(struct stream_out *out)
3032{
3033 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3034 list_init(&out->offload_cmd_list);
3035 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3036 offload_thread_loop, out);
3037 return 0;
3038}
3039
3040static int destroy_offload_callback_thread(struct stream_out *out)
3041{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003042 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043 stop_compressed_output_l(out);
3044 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3045
3046 pthread_mutex_unlock(&out->lock);
3047 pthread_join(out->offload_thread, (void **) NULL);
3048 pthread_cond_destroy(&out->offload_cond);
3049
3050 return 0;
3051}
3052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053static int stop_output_stream(struct stream_out *out)
3054{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303055 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 struct audio_usecase *uc_info;
3057 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003058 bool has_voip_usecase =
3059 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060
Eric Laurent994a6932013-07-17 11:51:42 -07003061 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003062 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 uc_info = get_usecase_from_list(adev, out->usecase);
3064 if (uc_info == NULL) {
3065 ALOGE("%s: Could not find the usecase (%d) in the list",
3066 __func__, out->usecase);
3067 return -EINVAL;
3068 }
3069
Derek Chenea197282019-01-07 17:35:01 -08003070 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3071 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003072
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003073 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303074 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003075 if (adev->visualizer_stop_output != NULL)
3076 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003077
3078 audio_extn_dts_remove_state_notifier_node(out->usecase);
3079
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003080 if (adev->offload_effects_stop_output != NULL)
3081 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3082 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003083
Arun Mirpurief53ce52018-09-11 18:00:09 -07003084 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3085 voice_set_device_mute_flag(adev, false);
3086
Eric Laurent150dbfe2013-02-27 14:31:02 -08003087 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003088 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003089
3090 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003091 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092
Aalique Grahame22e49102018-12-18 14:23:57 -08003093 audio_extn_extspk_update(adev->extspk);
3094
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003095 if (is_offload_usecase(out->usecase)) {
3096 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3097 adev->dsp_bit_width_enforce_mode,
3098 false);
3099 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003100 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3101 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3102 false);
3103
3104 if (ret != 0)
3105 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3106 /* default service interval was successfully updated,
3107 reopen USB backend with new service interval */
3108 ret = 0;
3109 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003110
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003111 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303112 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003113 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303114 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003115 ALOGV("Disable passthrough , reset mixer to pcm");
3116 /* NO_PASSTHROUGH */
3117 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003118 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003119 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3120 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003121
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303122 /* Must be called after removing the usecase from list */
3123 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303124 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303125
Manish Dewangan21a850a2017-08-14 12:03:55 +05303126 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003127 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3128 if (ret < 0)
3129 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3130 }
3131
Aalique Grahame22e49102018-12-18 14:23:57 -08003132 if (has_voip_usecase ||
3133 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3134 struct listnode *node;
3135 struct audio_usecase *usecase;
3136 list_for_each(node, &adev->usecase_list) {
3137 usecase = node_to_item(node, struct audio_usecase, list);
3138 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3139 continue;
3140
3141 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3142 __func__, usecase->id, use_case_table[usecase->id],
3143 out->usecase, use_case_table[out->usecase]);
3144 select_devices(adev, usecase->id);
3145 }
3146 }
3147
Garmond Leung5fd0b552018-04-17 11:56:12 -07003148 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003149 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 return ret;
3151}
3152
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003153struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3154 unsigned int flags, unsigned int pcm_open_retry_count,
3155 struct pcm_config *config)
3156{
3157 struct pcm* pcm = NULL;
3158
3159 while (1) {
3160 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3161 if (pcm == NULL || !pcm_is_ready(pcm)) {
3162 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3163 if (pcm != NULL) {
3164 pcm_close(pcm);
3165 pcm = NULL;
3166 }
3167 if (pcm_open_retry_count-- == 0)
3168 return NULL;
3169
3170 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3171 continue;
3172 }
3173 break;
3174 }
3175
3176 if (pcm_is_ready(pcm)) {
3177 int ret = pcm_prepare(pcm);
3178 if (ret < 0) {
3179 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3180 pcm_close(pcm);
3181 pcm = NULL;
3182 }
3183 }
3184
3185 return pcm;
3186}
3187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188int start_output_stream(struct stream_out *out)
3189{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 struct audio_usecase *uc_info;
3192 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003193 char mixer_ctl_name[128];
3194 struct mixer_ctl *ctl = NULL;
3195 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303196 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003197 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198
Haynes Mathew George380745d2017-10-04 15:27:45 -07003199 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003200 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3201 ret = -EINVAL;
3202 goto error_config;
3203 }
3204
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003205 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303206 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003207 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303208
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303209 if (CARD_STATUS_OFFLINE == out->card_status ||
3210 CARD_STATUS_OFFLINE == adev->card_status) {
3211 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303212 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303213 goto error_config;
3214 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303215
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303216 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003217 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003218 if (out->devices &
3219 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303220 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303221 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303222 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3223 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3224 ret = -EAGAIN;
3225 goto error_config;
3226 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303227 }
3228 }
3229 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303230 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3231 if (!adev->bt_sco_on) {
3232 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3233 //combo usecase just by pass a2dp
3234 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3235 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3236 } else {
3237 ALOGE("%s: SCO profile is not ready, return error", __func__);
3238 ret = -EAGAIN;
3239 goto error_config;
3240 }
3241 }
3242 }
3243
Eric Laurentb23d5282013-05-14 15:27:20 -07003244 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 if (out->pcm_device_id < 0) {
3246 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3247 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003248 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003249 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 }
3251
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003252 if (is_haptic_usecase) {
3253 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3254 if (adev->haptic_pcm_device_id < 0) {
3255 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3256 __func__, adev->haptic_pcm_device_id, out->usecase);
3257 ret = -EINVAL;
3258 goto error_config;
3259 }
3260 }
3261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003263
3264 if (!uc_info) {
3265 ret = -ENOMEM;
3266 goto error_config;
3267 }
3268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 uc_info->id = out->usecase;
3270 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003271 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003272 uc_info->devices = out->devices;
3273 uc_info->in_snd_device = SND_DEVICE_NONE;
3274 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003275
3276 /* This must be called before adding this usecase to the list */
3277 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3278 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3279 /* USB backend is not reopened immediately.
3280 This is eventually done as part of select_devices */
3281 }
3282
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003283 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303285 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3286 adev->perf_lock_opts,
3287 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303288
3289 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303290 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303291 if (audio_extn_passthru_is_enabled() &&
3292 audio_extn_passthru_is_passthrough_stream(out)) {
3293 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303294 }
3295 }
3296
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303297 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003298 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303299 if (!a2dp_combo) {
3300 check_a2dp_restore_l(adev, out, false);
3301 } else {
3302 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003303 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3304 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3305 else
3306 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303307 select_devices(adev, out->usecase);
3308 out->devices = dev;
3309 }
3310 } else {
3311 select_devices(adev, out->usecase);
3312 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003313
Arun Mirpurief53ce52018-09-11 18:00:09 -07003314 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3315 voice_set_device_mute_flag(adev, true);
3316
Derek Chenea197282019-01-07 17:35:01 -08003317 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3318 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003319
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3321 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003322
3323 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3324 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3325 ALOGE("%s: pcm stream not ready", __func__);
3326 goto error_open;
3327 }
3328 ret = pcm_start(out->pcm);
3329 if (ret < 0) {
3330 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3331 goto error_open;
3332 }
3333 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003334 unsigned int flags = PCM_OUT;
3335 unsigned int pcm_open_retry_count = 0;
3336 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3337 flags |= PCM_MMAP | PCM_NOIRQ;
3338 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003339 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003340 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003341 } else
3342 flags |= PCM_MONOTONIC;
3343
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003344 if ((adev->vr_audio_mode_enabled) &&
3345 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3346 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3347 "PCM_Dev %d Topology", out->pcm_device_id);
3348 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3349 if (!ctl) {
3350 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3351 __func__, mixer_ctl_name);
3352 } else {
3353 //if success use ULLPP
3354 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3355 __func__, mixer_ctl_name, out->pcm_device_id);
3356 //There is a still a possibility that some sessions
3357 // that request for FAST|RAW when 3D audio is active
3358 //can go through ULLPP. Ideally we expects apps to
3359 //listen to audio focus and stop concurrent playback
3360 //Also, we will look for mode flag (voice_in_communication)
3361 //before enabling the realtime flag.
3362 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3363 }
3364 }
3365
Surendar Karka91fa3682018-07-02 18:12:12 +05303366 if (out->realtime)
3367 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3368 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3369
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003370 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3371 flags, pcm_open_retry_count,
3372 &(out->config));
3373 if (out->pcm == NULL) {
3374 ret = -EIO;
3375 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003377
3378 if (is_haptic_usecase) {
3379 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3380 adev->haptic_pcm_device_id,
3381 flags, pcm_open_retry_count,
3382 &(adev->haptics_config));
3383 // failure to open haptics pcm shouldnt stop audio,
3384 // so do not close audio pcm in case of error
3385 }
3386
Surendar Karka91fa3682018-07-02 18:12:12 +05303387 if (!out->realtime)
3388 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303389 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003390
Zhou Song2b8f28f2017-09-11 10:51:38 +08003391 // apply volume for voip playback after path is set up
3392 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3393 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303394 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3395 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303396 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3397 out->apply_volume = false;
3398 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003399 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003400 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303401 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003402 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3403 adev->dsp_bit_width_enforce_mode,
3404 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003406 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003407 out->compr = compress_open(adev->snd_card,
3408 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003409 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003410 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303411 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303412 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3413 adev->card_status = CARD_STATUS_OFFLINE;
3414 out->card_status = CARD_STATUS_OFFLINE;
3415 ret = -EIO;
3416 goto error_open;
3417 }
3418
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003419 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003420 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003421 compress_close(out->compr);
3422 out->compr = NULL;
3423 ret = -EIO;
3424 goto error_open;
3425 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303426 /* compress_open sends params of the track, so reset the flag here */
3427 out->is_compr_metadata_avail = false;
3428
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003429 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003431
Fred Oh3f43e742015-03-04 18:42:34 -08003432 /* Since small bufs uses blocking writes, a write will be blocked
3433 for the default max poll time (20s) in the event of an SSR.
3434 Reduce the poll time to observe and deal with SSR faster.
3435 */
Ashish Jain5106d362016-05-11 19:23:33 +05303436 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003437 compress_set_max_poll_wait(out->compr, 1000);
3438 }
3439
Manish Dewangan69426c82017-01-30 17:35:36 +05303440 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303441 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303442
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003443 audio_extn_dts_create_state_notifier_node(out->usecase);
3444 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3445 popcount(out->channel_mask),
3446 out->playback_started);
3447
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003448#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303449 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003450 audio_extn_dolby_send_ddp_endp_params(adev);
3451#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303452 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3453 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003454 if (adev->visualizer_start_output != NULL)
3455 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3456 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303457 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003458 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003461
3462 if (ret == 0) {
3463 register_out_stream(out);
3464 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003465 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3466 ALOGE("%s: pcm stream not ready", __func__);
3467 goto error_open;
3468 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003469 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003470 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003471 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003472 if (ret < 0)
3473 goto error_open;
3474 }
3475 }
3476
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303477 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003478 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003479
Manish Dewangan21a850a2017-08-14 12:03:55 +05303480 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003481 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003482 if (ret < 0)
3483 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3484 }
3485
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003486 // consider a scenario where on pause lower layers are tear down.
3487 // so on resume, swap mixer control need to be sent only when
3488 // backend is active, hence rather than sending from enable device
3489 // sending it from start of streamtream
3490
3491 platform_set_swap_channels(adev, true);
3492
Haynes Mathew George380745d2017-10-04 15:27:45 -07003493 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303494 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003495 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003497 if (adev->haptic_pcm) {
3498 pcm_close(adev->haptic_pcm);
3499 adev->haptic_pcm = NULL;
3500 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303501 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003503error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303504 /*
3505 * sleep 50ms to allow sufficient time for kernel
3506 * drivers to recover incases like SSR.
3507 */
3508 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003509 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303510 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003511 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512}
3513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514static int check_input_parameters(uint32_t sample_rate,
3515 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003516 int channel_count,
3517 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003519 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303521 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3522 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3523 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003524 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003525 !audio_extn_compr_cap_format_supported(format) &&
3526 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003527 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003528
Aalique Grahame22e49102018-12-18 14:23:57 -08003529 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3530 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3531 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3532 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3533 return -EINVAL;
3534 }
3535
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003536 switch (channel_count) {
3537 case 1:
3538 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303539 case 3:
3540 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003541 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003542 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003543 break;
3544 default:
3545 ret = -EINVAL;
3546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547
3548 switch (sample_rate) {
3549 case 8000:
3550 case 11025:
3551 case 12000:
3552 case 16000:
3553 case 22050:
3554 case 24000:
3555 case 32000:
3556 case 44100:
3557 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003558 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303559 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003560 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303561 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 break;
3563 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003564 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 }
3566
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003567 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568}
3569
Naresh Tanniru04f71882018-06-26 17:46:22 +05303570
3571/** Add a value in a list if not already present.
3572 * @return true if value was successfully inserted or already present,
3573 * false if the list is full and does not contain the value.
3574 */
3575static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3576 for (size_t i = 0; i < list_length; i++) {
3577 if (list[i] == value) return true; // value is already present
3578 if (list[i] == 0) { // no values in this slot
3579 list[i] = value;
3580 return true; // value inserted
3581 }
3582 }
3583 return false; // could not insert value
3584}
3585
3586/** Add channel_mask in supported_channel_masks if not already present.
3587 * @return true if channel_mask was successfully inserted or already present,
3588 * false if supported_channel_masks is full and does not contain channel_mask.
3589 */
3590static void register_channel_mask(audio_channel_mask_t channel_mask,
3591 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3592 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3593 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3594}
3595
3596/** Add format in supported_formats if not already present.
3597 * @return true if format was successfully inserted or already present,
3598 * false if supported_formats is full and does not contain format.
3599 */
3600static void register_format(audio_format_t format,
3601 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3602 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3603 "%s: stream can not declare supporting its format %x", __func__, format);
3604}
3605/** Add sample_rate in supported_sample_rates if not already present.
3606 * @return true if sample_rate was successfully inserted or already present,
3607 * false if supported_sample_rates is full and does not contain sample_rate.
3608 */
3609static void register_sample_rate(uint32_t sample_rate,
3610 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3611 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3612 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3613}
3614
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003615static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3616{
3617 uint32_t high = num1, low = num2, temp = 0;
3618
3619 if (!num1 || !num2)
3620 return 0;
3621
3622 if (num1 < num2) {
3623 high = num2;
3624 low = num1;
3625 }
3626
3627 while (low != 0) {
3628 temp = low;
3629 low = high % low;
3630 high = temp;
3631 }
3632 return (num1 * num2)/high;
3633}
3634
3635static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3636{
3637 uint32_t remainder = 0;
3638
3639 if (!multiplier)
3640 return num;
3641
3642 remainder = num % multiplier;
3643 if (remainder)
3644 num += (multiplier - remainder);
3645
3646 return num;
3647}
3648
Aalique Grahame22e49102018-12-18 14:23:57 -08003649static size_t get_stream_buffer_size(size_t duration_ms,
3650 uint32_t sample_rate,
3651 audio_format_t format,
3652 int channel_count,
3653 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654{
3655 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003656 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657
Aalique Grahame22e49102018-12-18 14:23:57 -08003658 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003659 if (is_low_latency)
3660 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303661
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003662 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003663 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664
Ralf Herzbd08d632018-09-28 15:50:49 +02003665 /* make sure the size is multiple of 32 bytes and additionally multiple of
3666 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003667 * At 48 kHz mono 16-bit PCM:
3668 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3669 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003670 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003671 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003672 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003673
3674 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675}
3676
Aalique Grahame22e49102018-12-18 14:23:57 -08003677static size_t get_input_buffer_size(uint32_t sample_rate,
3678 audio_format_t format,
3679 int channel_count,
3680 bool is_low_latency)
3681{
3682 /* Don't know if USB HIFI in this context so use true to be conservative */
3683 if (check_input_parameters(sample_rate, format, channel_count,
3684 true /*is_usb_hifi */) != 0)
3685 return 0;
3686
3687 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3688 sample_rate,
3689 format,
3690 channel_count,
3691 is_low_latency);
3692}
3693
Ashish Jain058165c2016-09-28 23:18:48 +05303694static size_t get_output_period_size(uint32_t sample_rate,
3695 audio_format_t format,
3696 int channel_count,
3697 int duration /*in millisecs*/)
3698{
3699 size_t size = 0;
3700 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3701
3702 if ((duration == 0) || (sample_rate == 0) ||
3703 (bytes_per_sample == 0) || (channel_count == 0)) {
3704 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3705 bytes_per_sample, channel_count);
3706 return -EINVAL;
3707 }
3708
3709 size = (sample_rate *
3710 duration *
3711 bytes_per_sample *
3712 channel_count) / 1000;
3713 /*
3714 * To have same PCM samples for all channels, the buffer size requires to
3715 * be multiple of (number of channels * bytes per sample)
3716 * For writes to succeed, the buffer must be written at address which is multiple of 32
3717 */
3718 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3719
3720 return (size/(channel_count * bytes_per_sample));
3721}
3722
Zhou Song48453a02018-01-10 17:50:59 +08003723static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303724{
3725 uint64_t actual_frames_rendered = 0;
3726 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3727
3728 /* This adjustment accounts for buffering after app processor.
3729 * It is based on estimated DSP latency per use case, rather than exact.
3730 */
3731 int64_t platform_latency = platform_render_latency(out->usecase) *
3732 out->sample_rate / 1000000LL;
3733
Zhou Song48453a02018-01-10 17:50:59 +08003734 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303735 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3736 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3737 * hence only estimate.
3738 */
3739 int64_t signed_frames = out->written - kernel_buffer_size;
3740
3741 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3742
Zhou Song48453a02018-01-10 17:50:59 +08003743 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303744 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003745 if (timestamp != NULL )
3746 *timestamp = out->writeAt;
3747 } else if (timestamp != NULL) {
3748 clock_gettime(CLOCK_MONOTONIC, timestamp);
3749 }
3750 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303751
3752 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3753 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3754 (long long int)out->written, (int)kernel_buffer_size,
3755 audio_bytes_per_sample(out->compr_config.codec->format),
3756 popcount(out->channel_mask));
3757
3758 return actual_frames_rendered;
3759}
3760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3762{
3763 struct stream_out *out = (struct stream_out *)stream;
3764
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003765 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766}
3767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003768static int out_set_sample_rate(struct audio_stream *stream __unused,
3769 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770{
3771 return -ENOSYS;
3772}
3773
3774static size_t out_get_buffer_size(const struct audio_stream *stream)
3775{
3776 struct stream_out *out = (struct stream_out *)stream;
3777
Varun Balaraje49253e2017-07-06 19:48:56 +05303778 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303779 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303780 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303781 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3782 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3783 else
3784 return out->compr_config.fragment_size;
3785 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003786 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003787 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3788 return VOIP_IO_BUF_SIZE(out->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Dhananjay Kumarac341582017-02-23 23:42:25 +05303789 else if (is_offload_usecase(out->usecase) &&
3790 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303791 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003793 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003794 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795}
3796
3797static uint32_t out_get_channels(const struct audio_stream *stream)
3798{
3799 struct stream_out *out = (struct stream_out *)stream;
3800
3801 return out->channel_mask;
3802}
3803
3804static audio_format_t out_get_format(const struct audio_stream *stream)
3805{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003806 struct stream_out *out = (struct stream_out *)stream;
3807
3808 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809}
3810
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003811static int out_set_format(struct audio_stream *stream __unused,
3812 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813{
3814 return -ENOSYS;
3815}
3816
3817static int out_standby(struct audio_stream *stream)
3818{
3819 struct stream_out *out = (struct stream_out *)stream;
3820 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003821 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303823 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3824 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003826 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003828 if (adev->adm_deregister_stream)
3829 adev->adm_deregister_stream(adev->adm_data, out->handle);
3830
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003831 if (is_offload_usecase(out->usecase))
3832 stop_compressed_output_l(out);
3833
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003834 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003836 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3837 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303838 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003839 pthread_mutex_unlock(&adev->lock);
3840 pthread_mutex_unlock(&out->lock);
3841 ALOGD("VOIP output entered standby");
3842 return 0;
3843 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003844 if (out->pcm) {
3845 pcm_close(out->pcm);
3846 out->pcm = NULL;
3847 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003848 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3849 do_stop = out->playback_started;
3850 out->playback_started = false;
3851 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003852 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003853 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303854 out->send_next_track_params = false;
3855 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003856 out->gapless_mdata.encoder_delay = 0;
3857 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 if (out->compr != NULL) {
3859 compress_close(out->compr);
3860 out->compr = NULL;
3861 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003862 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003863 if (do_stop) {
3864 stop_output_stream(out);
3865 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003866 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 }
3868 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303869 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 return 0;
3871}
3872
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303873static int out_on_error(struct audio_stream *stream)
3874{
3875 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003876 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303877
3878 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003879 // always send CMD_ERROR for offload streams, this
3880 // is needed e.g. when SSR happens within compress_open
3881 // since the stream is active, offload_callback_thread is also active.
3882 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3883 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003884 }
3885 pthread_mutex_unlock(&out->lock);
3886
3887 status = out_standby(&out->stream.common);
3888
3889 lock_output_stream(out);
3890 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003891 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303892 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303893
3894 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3895 ALOGD("Setting previous card status if offline");
3896 out->prev_card_status_offline = true;
3897 }
3898
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303899 pthread_mutex_unlock(&out->lock);
3900
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003901 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303902}
3903
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303904/*
3905 *standby implementation without locks, assumes that the callee already
3906 *has taken adev and out lock.
3907 */
3908int out_standby_l(struct audio_stream *stream)
3909{
3910 struct stream_out *out = (struct stream_out *)stream;
3911 struct audio_device *adev = out->dev;
3912
3913 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3914 stream, out->usecase, use_case_table[out->usecase]);
3915
3916 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003917 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303918 if (adev->adm_deregister_stream)
3919 adev->adm_deregister_stream(adev->adm_data, out->handle);
3920
3921 if (is_offload_usecase(out->usecase))
3922 stop_compressed_output_l(out);
3923
3924 out->standby = true;
3925 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3926 voice_extn_compress_voip_close_output_stream(stream);
3927 out->started = 0;
3928 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003929 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303930 return 0;
3931 } else if (!is_offload_usecase(out->usecase)) {
3932 if (out->pcm) {
3933 pcm_close(out->pcm);
3934 out->pcm = NULL;
3935 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003936 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3937 if (adev->haptic_pcm) {
3938 pcm_close(adev->haptic_pcm);
3939 adev->haptic_pcm = NULL;
3940 }
3941
3942 if (adev->haptic_buffer != NULL) {
3943 free(adev->haptic_buffer);
3944 adev->haptic_buffer = NULL;
3945 adev->haptic_buffer_size = 0;
3946 }
3947 adev->haptic_pcm_device_id = 0;
3948 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303949 } else {
3950 ALOGD("copl(%p):standby", out);
3951 out->send_next_track_params = false;
3952 out->is_compr_metadata_avail = false;
3953 out->gapless_mdata.encoder_delay = 0;
3954 out->gapless_mdata.encoder_padding = 0;
3955 if (out->compr != NULL) {
3956 compress_close(out->compr);
3957 out->compr = NULL;
3958 }
3959 }
3960 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003961 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303962 }
3963 ALOGD("%s: exit", __func__);
3964 return 0;
3965}
3966
Aalique Grahame22e49102018-12-18 14:23:57 -08003967static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968{
Aalique Grahame22e49102018-12-18 14:23:57 -08003969 struct stream_out *out = (struct stream_out *)stream;
3970
3971 // We try to get the lock for consistency,
3972 // but it isn't necessary for these variables.
3973 // If we're not in standby, we may be blocked on a write.
3974 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
3975 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
3976 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
3977
3978 if (locked) {
3979 pthread_mutex_unlock(&out->lock);
3980 }
3981
3982 // dump error info
3983 (void)error_log_dump(
3984 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
3985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 return 0;
3987}
3988
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003989static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3990{
3991 int ret = 0;
3992 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003993
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003994 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003995 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003996 return -EINVAL;
3997 }
3998
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303999 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004000
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004001 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4002 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304003 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004004 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004005 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4006 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304007 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004008 }
4009
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004010 ALOGV("%s new encoder delay %u and padding %u", __func__,
4011 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4012
4013 return 0;
4014}
4015
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004016static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4017{
4018 return out == adev->primary_output || out == adev->voice_tx_output;
4019}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004020
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304021// note: this call is safe only if the stream_cb is
4022// removed first in close_output_stream (as is done now).
4023static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4024{
4025 if (!stream || !parms)
4026 return;
4027
4028 struct stream_out *out = (struct stream_out *)stream;
4029 struct audio_device *adev = out->dev;
4030
4031 card_status_t status;
4032 int card;
4033 if (parse_snd_card_status(parms, &card, &status) < 0)
4034 return;
4035
4036 pthread_mutex_lock(&adev->lock);
4037 bool valid_cb = (card == adev->snd_card);
4038 pthread_mutex_unlock(&adev->lock);
4039
4040 if (!valid_cb)
4041 return;
4042
4043 lock_output_stream(out);
4044 if (out->card_status != status)
4045 out->card_status = status;
4046 pthread_mutex_unlock(&out->lock);
4047
4048 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4049 use_case_table[out->usecase],
4050 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4051
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304052 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304053 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304054 if (voice_is_call_state_active(adev) &&
4055 out == adev->primary_output) {
4056 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4057 pthread_mutex_lock(&adev->lock);
4058 voice_stop_call(adev);
4059 adev->mode = AUDIO_MODE_NORMAL;
4060 pthread_mutex_unlock(&adev->lock);
4061 }
4062 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304063 return;
4064}
4065
Kevin Rocardfce19002017-08-07 19:21:36 -07004066static int get_alive_usb_card(struct str_parms* parms) {
4067 int card;
4068 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4069 !audio_extn_usb_alive(card)) {
4070 return card;
4071 }
4072 return -ENODEV;
4073}
4074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4076{
4077 struct stream_out *out = (struct stream_out *)stream;
4078 struct audio_device *adev = out->dev;
4079 struct str_parms *parms;
4080 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004081 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304082 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004083 bool reconfig = false;
4084 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085
sangwoobc677242013-08-08 16:53:43 +09004086 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004087 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304089 if (!parms)
4090 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004091 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4092 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004094 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004095 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004097 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004098 * When HDMI cable is unplugged the music playback is paused and
4099 * the policy manager sends routing=0. But the audioflinger continues
4100 * to write data until standby time (3sec). As the HDMI core is
4101 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004102 * Avoid this by routing audio to speaker until standby.
4103 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004104 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4105 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304106 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004107 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4108 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004109 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304110 /*
4111 * When A2DP is disconnected the
4112 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004113 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304114 * (3sec). As BT is turned off, the write gets blocked.
4115 * Avoid this by routing audio to speaker until standby.
4116 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004117 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004118 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004119 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304120 val = AUDIO_DEVICE_OUT_SPEAKER;
4121 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304122 /*
4123 * When USB headset is disconnected the music platback paused
4124 * and the policy manager send routing=0. But if the USB is connected
4125 * back before the standby time, AFE is not closed and opened
4126 * when USB is connected back. So routing to speker will guarantee
4127 * AFE reconfiguration and AFE will be opend once USB is connected again
4128 */
4129 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4130 (val == AUDIO_DEVICE_NONE) &&
4131 !audio_extn_usb_connected(parms)) {
4132 val = AUDIO_DEVICE_OUT_SPEAKER;
4133 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304134 /* To avoid a2dp to sco overlapping / BT device improper state
4135 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304136 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304137 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004138 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004139 if (val &
4140 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304141 //combo usecase just by pass a2dp
4142 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304143 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304144 } else {
4145 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4146 /* update device to a2dp and don't route as BT returned error
4147 * However it is still possible a2dp routing called because
4148 * of current active device disconnection (like wired headset)
4149 */
4150 out->devices = val;
4151 pthread_mutex_unlock(&out->lock);
4152 pthread_mutex_unlock(&adev->lock);
4153 goto error;
4154 }
4155 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304156 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004157
4158 audio_devices_t new_dev = val;
4159
4160 // Workaround: If routing to an non existing usb device, fail gracefully
4161 // The routing request will otherwise block during 10 second
4162 int card;
4163 if (audio_is_usb_out_device(new_dev) &&
4164 (card = get_alive_usb_card(parms)) >= 0) {
4165
4166 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4167 pthread_mutex_unlock(&adev->lock);
4168 pthread_mutex_unlock(&out->lock);
4169 ret = -ENOSYS;
4170 goto routing_fail;
4171 }
4172
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004173 /*
4174 * select_devices() call below switches all the usecases on the same
4175 * backend to the new device. Refer to check_usecases_codec_backend() in
4176 * the select_devices(). But how do we undo this?
4177 *
4178 * For example, music playback is active on headset (deep-buffer usecase)
4179 * and if we go to ringtones and select a ringtone, low-latency usecase
4180 * will be started on headset+speaker. As we can't enable headset+speaker
4181 * and headset devices at the same time, select_devices() switches the music
4182 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4183 * So when the ringtone playback is completed, how do we undo the same?
4184 *
4185 * We are relying on the out_set_parameters() call on deep-buffer output,
4186 * once the ringtone playback is ended.
4187 * NOTE: We should not check if the current devices are same as new devices.
4188 * Because select_devices() must be called to switch back the music
4189 * playback to headset.
4190 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004191 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004192 audio_devices_t new_dev = val;
4193 bool same_dev = out->devices == new_dev;
4194 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004195
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004196 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004197 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004198 if (adev->mode == AUDIO_MODE_IN_CALL) {
4199 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004200 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4201 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4202 audio_extn_usb_set_service_interval(true /*playback*/,
4203 service_interval,
4204 &reconfig);
4205 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4206 }
4207 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004208 }
4209 } else {
4210 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004211 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004212 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004213 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004214
4215 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004216 if (!same_dev) {
4217 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304218 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4219 adev->perf_lock_opts,
4220 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004221 if (adev->adm_on_routing_change)
4222 adev->adm_on_routing_change(adev->adm_data,
4223 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004224 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304225 if (!bypass_a2dp) {
4226 select_devices(adev, out->usecase);
4227 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004228 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4229 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4230 else
4231 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304232 select_devices(adev, out->usecase);
4233 out->devices = new_dev;
4234 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004235
4236 if (!same_dev) {
4237 // on device switch force swap, lower functions will make sure
4238 // to check if swap is allowed or not.
4239 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304240 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004241 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304242 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4243 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004244 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304245 pthread_mutex_lock(&out->compr_mute_lock);
4246 out->a2dp_compress_mute = false;
4247 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4248 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004249 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4250 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304251 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004252 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004253 }
4254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004256 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004257
4258 /*handles device and call state changes*/
4259 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004261 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004262
4263 if (out == adev->primary_output) {
4264 pthread_mutex_lock(&adev->lock);
4265 audio_extn_set_parameters(adev, parms);
4266 pthread_mutex_unlock(&adev->lock);
4267 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004268 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004269 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004270 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004271
4272 audio_extn_dts_create_state_notifier_node(out->usecase);
4273 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4274 popcount(out->channel_mask),
4275 out->playback_started);
4276
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004277 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004278 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004279
Surendar Karkaf51b5842018-04-26 11:28:38 +05304280 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4281 sizeof(value));
4282 if (err >= 0) {
4283 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4284 audio_extn_send_dual_mono_mixing_coefficients(out);
4285 }
4286
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304287 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4288 if (err >= 0) {
4289 strlcpy(out->profile, value, sizeof(out->profile));
4290 ALOGV("updating stream profile with value '%s'", out->profile);
4291 lock_output_stream(out);
4292 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4293 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004294 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304295 out->sample_rate, out->bit_width,
4296 out->channel_mask, out->profile,
4297 &out->app_type_cfg);
4298 pthread_mutex_unlock(&out->lock);
4299 }
4300
Alexy Joseph98988832017-01-13 14:56:59 -08004301 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004302 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4303 // and vendor.audio.hal.output.suspend.supported is set to true
4304 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004305 //check suspend parameter only for low latency and if the property
4306 //is enabled
4307 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4308 ALOGI("%s: got suspend_playback %s", __func__, value);
4309 lock_output_stream(out);
4310 if (!strncmp(value, "false", 5)) {
4311 //suspend_playback=false is supposed to set QOS value back to 75%
4312 //the mixer control sent with value Enable will achieve that
4313 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4314 } else if (!strncmp (value, "true", 4)) {
4315 //suspend_playback=true is supposed to remove QOS value
4316 //resetting the mixer control will set the default value
4317 //for the mixer control which is Disable and this removes the QOS vote
4318 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4319 } else {
4320 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4321 " got %s", __func__, value);
4322 ret = -1;
4323 }
4324
4325 if (ret != 0) {
4326 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4327 __func__, out->pm_qos_mixer_path, ret);
4328 }
4329
4330 pthread_mutex_unlock(&out->lock);
4331 }
4332 }
4333 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304335error:
Eric Laurent994a6932013-07-17 11:51:42 -07004336 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 return ret;
4338}
4339
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004340static bool stream_get_parameter_channels(struct str_parms *query,
4341 struct str_parms *reply,
4342 audio_channel_mask_t *supported_channel_masks) {
4343 int ret = -1;
4344 char value[512];
4345 bool first = true;
4346 size_t i, j;
4347
4348 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4349 ret = 0;
4350 value[0] = '\0';
4351 i = 0;
4352 while (supported_channel_masks[i] != 0) {
4353 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4354 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4355 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304356 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004357
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304358 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004359 first = false;
4360 break;
4361 }
4362 }
4363 i++;
4364 }
4365 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4366 }
4367 return ret == 0;
4368}
4369
4370static bool stream_get_parameter_formats(struct str_parms *query,
4371 struct str_parms *reply,
4372 audio_format_t *supported_formats) {
4373 int ret = -1;
4374 char value[256];
4375 size_t i, j;
4376 bool first = true;
4377
4378 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4379 ret = 0;
4380 value[0] = '\0';
4381 i = 0;
4382 while (supported_formats[i] != 0) {
4383 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4384 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4385 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304386 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004387 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304388 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004389 first = false;
4390 break;
4391 }
4392 }
4393 i++;
4394 }
4395 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4396 }
4397 return ret == 0;
4398}
4399
4400static bool stream_get_parameter_rates(struct str_parms *query,
4401 struct str_parms *reply,
4402 uint32_t *supported_sample_rates) {
4403
4404 int i;
4405 char value[256];
4406 int ret = -1;
4407 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4408 ret = 0;
4409 value[0] = '\0';
4410 i=0;
4411 int cursor = 0;
4412 while (supported_sample_rates[i]) {
4413 int avail = sizeof(value) - cursor;
4414 ret = snprintf(value + cursor, avail, "%s%d",
4415 cursor > 0 ? "|" : "",
4416 supported_sample_rates[i]);
4417 if (ret < 0 || ret >= avail) {
4418 // if cursor is at the last element of the array
4419 // overwrite with \0 is duplicate work as
4420 // snprintf already put a \0 in place.
4421 // else
4422 // we had space to write the '|' at value[cursor]
4423 // (which will be overwritten) or no space to fill
4424 // the first element (=> cursor == 0)
4425 value[cursor] = '\0';
4426 break;
4427 }
4428 cursor += ret;
4429 ++i;
4430 }
4431 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4432 value);
4433 }
4434 return ret >= 0;
4435}
4436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4438{
4439 struct stream_out *out = (struct stream_out *)stream;
4440 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004441 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004442 char value[256];
4443 struct str_parms *reply = str_parms_create();
4444 size_t i, j;
4445 int ret;
4446 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004447
4448 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004449 if (reply) {
4450 str_parms_destroy(reply);
4451 }
4452 if (query) {
4453 str_parms_destroy(query);
4454 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004455 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4456 return NULL;
4457 }
4458
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004459 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4461 if (ret >= 0) {
4462 value[0] = '\0';
4463 i = 0;
4464 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004465 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4466 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004468 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004470 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471 first = false;
4472 break;
4473 }
4474 }
4475 i++;
4476 }
4477 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4478 str = str_parms_to_str(reply);
4479 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004480 voice_extn_out_get_parameters(out, query, reply);
4481 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004483
Alexy Joseph62142aa2015-11-16 15:10:34 -08004484
4485 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4486 if (ret >= 0) {
4487 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304488 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4489 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004490 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304491 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004492 } else {
4493 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304494 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004495 }
4496 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004497 if (str)
4498 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004499 str = str_parms_to_str(reply);
4500 }
4501
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004502 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4503 if (ret >= 0) {
4504 value[0] = '\0';
4505 i = 0;
4506 first = true;
4507 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004508 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4509 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004510 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004511 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004512 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004513 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004514 first = false;
4515 break;
4516 }
4517 }
4518 i++;
4519 }
4520 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004521 if (str)
4522 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004523 str = str_parms_to_str(reply);
4524 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004525
4526 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4527 if (ret >= 0) {
4528 value[0] = '\0';
4529 i = 0;
4530 first = true;
4531 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004532 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4533 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004534 if (!first) {
4535 strlcat(value, "|", sizeof(value));
4536 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004537 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004538 first = false;
4539 break;
4540 }
4541 }
4542 i++;
4543 }
4544 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4545 if (str)
4546 free(str);
4547 str = str_parms_to_str(reply);
4548 }
4549
Alexy Joseph98988832017-01-13 14:56:59 -08004550 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4551 //only low latency track supports suspend_resume
4552 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004553 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004554 if (str)
4555 free(str);
4556 str = str_parms_to_str(reply);
4557 }
4558
4559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 str_parms_destroy(query);
4561 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004562 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 return str;
4564}
4565
4566static uint32_t out_get_latency(const struct audio_stream_out *stream)
4567{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004568 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004570 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571
Alexy Josephaa54c872014-12-03 02:46:47 -08004572 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304573 lock_output_stream(out);
4574 latency = audio_extn_utils_compress_get_dsp_latency(out);
4575 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004576 } else if ((out->realtime) ||
4577 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004578 // since the buffer won't be filled up faster than realtime,
4579 // return a smaller number
4580 if (out->config.rate)
4581 period_ms = (out->af_period_multiplier * out->config.period_size *
4582 1000) / (out->config.rate);
4583 else
4584 period_ms = 0;
4585 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004586 } else {
4587 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004588 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004589 }
4590
yidongh0515e042017-07-06 15:00:34 +08004591 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004592 latency += audio_extn_a2dp_get_encoder_latency();
4593
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304594 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004595 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596}
4597
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304598static float AmpToDb(float amplification)
4599{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304600 float db = DSD_VOLUME_MIN_DB;
4601 if (amplification > 0) {
4602 db = 20 * log10(amplification);
4603 if(db < DSD_VOLUME_MIN_DB)
4604 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304605 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304606 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304607}
4608
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304609static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4610 float right)
4611{
4612 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304613 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304614 char mixer_ctl_name[128];
4615 struct audio_device *adev = out->dev;
4616 struct mixer_ctl *ctl;
4617 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4618 PCM_PLAYBACK);
4619
4620 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4621 "Compress Playback %d Volume", pcm_device_id);
4622 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4623 if (!ctl) {
4624 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4625 __func__, mixer_ctl_name);
4626 return -EINVAL;
4627 }
4628 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4629 __func__, mixer_ctl_name, left, right);
4630 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4631 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4632 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4633
4634 return 0;
4635}
4636
Zhou Song2b8f28f2017-09-11 10:51:38 +08004637static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4638 float right)
4639{
4640 struct stream_out *out = (struct stream_out *)stream;
4641 char mixer_ctl_name[] = "App Type Gain";
4642 struct audio_device *adev = out->dev;
4643 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304644 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004645
4646 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4647 if (!ctl) {
4648 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4649 __func__, mixer_ctl_name);
4650 return -EINVAL;
4651 }
4652
4653 set_values[0] = 0; //0: Rx Session 1:Tx Session
4654 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304655 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4656 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004657
4658 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4659 return 0;
4660}
4661
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304662static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4663 float right)
4664{
4665 struct stream_out *out = (struct stream_out *)stream;
4666 /* Volume control for pcm playback */
4667 if (left != right) {
4668 return -EINVAL;
4669 } else {
4670 char mixer_ctl_name[128];
4671 struct audio_device *adev = out->dev;
4672 struct mixer_ctl *ctl;
4673 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4674 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4675 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4676 if (!ctl) {
4677 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4678 return -EINVAL;
4679 }
4680
4681 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4682 int ret = mixer_ctl_set_value(ctl, 0, volume);
4683 if (ret < 0) {
4684 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4685 return -EINVAL;
4686 }
4687
4688 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4689
4690 return 0;
4691 }
4692}
4693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694static int out_set_volume(struct audio_stream_out *stream, float left,
4695 float right)
4696{
Eric Laurenta9024de2013-04-04 09:19:12 -07004697 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004698 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304699 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004700
Eric Laurenta9024de2013-04-04 09:19:12 -07004701 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4702 /* only take left channel into account: the API is for stereo anyway */
4703 out->muted = (left == 0.0f);
4704 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004705 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304706 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004707 /*
4708 * Set mute or umute on HDMI passthrough stream.
4709 * Only take left channel into account.
4710 * Mute is 0 and unmute 1
4711 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304712 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304713 } else if (out->format == AUDIO_FORMAT_DSD){
4714 char mixer_ctl_name[128] = "DSD Volume";
4715 struct audio_device *adev = out->dev;
4716 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4717
4718 if (!ctl) {
4719 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4720 __func__, mixer_ctl_name);
4721 return -EINVAL;
4722 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304723 volume[0] = (long)(AmpToDb(left));
4724 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304725 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4726 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004727 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304728 pthread_mutex_lock(&out->compr_mute_lock);
4729 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4730 if (!out->a2dp_compress_mute)
4731 ret = out_set_compr_volume(stream, left, right);
4732 out->volume_l = left;
4733 out->volume_r = right;
4734 pthread_mutex_unlock(&out->compr_mute_lock);
4735 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004736 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004737 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004738 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4739 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4740 if (!out->standby) {
4741 audio_extn_utils_send_app_type_gain(out->dev,
4742 out->app_type_cfg.app_type,
4743 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004744 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004745 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004746 out->volume_l = left;
4747 out->volume_r = right;
4748 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304749 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304750 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4751 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304752 /* Volume control for pcm playback */
4753 if (!out->standby)
4754 ret = out_set_pcm_volume(stream, left, right);
4755 else
4756 out->apply_volume = true;
4757
4758 out->volume_l = left;
4759 out->volume_r = right;
4760 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004761 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763 return -ENOSYS;
4764}
4765
Zhou Songc9672822017-08-16 16:01:39 +08004766static void update_frames_written(struct stream_out *out, size_t bytes)
4767{
4768 size_t bpf = 0;
4769
4770 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4771 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4772 bpf = 1;
4773 else if (!is_offload_usecase(out->usecase))
4774 bpf = audio_bytes_per_sample(out->format) *
4775 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004776
4777 pthread_mutex_lock(&out->position_query_lock);
4778 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004779 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004780 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4781 }
4782 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004783}
4784
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004785int split_and_write_audio_haptic_data(struct stream_out *out,
4786 const void *buffer, size_t bytes_to_write)
4787{
4788 struct audio_device *adev = out->dev;
4789
4790 int ret = 0;
4791 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4792 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4793 size_t frame_size = channel_count * bytes_per_sample;
4794 size_t frame_count = bytes_to_write / frame_size;
4795
4796 bool force_haptic_path =
4797 property_get_bool("vendor.audio.test_haptic", false);
4798
4799 // extract Haptics data from Audio buffer
4800 bool alloc_haptic_buffer = false;
4801 int haptic_channel_count = adev->haptics_config.channels;
4802 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4803 size_t audio_frame_size = frame_size - haptic_frame_size;
4804 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4805
4806 if (adev->haptic_buffer == NULL) {
4807 alloc_haptic_buffer = true;
4808 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4809 free(adev->haptic_buffer);
4810 adev->haptic_buffer_size = 0;
4811 alloc_haptic_buffer = true;
4812 }
4813
4814 if (alloc_haptic_buffer) {
4815 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4816 adev->haptic_buffer_size = total_haptic_buffer_size;
4817 }
4818
4819 size_t src_index = 0, aud_index = 0, hap_index = 0;
4820 uint8_t *audio_buffer = (uint8_t *)buffer;
4821 uint8_t *haptic_buffer = adev->haptic_buffer;
4822
4823 // This is required for testing only. This works for stereo data only.
4824 // One channel is fed to audio stream and other to haptic stream for testing.
4825 if (force_haptic_path)
4826 audio_frame_size = haptic_frame_size = bytes_per_sample;
4827
4828 for (size_t i = 0; i < frame_count; i++) {
4829 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4830 audio_frame_size);
4831 aud_index += audio_frame_size;
4832 src_index += audio_frame_size;
4833
4834 if (adev->haptic_pcm)
4835 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4836 haptic_frame_size);
4837 hap_index += haptic_frame_size;
4838 src_index += haptic_frame_size;
4839
4840 // This is required for testing only.
4841 // Discard haptic channel data.
4842 if (force_haptic_path)
4843 src_index += haptic_frame_size;
4844 }
4845
4846 // write to audio pipeline
4847 ret = pcm_write(out->pcm, (void *)audio_buffer,
4848 frame_count * audio_frame_size);
4849
4850 // write to haptics pipeline
4851 if (adev->haptic_pcm)
4852 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4853 frame_count * haptic_frame_size);
4854
4855 return ret;
4856}
4857
Aalique Grahame22e49102018-12-18 14:23:57 -08004858#ifdef NO_AUDIO_OUT
4859static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4860 const void *buffer __unused, size_t bytes)
4861{
4862 struct stream_out *out = (struct stream_out *)stream;
4863
4864 /* No Output device supported other than BT for playback.
4865 * Sleep for the amount of buffer duration
4866 */
4867 lock_output_stream(out);
4868 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4869 (const struct audio_stream_out *)&out->stream) /
4870 out_get_sample_rate(&out->stream.common));
4871 pthread_mutex_unlock(&out->lock);
4872 return bytes;
4873}
4874#endif
4875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4877 size_t bytes)
4878{
4879 struct stream_out *out = (struct stream_out *)stream;
4880 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004881 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304882 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004883 const size_t frame_size = audio_stream_out_frame_size(stream);
4884 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885
Haynes Mathew George380745d2017-10-04 15:27:45 -07004886 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004887 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304888
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304889 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004890
Dhananjay Kumarac341582017-02-23 23:42:25 +05304891 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304892 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304893 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4894 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004895 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304896 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304897 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304898 ALOGD(" %s: sound card is not active/SSR state", __func__);
4899 ret= -EIO;
4900 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304901 }
4902 }
4903
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304904 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304905 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304906 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304907 goto exit;
4908 }
4909
Haynes Mathew George16081042017-05-31 17:16:49 -07004910 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4911 ret = -EINVAL;
4912 goto exit;
4913 }
4914
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304915 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4916 !out->is_iec61937_info_available) {
4917
4918 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4919 out->is_iec61937_info_available = true;
4920 } else if (audio_extn_passthru_is_enabled()) {
4921 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304922 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304923
4924 if((out->format == AUDIO_FORMAT_DTS) ||
4925 (out->format == AUDIO_FORMAT_DTS_HD)) {
4926 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4927 buffer, bytes);
4928 if (ret) {
4929 if (ret != -ENOSYS) {
4930 out->is_iec61937_info_available = false;
4931 ALOGD("iec61937 transmission info not yet updated retry");
4932 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304933 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304934 /* if stream has started and after that there is
4935 * stream config change (iec transmission config)
4936 * then trigger select_device to update backend configuration.
4937 */
4938 out->stream_config_changed = true;
4939 pthread_mutex_lock(&adev->lock);
4940 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304941 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4942 ret = -EINVAL;
4943 goto exit;
4944 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304945 pthread_mutex_unlock(&adev->lock);
4946 out->stream_config_changed = false;
4947 out->is_iec61937_info_available = true;
4948 }
4949 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304950
Garmond Leung317cbf12017-09-13 16:20:50 -07004951 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304952 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4953 (out->is_iec61937_info_available == true)) {
4954 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4955 ret = -EINVAL;
4956 goto exit;
4957 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304958 }
4959 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304960
4961 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004962 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004963 if (!(out->devices &
4964 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304965 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304966 ret = -EIO;
4967 goto exit;
4968 }
4969 }
4970 }
4971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004973 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004974 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004975 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4976 ret = voice_extn_compress_voip_start_output_stream(out);
4977 else
4978 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004979 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004980 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004982 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 goto exit;
4984 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304985 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004986 if (last_known_cal_step != -1) {
4987 ALOGD("%s: retry previous failed cal level set", __func__);
4988 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304989 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004990 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304991
4992 if ((out->is_iec61937_info_available == true) &&
4993 (audio_extn_passthru_is_passthrough_stream(out))&&
4994 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4995 ret = -EINVAL;
4996 goto exit;
4997 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05304998 if (out->set_dual_mono)
4999 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001
Ashish Jain81eb2a82015-05-13 10:52:34 +05305002 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005003 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305004 adev->is_channel_status_set = true;
5005 }
5006
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005007 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005008 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005009 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005010 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005011 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5012 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305013 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5014 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005015 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305016 out->send_next_track_params = false;
5017 out->is_compr_metadata_avail = false;
5018 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005019 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305020 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305021 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005022
Ashish Jain83a6cc22016-06-28 14:34:17 +05305023 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305024 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305025 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305026 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005027 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305028 return -EINVAL;
5029 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305030 audio_format_t dst_format = out->hal_op_format;
5031 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305032
Dieter Luecking5d57def2018-09-07 14:23:37 +02005033 /* prevent division-by-zero */
5034 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5035 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5036 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5037 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305038 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005039 ATRACE_END();
5040 return -EINVAL;
5041 }
5042
Ashish Jainf1eaa582016-05-23 20:54:24 +05305043 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5044 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5045
Ashish Jain83a6cc22016-06-28 14:34:17 +05305046 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305047 dst_format,
5048 buffer,
5049 src_format,
5050 frames);
5051
Ashish Jain83a6cc22016-06-28 14:34:17 +05305052 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305053 bytes_to_write);
5054
5055 /*Convert written bytes in audio flinger format*/
5056 if (ret > 0)
5057 ret = ((ret * format_to_bitwidth_table[out->format]) /
5058 format_to_bitwidth_table[dst_format]);
5059 }
5060 } else
5061 ret = compress_write(out->compr, buffer, bytes);
5062
Zhou Songc9672822017-08-16 16:01:39 +08005063 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5064 update_frames_written(out, bytes);
5065
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305066 if (ret < 0)
5067 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005068 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305069 /*msg to cb thread only if non blocking write is enabled*/
5070 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305071 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005072 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305073 } else if (-ENETRESET == ret) {
5074 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305075 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305076 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305077 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005078 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305079 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005080 }
Ashish Jain5106d362016-05-11 19:23:33 +05305081
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305082 /* Call compr start only when non-zero bytes of data is there to be rendered */
5083 if (!out->playback_started && ret > 0) {
5084 int status = compress_start(out->compr);
5085 if (status < 0) {
5086 ret = status;
5087 ALOGE("%s: compr start failed with err %d", __func__, errno);
5088 goto exit;
5089 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005090 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005091 out->playback_started = 1;
5092 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005093
5094 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5095 popcount(out->channel_mask),
5096 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005097 }
5098 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005099 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005100 return ret;
5101 } else {
5102 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005103 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005104 if (out->muted)
5105 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005106 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5107 __func__, frames, frame_size, bytes_to_write);
5108
Aalique Grahame22e49102018-12-18 14:23:57 -08005109 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005110 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP
5111 && !voice_extn_is_compress_voip_supported()) ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005112 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005113 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5114 int16_t *src = (int16_t *)buffer;
5115 int16_t *dst = (int16_t *)buffer;
5116
5117 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5118 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005119 "out_write called for %s use case with wrong properties",
5120 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005121
5122 /*
5123 * FIXME: this can be removed once audio flinger mixer supports
5124 * mono output
5125 */
5126
5127 /*
5128 * Code below goes over each frame in the buffer and adds both
5129 * L and R samples and then divides by 2 to convert to mono
5130 */
5131 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5132 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5133 }
5134 bytes_to_write /= 2;
5135 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005136
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305137 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005138
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005139 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005140
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005141 if (out->config.rate)
5142 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5143 out->config.rate;
5144
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005145 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005146 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5147
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005148 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005149 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005150 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305151 out->convert_buffer != NULL) {
5152
5153 memcpy_by_audio_format(out->convert_buffer,
5154 out->hal_op_format,
5155 buffer,
5156 out->hal_ip_format,
5157 out->config.period_size * out->config.channels);
5158
5159 ret = pcm_write(out->pcm, out->convert_buffer,
5160 (out->config.period_size *
5161 out->config.channels *
5162 format_to_bitwidth_table[out->hal_op_format]));
5163 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305164 /*
5165 * To avoid underrun in DSP when the application is not pumping
5166 * data at required rate, check for the no. of bytes and ignore
5167 * pcm_write if it is less than actual buffer size.
5168 * It is a work around to a change in compress VOIP driver.
5169 */
5170 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5171 bytes < (out->config.period_size * out->config.channels *
5172 audio_bytes_per_sample(out->format))) {
5173 size_t voip_buf_size =
5174 out->config.period_size * out->config.channels *
5175 audio_bytes_per_sample(out->format);
5176 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5177 __func__, bytes, voip_buf_size);
5178 usleep(((uint64_t)voip_buf_size - bytes) *
5179 1000000 / audio_stream_out_frame_size(stream) /
5180 out_get_sample_rate(&out->stream.common));
5181 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005182 } else {
5183 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5184 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5185 else
5186 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5187 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305188 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005189
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005190 release_out_focus(out);
5191
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305192 if (ret < 0)
5193 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005194 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305195 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005196 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197 }
5198
5199exit:
Zhou Songc9672822017-08-16 16:01:39 +08005200 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305201 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305202 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305203 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005204 pthread_mutex_unlock(&out->lock);
5205
5206 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005207 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005208 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305209 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305210 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305211 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305212 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305213 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305214 out->standby = true;
5215 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305216 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005217 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5218 /* prevent division-by-zero */
5219 uint32_t stream_size = audio_stream_out_frame_size(stream);
5220 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005221
Dieter Luecking5d57def2018-09-07 14:23:37 +02005222 if ((stream_size == 0) || (srate == 0)) {
5223 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5224 ATRACE_END();
5225 return -EINVAL;
5226 }
5227 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5228 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005229 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305230 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005231 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005232 return ret;
5233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005235 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236 return bytes;
5237}
5238
5239static int out_get_render_position(const struct audio_stream_out *stream,
5240 uint32_t *dsp_frames)
5241{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005242 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005243
5244 if (dsp_frames == NULL)
5245 return -EINVAL;
5246
5247 *dsp_frames = 0;
5248 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005249 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305250
5251 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5252 * this operation and adev_close_output_stream(where out gets reset).
5253 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305254 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005255 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305256 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005257 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305258 return 0;
5259 }
5260
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005261 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305262 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305263 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005264 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305265 if (ret < 0)
5266 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005267 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305268 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005269 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305270 if (-ENETRESET == ret) {
5271 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305272 out->card_status = CARD_STATUS_OFFLINE;
5273 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305274 } else if(ret < 0) {
5275 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305276 ret = -EINVAL;
5277 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305278 /*
5279 * Handle corner case where compress session is closed during SSR
5280 * and timestamp is queried
5281 */
5282 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305283 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305284 } else if (out->prev_card_status_offline) {
5285 ALOGE("ERROR: previously sound card was offline,return error");
5286 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305287 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305288 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005289 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305290 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305291 pthread_mutex_unlock(&out->lock);
5292 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005293 } else if (audio_is_linear_pcm(out->format)) {
5294 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005295 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005296 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005297 } else
5298 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299}
5300
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005301static int out_add_audio_effect(const struct audio_stream *stream __unused,
5302 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005303{
5304 return 0;
5305}
5306
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005307static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5308 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005309{
5310 return 0;
5311}
5312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005313static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5314 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305316 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005317}
5318
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005319static int out_get_presentation_position(const struct audio_stream_out *stream,
5320 uint64_t *frames, struct timespec *timestamp)
5321{
5322 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305323 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005324 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005325
Ashish Jain5106d362016-05-11 19:23:33 +05305326 /* below piece of code is not guarded against any lock because audioFliner serializes
5327 * this operation and adev_close_output_stream( where out gets reset).
5328 */
5329 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305330 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005331 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305332 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5333 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5334 return 0;
5335 }
5336
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005337 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005338
Ashish Jain5106d362016-05-11 19:23:33 +05305339 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5340 ret = compress_get_tstamp(out->compr, &dsp_frames,
5341 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005342 // Adjustment accounts for A2dp encoder latency with offload usecases
5343 // Note: Encoder latency is returned in ms.
5344 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5345 unsigned long offset =
5346 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5347 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5348 }
Ashish Jain5106d362016-05-11 19:23:33 +05305349 ALOGVV("%s rendered frames %ld sample_rate %d",
5350 __func__, dsp_frames, out->sample_rate);
5351 *frames = dsp_frames;
5352 if (ret < 0)
5353 ret = -errno;
5354 if (-ENETRESET == ret) {
5355 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305356 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305357 ret = -EINVAL;
5358 } else
5359 ret = 0;
5360 /* this is the best we can do */
5361 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005362 } else {
5363 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005364 unsigned int avail;
5365 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5366 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5367 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5368 // This adjustment accounts for buffering after app processor.
5369 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005370 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005371 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005372
Weiyin Jiangd4633762018-03-16 12:05:03 +08005373 // Adjustment accounts for A2dp encoder latency with non offload usecases
5374 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5375 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5376 signed_frames -=
5377 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5378 }
5379
5380 // It would be unusual for this value to be negative, but check just in case ...
5381 if (signed_frames >= 0) {
5382 *frames = signed_frames;
5383 ret = 0;
5384 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005385 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305386 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305387 *frames = out->written;
5388 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305389 if (is_offload_usecase(out->usecase))
5390 ret = -EINVAL;
5391 else
5392 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005393 }
5394 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005395 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005396 return ret;
5397}
5398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005399static int out_set_callback(struct audio_stream_out *stream,
5400 stream_callback_t callback, void *cookie)
5401{
5402 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005403 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005404
5405 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005406 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005407 out->client_callback = callback;
5408 out->client_cookie = cookie;
5409 if (out->adsp_hdlr_stream_handle) {
5410 ret = audio_extn_adsp_hdlr_stream_set_callback(
5411 out->adsp_hdlr_stream_handle,
5412 callback,
5413 cookie);
5414 if (ret)
5415 ALOGW("%s:adsp hdlr callback registration failed %d",
5416 __func__, ret);
5417 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005418 pthread_mutex_unlock(&out->lock);
5419 return 0;
5420}
5421
5422static int out_pause(struct audio_stream_out* stream)
5423{
5424 struct stream_out *out = (struct stream_out *)stream;
5425 int status = -ENOSYS;
5426 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005427 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005428 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005429 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005430 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305431 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305432 status = compress_pause(out->compr);
5433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005434 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005435
Mingming Yin21854652016-04-13 11:54:02 -07005436 if (audio_extn_passthru_is_active()) {
5437 ALOGV("offload use case, pause passthru");
5438 audio_extn_passthru_on_pause(out);
5439 }
5440
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305441 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005442 audio_extn_dts_notify_playback_state(out->usecase, 0,
5443 out->sample_rate, popcount(out->channel_mask),
5444 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005445 }
5446 pthread_mutex_unlock(&out->lock);
5447 }
5448 return status;
5449}
5450
5451static int out_resume(struct audio_stream_out* stream)
5452{
5453 struct stream_out *out = (struct stream_out *)stream;
5454 int status = -ENOSYS;
5455 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005456 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005457 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005458 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005459 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005460 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305461 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305462 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005463 }
5464 if (!status) {
5465 out->offload_state = OFFLOAD_STATE_PLAYING;
5466 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305467 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005468 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5469 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005470 }
5471 pthread_mutex_unlock(&out->lock);
5472 }
5473 return status;
5474}
5475
5476static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5477{
5478 struct stream_out *out = (struct stream_out *)stream;
5479 int status = -ENOSYS;
5480 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005481 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005483 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5484 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5485 else
5486 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5487 pthread_mutex_unlock(&out->lock);
5488 }
5489 return status;
5490}
5491
5492static int out_flush(struct audio_stream_out* stream)
5493{
5494 struct stream_out *out = (struct stream_out *)stream;
5495 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005496 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005497 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005498 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005499 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5500 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005501 } else {
5502 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5503 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005504 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005505 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005506 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005507 return 0;
5508 }
5509 return -ENOSYS;
5510}
5511
Haynes Mathew George16081042017-05-31 17:16:49 -07005512static int out_stop(const struct audio_stream_out* stream)
5513{
5514 struct stream_out *out = (struct stream_out *)stream;
5515 struct audio_device *adev = out->dev;
5516 int ret = -ENOSYS;
5517
5518 ALOGV("%s", __func__);
5519 pthread_mutex_lock(&adev->lock);
5520 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5521 out->playback_started && out->pcm != NULL) {
5522 pcm_stop(out->pcm);
5523 ret = stop_output_stream(out);
5524 out->playback_started = false;
5525 }
5526 pthread_mutex_unlock(&adev->lock);
5527 return ret;
5528}
5529
5530static int out_start(const struct audio_stream_out* stream)
5531{
5532 struct stream_out *out = (struct stream_out *)stream;
5533 struct audio_device *adev = out->dev;
5534 int ret = -ENOSYS;
5535
5536 ALOGV("%s", __func__);
5537 pthread_mutex_lock(&adev->lock);
5538 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5539 !out->playback_started && out->pcm != NULL) {
5540 ret = start_output_stream(out);
5541 if (ret == 0) {
5542 out->playback_started = true;
5543 }
5544 }
5545 pthread_mutex_unlock(&adev->lock);
5546 return ret;
5547}
5548
5549/*
5550 * Modify config->period_count based on min_size_frames
5551 */
5552static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5553{
5554 int periodCountRequested = (min_size_frames + config->period_size - 1)
5555 / config->period_size;
5556 int periodCount = MMAP_PERIOD_COUNT_MIN;
5557
5558 ALOGV("%s original config.period_size = %d config.period_count = %d",
5559 __func__, config->period_size, config->period_count);
5560
5561 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5562 periodCount *= 2;
5563 }
5564 config->period_count = periodCount;
5565
5566 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5567}
5568
5569static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5570 int32_t min_size_frames,
5571 struct audio_mmap_buffer_info *info)
5572{
5573 struct stream_out *out = (struct stream_out *)stream;
5574 struct audio_device *adev = out->dev;
5575 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005576 unsigned int offset1 = 0;
5577 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005578 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005579 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005580
5581 ALOGV("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305582 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005583 pthread_mutex_lock(&adev->lock);
5584
Sharad Sanglec6f32552018-05-04 16:15:38 +05305585 if (CARD_STATUS_OFFLINE == out->card_status ||
5586 CARD_STATUS_OFFLINE == adev->card_status) {
5587 ALOGW("out->card_status or adev->card_status offline, try again");
5588 ret = -EIO;
5589 goto exit;
5590 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005591 if (info == NULL || min_size_frames == 0) {
5592 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5593 ret = -EINVAL;
5594 goto exit;
5595 }
5596 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5597 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5598 ret = -ENOSYS;
5599 goto exit;
5600 }
5601 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5602 if (out->pcm_device_id < 0) {
5603 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5604 __func__, out->pcm_device_id, out->usecase);
5605 ret = -EINVAL;
5606 goto exit;
5607 }
5608
5609 adjust_mmap_period_count(&out->config, min_size_frames);
5610
5611 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5612 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5613 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5614 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305615 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305616 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5617 out->card_status = CARD_STATUS_OFFLINE;
5618 adev->card_status = CARD_STATUS_OFFLINE;
5619 ret = -EIO;
5620 goto exit;
5621 }
5622
Haynes Mathew George16081042017-05-31 17:16:49 -07005623 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5624 step = "open";
5625 ret = -ENODEV;
5626 goto exit;
5627 }
5628 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5629 if (ret < 0) {
5630 step = "begin";
5631 goto exit;
5632 }
5633 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5634 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005635 ret = platform_get_mmap_data_fd(adev->platform,
5636 out->pcm_device_id, 0 /*playback*/,
5637 &info->shared_memory_fd,
5638 &mmap_size);
5639 if (ret < 0) {
5640 step = "get_mmap_fd";
5641 goto exit;
5642 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005643 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005644 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005645
5646 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5647 if (ret < 0) {
5648 step = "commit";
5649 goto exit;
5650 }
5651
5652 out->standby = false;
5653 ret = 0;
5654
5655 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5656 __func__, info->shared_memory_address, info->buffer_size_frames);
5657
5658exit:
5659 if (ret != 0) {
5660 if (out->pcm == NULL) {
5661 ALOGE("%s: %s - %d", __func__, step, ret);
5662 } else {
5663 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5664 pcm_close(out->pcm);
5665 out->pcm = NULL;
5666 }
5667 }
5668 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305669 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005670 return ret;
5671}
5672
5673static int out_get_mmap_position(const struct audio_stream_out *stream,
5674 struct audio_mmap_position *position)
5675{
5676 struct stream_out *out = (struct stream_out *)stream;
5677 ALOGVV("%s", __func__);
5678 if (position == NULL) {
5679 return -EINVAL;
5680 }
5681 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005682 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005683 return -ENOSYS;
5684 }
5685 if (out->pcm == NULL) {
5686 return -ENOSYS;
5687 }
5688
5689 struct timespec ts = { 0, 0 };
5690 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5691 if (ret < 0) {
5692 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5693 return ret;
5694 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005695 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005696 return 0;
5697}
5698
5699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700/** audio_stream_in implementation **/
5701static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5702{
5703 struct stream_in *in = (struct stream_in *)stream;
5704
5705 return in->config.rate;
5706}
5707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005708static int in_set_sample_rate(struct audio_stream *stream __unused,
5709 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005710{
5711 return -ENOSYS;
5712}
5713
5714static size_t in_get_buffer_size(const struct audio_stream *stream)
5715{
5716 struct stream_in *in = (struct stream_in *)stream;
5717
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005718 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5719 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005720 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5721 return VOIP_IO_BUF_SIZE(in->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Mingming Yine62d7842013-10-25 16:26:03 -07005722 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5723 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305724 else if(audio_extn_cin_attached_usecase(in->usecase))
5725 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005726
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005727 return in->config.period_size * in->af_period_multiplier *
5728 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005729}
5730
5731static uint32_t in_get_channels(const struct audio_stream *stream)
5732{
5733 struct stream_in *in = (struct stream_in *)stream;
5734
5735 return in->channel_mask;
5736}
5737
5738static audio_format_t in_get_format(const struct audio_stream *stream)
5739{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005740 struct stream_in *in = (struct stream_in *)stream;
5741
5742 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743}
5744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005745static int in_set_format(struct audio_stream *stream __unused,
5746 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005747{
5748 return -ENOSYS;
5749}
5750
5751static int in_standby(struct audio_stream *stream)
5752{
5753 struct stream_in *in = (struct stream_in *)stream;
5754 struct audio_device *adev = in->dev;
5755 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305756 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5757 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005758 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305759
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005760 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005761 if (!in->standby && in->is_st_session) {
5762 ALOGD("%s: sound trigger pcm stop lab", __func__);
5763 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005764 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005765 in->standby = 1;
5766 }
5767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005768 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005769 if (adev->adm_deregister_stream)
5770 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5771
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005773 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005774 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005775 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005776 voice_extn_compress_voip_close_input_stream(stream);
5777 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005778 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5779 do_stop = in->capture_started;
5780 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005781 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305782 if (audio_extn_cin_attached_usecase(in->usecase))
5783 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005784 }
5785
5786 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005787 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005788 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005789 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005790 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005791 in->pcm = NULL;
5792 }
Aalique Grahame22e49102018-12-18 14:23:57 -08005793 adev->enable_voicerx = false;
5794 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005795 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005796 }
Quinn Malef6050362019-01-30 15:55:40 -08005797
5798 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5799 adev->num_va_sessions--;
5800
Eric Laurent150dbfe2013-02-27 14:31:02 -08005801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005802 }
5803 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005804 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005805 return status;
5806}
5807
Aalique Grahame22e49102018-12-18 14:23:57 -08005808static int in_dump(const struct audio_stream *stream,
5809 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005810{
Aalique Grahame22e49102018-12-18 14:23:57 -08005811 struct stream_in *in = (struct stream_in *)stream;
5812
5813 // We try to get the lock for consistency,
5814 // but it isn't necessary for these variables.
5815 // If we're not in standby, we may be blocked on a read.
5816 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5817 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5818 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5819 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5820
5821 if (locked) {
5822 pthread_mutex_unlock(&in->lock);
5823 }
5824
5825 // dump error info
5826 (void)error_log_dump(
5827 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829 return 0;
5830}
5831
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305832static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5833{
5834 if (!stream || !parms)
5835 return;
5836
5837 struct stream_in *in = (struct stream_in *)stream;
5838 struct audio_device *adev = in->dev;
5839
5840 card_status_t status;
5841 int card;
5842 if (parse_snd_card_status(parms, &card, &status) < 0)
5843 return;
5844
5845 pthread_mutex_lock(&adev->lock);
5846 bool valid_cb = (card == adev->snd_card);
5847 pthread_mutex_unlock(&adev->lock);
5848
5849 if (!valid_cb)
5850 return;
5851
5852 lock_input_stream(in);
5853 if (in->card_status != status)
5854 in->card_status = status;
5855 pthread_mutex_unlock(&in->lock);
5856
5857 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5858 use_case_table[in->usecase],
5859 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5860
5861 // a better solution would be to report error back to AF and let
5862 // it put the stream to standby
5863 if (status == CARD_STATUS_OFFLINE)
5864 in_standby(&in->stream.common);
5865
5866 return;
5867}
5868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5870{
5871 struct stream_in *in = (struct stream_in *)stream;
5872 struct audio_device *adev = in->dev;
5873 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005874 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005875 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005876
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305877 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005878 parms = str_parms_create_str(kvpairs);
5879
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305880 if (!parms)
5881 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005882 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005883 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005884
5885 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5886 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887 val = atoi(value);
5888 /* no audio source uses val == 0 */
5889 if ((in->source != val) && (val != 0)) {
5890 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005891 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5892 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5893 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005894 (in->config.rate == 8000 || in->config.rate == 16000 ||
5895 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005896 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005897 err = voice_extn_compress_voip_open_input_stream(in);
5898 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005899 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005900 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005901 }
5902 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005903 }
5904 }
5905
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005906 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5907 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005908 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005909 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5910
5911 // Workaround: If routing to an non existing usb device, fail gracefully
5912 // The routing request will otherwise block during 10 second
5913 int card;
5914 if (audio_is_usb_in_device(val) &&
5915 (card = get_alive_usb_card(parms)) >= 0) {
5916
5917 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5918 ret = -ENOSYS;
5919 } else {
5920
5921 in->device = val;
5922 /* If recording is in progress, change the tx device to new device */
5923 if (!in->standby && !in->is_st_session) {
5924 ALOGV("update input routing change");
5925 // inform adm before actual routing to prevent glitches.
5926 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005927 adev->adm_on_routing_change(adev->adm_data,
5928 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005929 ret = select_devices(adev, in->usecase);
5930 }
5931 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933 }
5934 }
5935
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305936 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5937 if (err >= 0) {
5938 strlcpy(in->profile, value, sizeof(in->profile));
5939 ALOGV("updating stream profile with value '%s'", in->profile);
5940 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5941 &adev->streams_input_cfg_list,
5942 in->device, in->flags, in->format,
5943 in->sample_rate, in->bit_width,
5944 in->profile, &in->app_type_cfg);
5945 }
5946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005947 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005948 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005949
5950 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305951error:
Eric Laurent994a6932013-07-17 11:51:42 -07005952 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005953 return ret;
5954}
5955
5956static char* in_get_parameters(const struct audio_stream *stream,
5957 const char *keys)
5958{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005959 struct stream_in *in = (struct stream_in *)stream;
5960 struct str_parms *query = str_parms_create_str(keys);
5961 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005962 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005963
5964 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005965 if (reply) {
5966 str_parms_destroy(reply);
5967 }
5968 if (query) {
5969 str_parms_destroy(query);
5970 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005971 ALOGE("in_get_parameters: failed to create query or reply");
5972 return NULL;
5973 }
5974
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005975 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005976
5977 voice_extn_in_get_parameters(in, query, reply);
5978
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005979 stream_get_parameter_channels(query, reply,
5980 &in->supported_channel_masks[0]);
5981 stream_get_parameter_formats(query, reply,
5982 &in->supported_formats[0]);
5983 stream_get_parameter_rates(query, reply,
5984 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005985 str = str_parms_to_str(reply);
5986 str_parms_destroy(query);
5987 str_parms_destroy(reply);
5988
5989 ALOGV("%s: exit: returns - %s", __func__, str);
5990 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005991}
5992
Aalique Grahame22e49102018-12-18 14:23:57 -08005993static int in_set_gain(struct audio_stream_in *stream,
5994 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005995{
Aalique Grahame22e49102018-12-18 14:23:57 -08005996 struct stream_in *in = (struct stream_in *)stream;
5997 char mixer_ctl_name[128];
5998 struct mixer_ctl *ctl;
5999 int ctl_value;
6000
6001 ALOGV("%s: gain %f", __func__, gain);
6002
6003 if (stream == NULL)
6004 return -EINVAL;
6005
6006 /* in_set_gain() only used to silence MMAP capture for now */
6007 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6008 return -ENOSYS;
6009
6010 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6011
6012 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6013 if (!ctl) {
6014 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6015 __func__, mixer_ctl_name);
6016 return -ENOSYS;
6017 }
6018
6019 if (gain < RECORD_GAIN_MIN)
6020 gain = RECORD_GAIN_MIN;
6021 else if (gain > RECORD_GAIN_MAX)
6022 gain = RECORD_GAIN_MAX;
6023 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6024
6025 mixer_ctl_set_value(ctl, 0, ctl_value);
6026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006027 return 0;
6028}
6029
6030static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6031 size_t bytes)
6032{
6033 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306034
6035 if (in == NULL) {
6036 ALOGE("%s: stream_in ptr is NULL", __func__);
6037 return -EINVAL;
6038 }
6039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306041 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306042 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006043
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006044 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306045
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006046 if (in->is_st_session) {
6047 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6048 /* Read from sound trigger HAL */
6049 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006050 if (in->standby) {
6051 adev->num_va_sessions++;
6052 in->standby = 0;
6053 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006054 pthread_mutex_unlock(&in->lock);
6055 return bytes;
6056 }
6057
Haynes Mathew George16081042017-05-31 17:16:49 -07006058 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6059 ret = -ENOSYS;
6060 goto exit;
6061 }
6062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006063 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006064 pthread_mutex_lock(&adev->lock);
6065 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6066 ret = voice_extn_compress_voip_start_input_stream(in);
6067 else
6068 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006069 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6070 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006071 pthread_mutex_unlock(&adev->lock);
6072 if (ret != 0) {
6073 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006074 }
6075 in->standby = 0;
6076 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006077
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006078 // what's the duration requested by the client?
6079 long ns = 0;
6080
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306081 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006082 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6083 in->config.rate;
6084
6085 request_in_focus(in, ns);
6086 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006087
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306088 if (audio_extn_cin_attached_usecase(in->usecase)) {
6089 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6090 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306091 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006092 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306093 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006094 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006095 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006096 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006097 } else if (audio_extn_ffv_get_stream() == in) {
6098 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306099 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006100 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306101 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6102 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6103 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6104 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306105 ret = -EINVAL;
6106 goto exit;
6107 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306108 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306109 ret = -errno;
6110 }
6111 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306112 /* bytes read is always set to bytes for non compress usecases */
6113 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006114 }
6115
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006116 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006118 /*
Quinn Malef6050362019-01-30 15:55:40 -08006119 * Instead of writing zeroes here, we could trust the hardware to always
6120 * provide zeroes when muted. This is also muted with voice recognition
6121 * usecases so that other clients do not have access to voice recognition
6122 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006123 */
Quinn Malef6050362019-01-30 15:55:40 -08006124 if ((ret == 0 && voice_get_mic_mute(adev) &&
6125 !voice_is_in_call_rec_stream(in) &&
6126 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6127 (adev->num_va_sessions &&
6128 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6129 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6130 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006131 memset(buffer, 0, bytes);
6132
6133exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006134 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306135 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006136 pthread_mutex_unlock(&in->lock);
6137
6138 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306139 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306140 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306141 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306142 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306143 in->standby = true;
6144 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306145 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6146 bytes_read = bytes;
6147 memset(buffer, 0, bytes);
6148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006149 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006150 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306151 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306152 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306154 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155}
6156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006157static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006158{
6159 return 0;
6160}
6161
Aalique Grahame22e49102018-12-18 14:23:57 -08006162static int in_get_capture_position(const struct audio_stream_in *stream,
6163 int64_t *frames, int64_t *time)
6164{
6165 if (stream == NULL || frames == NULL || time == NULL) {
6166 return -EINVAL;
6167 }
6168 struct stream_in *in = (struct stream_in *)stream;
6169 int ret = -ENOSYS;
6170
6171 lock_input_stream(in);
6172 // note: ST sessions do not close the alsa pcm driver synchronously
6173 // on standby. Therefore, we may return an error even though the
6174 // pcm stream is still opened.
6175 if (in->standby) {
6176 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6177 "%s stream in standby but pcm not NULL for non ST session", __func__);
6178 goto exit;
6179 }
6180 if (in->pcm) {
6181 struct timespec timestamp;
6182 unsigned int avail;
6183 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6184 *frames = in->frames_read + avail;
6185 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6186 ret = 0;
6187 }
6188 }
6189exit:
6190 pthread_mutex_unlock(&in->lock);
6191 return ret;
6192}
6193
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006194static int add_remove_audio_effect(const struct audio_stream *stream,
6195 effect_handle_t effect,
6196 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006197{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006198 struct stream_in *in = (struct stream_in *)stream;
6199 int status = 0;
6200 effect_descriptor_t desc;
6201
6202 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006203 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6204
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006205 if (status != 0)
6206 return status;
6207
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006208 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006209 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006210 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006211 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006212 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006213 in->enable_aec != enable &&
6214 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6215 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006216 if (!enable)
6217 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6218 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6219 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6220 in->dev->enable_voicerx = enable;
6221 struct audio_usecase *usecase;
6222 struct listnode *node;
6223 list_for_each(node, &in->dev->usecase_list) {
6224 usecase = node_to_item(node, struct audio_usecase, list);
6225 if (usecase->type == PCM_PLAYBACK)
6226 select_devices(in->dev, usecase->id);
6227 }
6228 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006229 if (!in->standby) {
6230 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6231 select_devices(in->dev, in->usecase);
6232 }
6233
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006234 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006235 if (in->enable_ns != enable &&
6236 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6237 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006238 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006239 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6240 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006241 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6242 select_devices(in->dev, in->usecase);
6243 } else
6244 select_devices(in->dev, in->usecase);
6245 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006246 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006247 pthread_mutex_unlock(&in->dev->lock);
6248 pthread_mutex_unlock(&in->lock);
6249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006250 return 0;
6251}
6252
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006253static int in_add_audio_effect(const struct audio_stream *stream,
6254 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255{
Eric Laurent994a6932013-07-17 11:51:42 -07006256 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006257 return add_remove_audio_effect(stream, effect, true);
6258}
6259
6260static int in_remove_audio_effect(const struct audio_stream *stream,
6261 effect_handle_t effect)
6262{
Eric Laurent994a6932013-07-17 11:51:42 -07006263 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006264 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006265}
6266
Haynes Mathew George16081042017-05-31 17:16:49 -07006267static int in_stop(const struct audio_stream_in* stream)
6268{
6269 struct stream_in *in = (struct stream_in *)stream;
6270 struct audio_device *adev = in->dev;
6271
6272 int ret = -ENOSYS;
6273 ALOGV("%s", __func__);
6274 pthread_mutex_lock(&adev->lock);
6275 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6276 in->capture_started && in->pcm != NULL) {
6277 pcm_stop(in->pcm);
6278 ret = stop_input_stream(in);
6279 in->capture_started = false;
6280 }
6281 pthread_mutex_unlock(&adev->lock);
6282 return ret;
6283}
6284
6285static int in_start(const struct audio_stream_in* stream)
6286{
6287 struct stream_in *in = (struct stream_in *)stream;
6288 struct audio_device *adev = in->dev;
6289 int ret = -ENOSYS;
6290
6291 ALOGV("%s in %p", __func__, in);
6292 pthread_mutex_lock(&adev->lock);
6293 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6294 !in->capture_started && in->pcm != NULL) {
6295 if (!in->capture_started) {
6296 ret = start_input_stream(in);
6297 if (ret == 0) {
6298 in->capture_started = true;
6299 }
6300 }
6301 }
6302 pthread_mutex_unlock(&adev->lock);
6303 return ret;
6304}
6305
6306static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6307 int32_t min_size_frames,
6308 struct audio_mmap_buffer_info *info)
6309{
6310 struct stream_in *in = (struct stream_in *)stream;
6311 struct audio_device *adev = in->dev;
6312 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006313 unsigned int offset1 = 0;
6314 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006315 const char *step = "";
6316
6317 pthread_mutex_lock(&adev->lock);
6318 ALOGV("%s in %p", __func__, in);
6319
Sharad Sanglec6f32552018-05-04 16:15:38 +05306320 if (CARD_STATUS_OFFLINE == in->card_status||
6321 CARD_STATUS_OFFLINE == adev->card_status) {
6322 ALOGW("in->card_status or adev->card_status offline, try again");
6323 ret = -EIO;
6324 goto exit;
6325 }
6326
Haynes Mathew George16081042017-05-31 17:16:49 -07006327 if (info == NULL || min_size_frames == 0) {
6328 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6329 ret = -EINVAL;
6330 goto exit;
6331 }
6332 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6333 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6334 ALOGV("%s in %p", __func__, in);
6335 ret = -ENOSYS;
6336 goto exit;
6337 }
6338 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6339 if (in->pcm_device_id < 0) {
6340 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6341 __func__, in->pcm_device_id, in->usecase);
6342 ret = -EINVAL;
6343 goto exit;
6344 }
6345
6346 adjust_mmap_period_count(&in->config, min_size_frames);
6347
6348 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6349 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6350 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6351 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306352 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306353 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6354 in->card_status = CARD_STATUS_OFFLINE;
6355 adev->card_status = CARD_STATUS_OFFLINE;
6356 ret = -EIO;
6357 goto exit;
6358 }
6359
Haynes Mathew George16081042017-05-31 17:16:49 -07006360 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6361 step = "open";
6362 ret = -ENODEV;
6363 goto exit;
6364 }
6365
6366 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6367 if (ret < 0) {
6368 step = "begin";
6369 goto exit;
6370 }
6371 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6372 info->burst_size_frames = in->config.period_size;
6373 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6374
6375 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
6376 info->buffer_size_frames));
6377
6378 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6379 if (ret < 0) {
6380 step = "commit";
6381 goto exit;
6382 }
6383
6384 in->standby = false;
6385 ret = 0;
6386
6387 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6388 __func__, info->shared_memory_address, info->buffer_size_frames);
6389
6390exit:
6391 if (ret != 0) {
6392 if (in->pcm == NULL) {
6393 ALOGE("%s: %s - %d", __func__, step, ret);
6394 } else {
6395 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6396 pcm_close(in->pcm);
6397 in->pcm = NULL;
6398 }
6399 }
6400 pthread_mutex_unlock(&adev->lock);
6401 return ret;
6402}
6403
6404static int in_get_mmap_position(const struct audio_stream_in *stream,
6405 struct audio_mmap_position *position)
6406{
6407 struct stream_in *in = (struct stream_in *)stream;
6408 ALOGVV("%s", __func__);
6409 if (position == NULL) {
6410 return -EINVAL;
6411 }
6412 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6413 return -ENOSYS;
6414 }
6415 if (in->pcm == NULL) {
6416 return -ENOSYS;
6417 }
6418 struct timespec ts = { 0, 0 };
6419 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6420 if (ret < 0) {
6421 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6422 return ret;
6423 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306424 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006425 return 0;
6426}
6427
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306428static int in_get_active_microphones(const struct audio_stream_in *stream,
6429 struct audio_microphone_characteristic_t *mic_array,
6430 size_t *mic_count) {
6431 struct stream_in *in = (struct stream_in *)stream;
6432 struct audio_device *adev = in->dev;
6433 ALOGVV("%s", __func__);
6434
6435 lock_input_stream(in);
6436 pthread_mutex_lock(&adev->lock);
6437 int ret = platform_get_active_microphones(adev->platform,
6438 audio_channel_count_from_in_mask(in->channel_mask),
6439 in->usecase, mic_array, mic_count);
6440 pthread_mutex_unlock(&adev->lock);
6441 pthread_mutex_unlock(&in->lock);
6442
6443 return ret;
6444}
6445
6446static int adev_get_microphones(const struct audio_hw_device *dev,
6447 struct audio_microphone_characteristic_t *mic_array,
6448 size_t *mic_count) {
6449 struct audio_device *adev = (struct audio_device *)dev;
6450 ALOGVV("%s", __func__);
6451
6452 pthread_mutex_lock(&adev->lock);
6453 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6454 pthread_mutex_unlock(&adev->lock);
6455
6456 return ret;
6457}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306458int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006459 audio_io_handle_t handle,
6460 audio_devices_t devices,
6461 audio_output_flags_t flags,
6462 struct audio_config *config,
6463 struct audio_stream_out **stream_out,
6464 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006465{
6466 struct audio_device *adev = (struct audio_device *)dev;
6467 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306468 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006469 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006470 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306471 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006472 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6473 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6474 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6475 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006476 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006477 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006478 bool force_haptic_path =
6479 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006480
kunleizdff872d2018-08-20 14:40:33 +08006481 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006482 is_usb_dev = false;
6483 devices = AUDIO_DEVICE_OUT_SPEAKER;
6484 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6485 __func__, devices);
6486 }
6487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006488 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006490 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6491
Mingming Yin3a941d42016-02-17 18:08:05 -08006492 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6493 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306494 devices, flags, &out->stream);
6495
6496
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006497 if (!out) {
6498 return -ENOMEM;
6499 }
6500
Haynes Mathew George204045b2015-02-25 20:32:03 -08006501 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006502 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306503 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006504 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006505 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006507 if (devices == AUDIO_DEVICE_NONE)
6508 devices = AUDIO_DEVICE_OUT_SPEAKER;
6509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006510 out->flags = flags;
6511 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006512 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006513 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006514 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306515 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306516 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6517 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6518 else
6519 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006520 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006521 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006522 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306523 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306524 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306525 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006526 out->hal_output_suspend_supported = 0;
6527 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306528 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306529 out->prev_card_status_offline = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306531 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306532 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006533 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6534
Aalique Grahame22e49102018-12-18 14:23:57 -08006535 if (direct_dev &&
6536 (audio_is_linear_pcm(out->format) ||
6537 config->format == AUDIO_FORMAT_DEFAULT) &&
6538 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6539 audio_format_t req_format = config->format;
6540 audio_channel_mask_t req_channel_mask = config->channel_mask;
6541 uint32_t req_sample_rate = config->sample_rate;
6542
6543 pthread_mutex_lock(&adev->lock);
6544 if (is_hdmi) {
6545 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6546 ret = read_hdmi_sink_caps(out);
6547 if (config->sample_rate == 0)
6548 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6549 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6550 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6551 if (config->format == AUDIO_FORMAT_DEFAULT)
6552 config->format = AUDIO_FORMAT_PCM_16_BIT;
6553 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006554 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6555 &config->format,
6556 &out->supported_formats[0],
6557 MAX_SUPPORTED_FORMATS,
6558 &config->channel_mask,
6559 &out->supported_channel_masks[0],
6560 MAX_SUPPORTED_CHANNEL_MASKS,
6561 &config->sample_rate,
6562 &out->supported_sample_rates[0],
6563 MAX_SUPPORTED_SAMPLE_RATES);
6564 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006565 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006566
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006567 pthread_mutex_unlock(&adev->lock);
6568 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006569 if (ret == -ENOSYS) {
6570 /* ignore and go with default */
6571 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006572 }
6573 // For MMAP NO IRQ, allow conversions in ADSP
6574 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6575 goto error_open;
6576 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006577 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006578 goto error_open;
6579 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006580
6581 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6582 config->sample_rate = req_sample_rate;
6583 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6584 config->channel_mask = req_channel_mask;
6585 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6586 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006587 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006588
6589 out->sample_rate = config->sample_rate;
6590 out->channel_mask = config->channel_mask;
6591 out->format = config->format;
6592 if (is_hdmi) {
6593 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6594 out->config = pcm_config_hdmi_multi;
6595 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6596 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6597 out->config = pcm_config_mmap_playback;
6598 out->stream.start = out_start;
6599 out->stream.stop = out_stop;
6600 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6601 out->stream.get_mmap_position = out_get_mmap_position;
6602 } else {
6603 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6604 out->config = pcm_config_hifi;
6605 }
6606
6607 out->config.rate = out->sample_rate;
6608 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6609 if (is_hdmi) {
6610 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6611 audio_bytes_per_sample(out->format));
6612 }
6613 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006614 }
6615
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006616 /* Check for VOIP usecase */
6617 if(out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) {
6618 if (!voice_extn_is_compress_voip_supported()) {
6619 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6620 out->sample_rate == 32000 || out->sample_rate == 48000) {
6621 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6622 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6623 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6624 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006625
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006626 out->config = default_pcm_config_voip_copp;
6627 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6628 out->config.rate = out->sample_rate;
6629 }
6630 } else {
6631 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6632 voice_extn_compress_voip_is_active(out->dev)) &&
6633 (voice_extn_compress_voip_is_config_supported(config))) {
6634 ret = voice_extn_compress_voip_open_output_stream(out);
6635 if (ret != 0) {
6636 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6637 __func__, ret);
6638 goto error_open;
6639 }
6640 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006641 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006642 } else if (audio_is_linear_pcm(out->format) &&
6643 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6644 out->channel_mask = config->channel_mask;
6645 out->sample_rate = config->sample_rate;
6646 out->format = config->format;
6647 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6648 // does this change?
6649 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6650 out->config.rate = config->sample_rate;
6651 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6652 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6653 audio_bytes_per_sample(config->format));
6654 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006655 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306656 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306657 pthread_mutex_lock(&adev->lock);
6658 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6659 pthread_mutex_unlock(&adev->lock);
6660
6661 // reject offload during card offline to allow
6662 // fallback to s/w paths
6663 if (offline) {
6664 ret = -ENODEV;
6665 goto error_open;
6666 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006667
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006668 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6669 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6670 ALOGE("%s: Unsupported Offload information", __func__);
6671 ret = -EINVAL;
6672 goto error_open;
6673 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006674
Atul Khare3fa6e542017-08-09 00:56:17 +05306675 if (config->offload_info.format == 0)
6676 config->offload_info.format = config->format;
6677 if (config->offload_info.sample_rate == 0)
6678 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006679
Mingming Yin90310102013-11-13 16:57:00 -08006680 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306681 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006682 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006683 ret = -EINVAL;
6684 goto error_open;
6685 }
6686
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006687 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6688 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6689 (audio_extn_passthru_is_passthrough_stream(out)) &&
6690 !((config->sample_rate == 48000) ||
6691 (config->sample_rate == 96000) ||
6692 (config->sample_rate == 192000))) {
6693 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6694 __func__, config->sample_rate, config->offload_info.format);
6695 ret = -EINVAL;
6696 goto error_open;
6697 }
6698
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006699 out->compr_config.codec = (struct snd_codec *)
6700 calloc(1, sizeof(struct snd_codec));
6701
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006702 if (!out->compr_config.codec) {
6703 ret = -ENOMEM;
6704 goto error_open;
6705 }
6706
Dhananjay Kumarac341582017-02-23 23:42:25 +05306707 out->stream.pause = out_pause;
6708 out->stream.resume = out_resume;
6709 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306710 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306711 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006712 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306713 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006714 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306715 } else {
6716 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6717 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006718 }
vivek mehta446c3962015-09-14 10:57:35 -07006719
6720 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006721 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6722 config->format == 0 && config->sample_rate == 0 &&
6723 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006724 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006725 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6726 } else {
6727 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6728 ret = -EEXIST;
6729 goto error_open;
6730 }
vivek mehta446c3962015-09-14 10:57:35 -07006731 }
6732
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006733 if (config->offload_info.channel_mask)
6734 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006735 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006736 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006737 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006738 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306739 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006740 ret = -EINVAL;
6741 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006742 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006743
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006744 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006745 out->sample_rate = config->offload_info.sample_rate;
6746
Mingming Yin3ee55c62014-08-04 14:23:35 -07006747 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006748
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306749 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306750 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306751 audio_extn_dolby_send_ddp_endp_params(adev);
6752 audio_extn_dolby_set_dmid(adev);
6753 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006754
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006755 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006756 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006757 out->compr_config.codec->bit_rate =
6758 config->offload_info.bit_rate;
6759 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306760 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006761 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306762 /* Update bit width only for non passthrough usecases.
6763 * For passthrough usecases, the output will always be opened @16 bit
6764 */
6765 if (!audio_extn_passthru_is_passthrough_stream(out))
6766 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306767
6768 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6769 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6770 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6771
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006772 /*TODO: Do we need to change it for passthrough */
6773 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006774
Manish Dewangana6fc5442015-08-24 20:30:31 +05306775 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6776 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306777 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306778 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306779 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6780 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306781
6782 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6783 AUDIO_FORMAT_PCM) {
6784
6785 /*Based on platform support, configure appropriate alsa format for corresponding
6786 *hal input format.
6787 */
6788 out->compr_config.codec->format = hal_format_to_alsa(
6789 config->offload_info.format);
6790
Ashish Jain83a6cc22016-06-28 14:34:17 +05306791 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306792 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306793 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306794
Dhananjay Kumarac341582017-02-23 23:42:25 +05306795 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306796 *hal input format and alsa format might differ based on platform support.
6797 */
6798 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306799 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306800
6801 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6802
6803 /* Check if alsa session is configured with the same format as HAL input format,
6804 * if not then derive correct fragment size needed to accomodate the
6805 * conversion of HAL input format to alsa format.
6806 */
6807 audio_extn_utils_update_direct_pcm_fragment_size(out);
6808
6809 /*if hal input and output fragment size is different this indicates HAL input format is
6810 *not same as the alsa format
6811 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306812 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306813 /*Allocate a buffer to convert input data to the alsa configured format.
6814 *size of convert buffer is equal to the size required to hold one fragment size
6815 *worth of pcm data, this is because flinger does not write more than fragment_size
6816 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306817 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6818 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306819 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6820 ret = -ENOMEM;
6821 goto error_open;
6822 }
6823 }
6824 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6825 out->compr_config.fragment_size =
6826 audio_extn_passthru_get_buffer_size(&config->offload_info);
6827 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6828 } else {
6829 out->compr_config.fragment_size =
6830 platform_get_compress_offload_buffer_size(&config->offload_info);
6831 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6832 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006833
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306834 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6835 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6836 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006837 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306838 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006839
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306840 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6841 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6842 }
6843
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006844 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6845 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006846
Manish Dewangan69426c82017-01-30 17:35:36 +05306847 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6848 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6849 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6850 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6851 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6852 } else {
6853 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6854 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006855
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306856 memset(&out->channel_map_param, 0,
6857 sizeof(struct audio_out_channel_map_param));
6858
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006859 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306860 out->send_next_track_params = false;
6861 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006862 out->offload_state = OFFLOAD_STATE_IDLE;
6863 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006864 out->writeAt.tv_sec = 0;
6865 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006866
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006867 audio_extn_dts_create_state_notifier_node(out->usecase);
6868
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006869 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6870 __func__, config->offload_info.version,
6871 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306872
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306873 /* Check if DSD audio format is supported in codec
6874 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306875 */
6876
6877 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306878 (!platform_check_codec_dsd_support(adev->platform) ||
6879 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306880 ret = -EINVAL;
6881 goto error_open;
6882 }
6883
Ashish Jain5106d362016-05-11 19:23:33 +05306884 /* Disable gapless if any of the following is true
6885 * passthrough playback
6886 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306887 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306888 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306889 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306890 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006891 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306892 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306893 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306894 check_and_set_gapless_mode(adev, false);
6895 } else
6896 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006897
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306898 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006899 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6900 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306901 if (config->format == AUDIO_FORMAT_DSD) {
6902 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6903 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6904 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006905
6906 create_offload_callback_thread(out);
6907
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006908 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006909 switch (config->sample_rate) {
6910 case 0:
6911 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6912 break;
6913 case 8000:
6914 case 16000:
6915 case 48000:
6916 out->sample_rate = config->sample_rate;
6917 break;
6918 default:
6919 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6920 config->sample_rate);
6921 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6922 ret = -EINVAL;
6923 goto error_open;
6924 }
6925 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6926 switch (config->channel_mask) {
6927 case AUDIO_CHANNEL_NONE:
6928 case AUDIO_CHANNEL_OUT_STEREO:
6929 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6930 break;
6931 default:
6932 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6933 config->channel_mask);
6934 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6935 ret = -EINVAL;
6936 goto error_open;
6937 }
6938 switch (config->format) {
6939 case AUDIO_FORMAT_DEFAULT:
6940 case AUDIO_FORMAT_PCM_16_BIT:
6941 out->format = AUDIO_FORMAT_PCM_16_BIT;
6942 break;
6943 default:
6944 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6945 config->format);
6946 config->format = AUDIO_FORMAT_PCM_16_BIT;
6947 ret = -EINVAL;
6948 goto error_open;
6949 }
6950
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306951 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006952 if (ret != 0) {
6953 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006954 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006955 goto error_open;
6956 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006957 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006958 switch (config->sample_rate) {
6959 case 0:
6960 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
6961 break;
6962 case 8000:
6963 case 16000:
6964 case 48000:
6965 out->sample_rate = config->sample_rate;
6966 break;
6967 default:
6968 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
6969 config->sample_rate);
6970 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6971 ret = -EINVAL;
6972 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006973 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006974 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6975 switch (config->channel_mask) {
6976 case AUDIO_CHANNEL_NONE:
6977 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6978 break;
6979 case AUDIO_CHANNEL_OUT_STEREO:
6980 out->channel_mask = config->channel_mask;
6981 break;
6982 default:
6983 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
6984 config->channel_mask);
6985 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6986 ret = -EINVAL;
6987 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006988 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006989 switch (config->format) {
6990 case AUDIO_FORMAT_DEFAULT:
6991 out->format = AUDIO_FORMAT_PCM_16_BIT;
6992 break;
6993 case AUDIO_FORMAT_PCM_16_BIT:
6994 out->format = config->format;
6995 break;
6996 default:
6997 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
6998 config->format);
6999 config->format = AUDIO_FORMAT_PCM_16_BIT;
7000 ret = -EINVAL;
7001 break;
7002 }
7003 if (ret != 0)
7004 goto error_open;
7005
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007006 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7007 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007008 out->config.rate = out->sample_rate;
7009 out->config.channels =
7010 audio_channel_count_from_out_mask(out->channel_mask);
7011 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007012 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007013 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307014 unsigned int channels = 0;
7015 /*Update config params to default if not set by the caller*/
7016 if (config->sample_rate == 0)
7017 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7018 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7019 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7020 if (config->format == AUDIO_FORMAT_DEFAULT)
7021 config->format = AUDIO_FORMAT_PCM_16_BIT;
7022
7023 channels = audio_channel_count_from_out_mask(out->channel_mask);
7024
Varun Balaraje49253e2017-07-06 19:48:56 +05307025 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7026 out->usecase = get_interactive_usecase(adev);
7027 out->config = pcm_config_low_latency;
7028 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307029 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007030 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7031 out->flags);
7032 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007033 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7034 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7035 out->config = pcm_config_mmap_playback;
7036 out->stream.start = out_start;
7037 out->stream.stop = out_stop;
7038 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7039 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307040 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7041 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007042 out->hal_output_suspend_supported =
7043 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7044 out->dynamic_pm_qos_config_supported =
7045 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7046 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007047 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7048 } else {
7049 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7050 //the mixer path will be a string similar to "low-latency-playback resume"
7051 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7052 strlcat(out->pm_qos_mixer_path,
7053 " resume", MAX_MIXER_PATH_LEN);
7054 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7055 out->pm_qos_mixer_path);
7056 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307057 out->config = pcm_config_low_latency;
7058 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7059 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7060 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307061 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7062 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7063 if (out->config.period_size <= 0) {
7064 ALOGE("Invalid configuration period size is not valid");
7065 ret = -EINVAL;
7066 goto error_open;
7067 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007068 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7069 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7070 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007071 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7072 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7073 out->config = pcm_config_haptics_audio;
7074 if (force_haptic_path)
7075 adev->haptics_config = pcm_config_haptics_audio;
7076 else
7077 adev->haptics_config = pcm_config_haptics;
7078
7079 out->config.channels =
7080 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7081
7082 if (force_haptic_path) {
7083 out->config.channels = 1;
7084 adev->haptics_config.channels = 1;
7085 } else
7086 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307087 } else {
7088 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007089 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7090 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307091 }
7092 out->hal_ip_format = format = out->format;
7093 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7094 out->hal_op_format = pcm_format_to_hal(out->config.format);
7095 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7096 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007097 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307098 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307099 if (out->hal_ip_format != out->hal_op_format) {
7100 uint32_t buffer_size = out->config.period_size *
7101 format_to_bitwidth_table[out->hal_op_format] *
7102 out->config.channels;
7103 out->convert_buffer = calloc(1, buffer_size);
7104 if (out->convert_buffer == NULL){
7105 ALOGE("Allocation failed for convert buffer for size %d",
7106 out->compr_config.fragment_size);
7107 ret = -ENOMEM;
7108 goto error_open;
7109 }
7110 ALOGD("Convert buffer allocated of size %d", buffer_size);
7111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007112 }
7113
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007114 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7115 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307116
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007117 /* TODO remove this hardcoding and check why width is zero*/
7118 if (out->bit_width == 0)
7119 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307120 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007121 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007122 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307123 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307124 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007125 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007126 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7127 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007128 if(adev->primary_output == NULL)
7129 adev->primary_output = out;
7130 else {
7131 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007132 ret = -EEXIST;
7133 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007134 }
7135 }
7136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007137 /* Check if this usecase is already existing */
7138 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007139 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7140 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007141 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007143 ret = -EEXIST;
7144 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007145 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147 pthread_mutex_unlock(&adev->lock);
7148
7149 out->stream.common.get_sample_rate = out_get_sample_rate;
7150 out->stream.common.set_sample_rate = out_set_sample_rate;
7151 out->stream.common.get_buffer_size = out_get_buffer_size;
7152 out->stream.common.get_channels = out_get_channels;
7153 out->stream.common.get_format = out_get_format;
7154 out->stream.common.set_format = out_set_format;
7155 out->stream.common.standby = out_standby;
7156 out->stream.common.dump = out_dump;
7157 out->stream.common.set_parameters = out_set_parameters;
7158 out->stream.common.get_parameters = out_get_parameters;
7159 out->stream.common.add_audio_effect = out_add_audio_effect;
7160 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7161 out->stream.get_latency = out_get_latency;
7162 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007163#ifdef NO_AUDIO_OUT
7164 out->stream.write = out_write_for_no_output;
7165#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007166 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007167#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168 out->stream.get_render_position = out_get_render_position;
7169 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007170 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007171
Haynes Mathew George16081042017-05-31 17:16:49 -07007172 if (out->realtime)
7173 out->af_period_multiplier = af_period_multiplier;
7174 else
7175 out->af_period_multiplier = 1;
7176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007178 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007179 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007180
7181 config->format = out->stream.common.get_format(&out->stream.common);
7182 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7183 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307184 register_format(out->format, out->supported_formats);
7185 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7186 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187
Aalique Grahame22e49102018-12-18 14:23:57 -08007188 out->error_log = error_log_create(
7189 ERROR_LOG_ENTRIES,
7190 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7191
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307192 /*
7193 By locking output stream before registering, we allow the callback
7194 to update stream's state only after stream's initial state is set to
7195 adev state.
7196 */
7197 lock_output_stream(out);
7198 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7199 pthread_mutex_lock(&adev->lock);
7200 out->card_status = adev->card_status;
7201 pthread_mutex_unlock(&adev->lock);
7202 pthread_mutex_unlock(&out->lock);
7203
Aalique Grahame22e49102018-12-18 14:23:57 -08007204 stream_app_type_cfg_init(&out->app_type_cfg);
7205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007206 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307207 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007208 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007209
7210 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7211 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7212 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007213 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307214 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007215 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007216 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307217 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007218 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7219 out->usecase, PCM_PLAYBACK);
7220 hdlr_stream_cfg.flags = out->flags;
7221 hdlr_stream_cfg.type = PCM_PLAYBACK;
7222 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7223 &hdlr_stream_cfg);
7224 if (ret) {
7225 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7226 out->adsp_hdlr_stream_handle = NULL;
7227 }
7228 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307229 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007230 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007231 if (ret < 0) {
7232 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7233 out->ip_hdlr_handle = NULL;
7234 }
7235 }
Eric Laurent994a6932013-07-17 11:51:42 -07007236 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007238
7239error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307240 if (out->convert_buffer)
7241 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007242 free(out);
7243 *stream_out = NULL;
7244 ALOGD("%s: exit: ret %d", __func__, ret);
7245 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007246}
7247
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307248void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249 struct audio_stream_out *stream)
7250{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007251 struct stream_out *out = (struct stream_out *)stream;
7252 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007253 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007254
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007255 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307256
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307257 // must deregister from sndmonitor first to prevent races
7258 // between the callback and close_stream
7259 audio_extn_snd_mon_unregister_listener(out);
7260
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007261 /* close adsp hdrl session before standby */
7262 if (out->adsp_hdlr_stream_handle) {
7263 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7264 if (ret)
7265 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7266 out->adsp_hdlr_stream_handle = NULL;
7267 }
7268
Manish Dewangan21a850a2017-08-14 12:03:55 +05307269 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007270 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7271 out->ip_hdlr_handle = NULL;
7272 }
7273
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007274 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307275 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007276 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307277 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307278 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007279 if(ret != 0)
7280 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7281 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007282 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007283 out_standby(&stream->common);
7284
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007285 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007286 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007287 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007288 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007289 if (out->compr_config.codec != NULL)
7290 free(out->compr_config.codec);
7291 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007292
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307293 out->a2dp_compress_mute = false;
7294
Varun Balaraje49253e2017-07-06 19:48:56 +05307295 if (is_interactive_usecase(out->usecase))
7296 free_interactive_usecase(adev, out->usecase);
7297
Ashish Jain83a6cc22016-06-28 14:34:17 +05307298 if (out->convert_buffer != NULL) {
7299 free(out->convert_buffer);
7300 out->convert_buffer = NULL;
7301 }
7302
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007303 if (adev->voice_tx_output == out)
7304 adev->voice_tx_output = NULL;
7305
Aalique Grahame22e49102018-12-18 14:23:57 -08007306 error_log_destroy(out->error_log);
7307 out->error_log = NULL;
7308
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307309 if (adev->primary_output == out)
7310 adev->primary_output = NULL;
7311
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007312 pthread_cond_destroy(&out->cond);
7313 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007314 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07007315 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007316}
7317
7318static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7319{
7320 struct audio_device *adev = (struct audio_device *)dev;
7321 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007322 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007323 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007324 int ret;
7325 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007326 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007327
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007328 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007329 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007330
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307331 if (!parms)
7332 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307333
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307334 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7335 if (ret >= 0) {
7336 /* When set to false, HAL should disable EC and NS */
7337 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7338 adev->bt_sco_on = true;
7339 else
7340 adev->bt_sco_on = false;
7341 }
7342
Naresh Tanniru4c630392014-05-12 01:05:52 +05307343 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007344 status = voice_set_parameters(adev, parms);
7345 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007346 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007347
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007348 status = platform_set_parameters(adev->platform, parms);
7349 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007350 goto done;
7351
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007352 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7353 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007354 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007355 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7356 adev->bluetooth_nrec = true;
7357 else
7358 adev->bluetooth_nrec = false;
7359 }
7360
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007361 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7362 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7364 adev->screen_off = false;
7365 else
7366 adev->screen_off = true;
7367 }
7368
Aalique Grahame22e49102018-12-18 14:23:57 -08007369#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007370 ret = str_parms_get_int(parms, "rotation", &val);
7371 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007372 bool reverse_speakers = false;
7373 switch(val) {
7374 // FIXME: note that the code below assumes that the speakers are in the correct placement
7375 // relative to the user when the device is rotated 90deg from its default rotation. This
7376 // assumption is device-specific, not platform-specific like this code.
7377 case 270:
7378 reverse_speakers = true;
7379 break;
7380 case 0:
7381 case 90:
7382 case 180:
7383 break;
7384 default:
7385 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007386 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007387 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007388 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007389 // check and set swap
7390 // - check if orientation changed and speaker active
7391 // - set rotation and cache the rotation value
7392 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007393 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007394 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007395#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007396
Mingming Yin514a8bc2014-07-29 15:22:21 -07007397 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7398 if (ret >= 0) {
7399 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7400 adev->bt_wb_speech_enabled = true;
7401 else
7402 adev->bt_wb_speech_enabled = false;
7403 }
7404
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007405 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7406 if (ret >= 0) {
7407 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307408 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007409 if (audio_is_output_device(val) &&
7410 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007411 ALOGV("cache new ext disp type and edid");
7412 ret = platform_get_ext_disp_type(adev->platform);
7413 if (ret < 0) {
7414 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307415 } else {
7416 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007417 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307418 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007419 /*
7420 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7421 * Per AudioPolicyManager, USB device is higher priority than WFD.
7422 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7423 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7424 * starting voice call on USB
7425 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007426 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307427 if (ret >= 0)
7428 audio_extn_usb_add_device(device, atoi(value));
7429
Zhou Song6f862822017-11-06 17:27:57 +08007430 if (!audio_extn_usb_is_tunnel_supported()) {
7431 ALOGV("detected USB connect .. disable proxy");
7432 adev->allow_afe_proxy_usage = false;
7433 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007434 }
7435 }
7436
7437 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7438 if (ret >= 0) {
7439 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307440 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007441 /*
7442 * The HDMI / Displayport disconnect handling has been moved to
7443 * audio extension to ensure that its parameters are not
7444 * invalidated prior to updating sysfs of the disconnect event
7445 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7446 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307447 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007448 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307449 if (ret >= 0)
7450 audio_extn_usb_remove_device(device, atoi(value));
7451
Zhou Song6f862822017-11-06 17:27:57 +08007452 if (!audio_extn_usb_is_tunnel_supported()) {
7453 ALOGV("detected USB disconnect .. enable proxy");
7454 adev->allow_afe_proxy_usage = true;
7455 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007456 }
7457 }
7458
Aalique Grahame22e49102018-12-18 14:23:57 -08007459 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007460 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007461
7462 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007463 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307464 struct audio_usecase *usecase;
7465 struct listnode *node;
7466 list_for_each(node, &adev->usecase_list) {
7467 usecase = node_to_item(node, struct audio_usecase, list);
7468 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007469 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307470 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007471
7472 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307473 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007474 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307475 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307476 //force device switch to re configure encoder
7477 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307478 audio_extn_a2dp_set_handoff_mode(false);
7479 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307480 break;
7481 }
7482 }
7483 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007484
7485 //handle vr audio setparam
7486 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7487 value, sizeof(value));
7488 if (ret >= 0) {
7489 ALOGI("Setting vr mode to be %s", value);
7490 if (!strncmp(value, "true", 4)) {
7491 adev->vr_audio_mode_enabled = true;
7492 ALOGI("Setting vr mode to true");
7493 } else if (!strncmp(value, "false", 5)) {
7494 adev->vr_audio_mode_enabled = false;
7495 ALOGI("Setting vr mode to false");
7496 } else {
7497 ALOGI("wrong vr mode set");
7498 }
7499 }
7500
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307501 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007502done:
7503 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007504 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307505error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007506 ALOGV("%s: exit with code(%d)", __func__, status);
7507 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007508}
7509
7510static char* adev_get_parameters(const struct audio_hw_device *dev,
7511 const char *keys)
7512{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307513 ALOGD("%s:%s", __func__, keys);
7514
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007515 struct audio_device *adev = (struct audio_device *)dev;
7516 struct str_parms *reply = str_parms_create();
7517 struct str_parms *query = str_parms_create_str(keys);
7518 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307519 char value[256] = {0};
7520 int ret = 0;
7521
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007522 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007523 if (reply) {
7524 str_parms_destroy(reply);
7525 }
7526 if (query) {
7527 str_parms_destroy(query);
7528 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007529 ALOGE("adev_get_parameters: failed to create query or reply");
7530 return NULL;
7531 }
7532
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007533 //handle vr audio getparam
7534
7535 ret = str_parms_get_str(query,
7536 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7537 value, sizeof(value));
7538
7539 if (ret >= 0) {
7540 bool vr_audio_enabled = false;
7541 pthread_mutex_lock(&adev->lock);
7542 vr_audio_enabled = adev->vr_audio_mode_enabled;
7543 pthread_mutex_unlock(&adev->lock);
7544
7545 ALOGI("getting vr mode to %d", vr_audio_enabled);
7546
7547 if (vr_audio_enabled) {
7548 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7549 "true");
7550 goto exit;
7551 } else {
7552 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7553 "false");
7554 goto exit;
7555 }
7556 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007557
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007558 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007559 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007560 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007561 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007562 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307563 pthread_mutex_unlock(&adev->lock);
7564
Naresh Tannirud7205b62014-06-20 02:54:48 +05307565exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007566 str = str_parms_to_str(reply);
7567 str_parms_destroy(query);
7568 str_parms_destroy(reply);
7569
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307570 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007571 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007572}
7573
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007574static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007575{
7576 return 0;
7577}
7578
7579static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7580{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007581 int ret;
7582 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007583
7584 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7585
Haynes Mathew George5191a852013-09-11 14:19:36 -07007586 pthread_mutex_lock(&adev->lock);
7587 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007588 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007589 pthread_mutex_unlock(&adev->lock);
7590 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007591}
7592
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007593static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7594 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007595{
7596 return -ENOSYS;
7597}
7598
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007599static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7600 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007601{
7602 return -ENOSYS;
7603}
7604
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007605static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7606 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007607{
7608 return -ENOSYS;
7609}
7610
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007611static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7612 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007613{
7614 return -ENOSYS;
7615}
7616
7617static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7618{
7619 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007620 struct listnode *node;
7621 struct audio_usecase *usecase = NULL;
7622 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007623 pthread_mutex_lock(&adev->lock);
7624 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007625 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007626 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007627 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007628 list_for_each(node, &adev->usecase_list) {
7629 usecase = node_to_item(node, struct audio_usecase, list);
7630 if (usecase->type == VOICE_CALL)
7631 break;
7632 }
7633 if (usecase &&
7634 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7635 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7636 true);
7637 if (ret != 0) {
7638 /* default service interval was successfully updated,
7639 reopen USB backend with new service interval */
7640 check_usecases_codec_backend(adev,
7641 usecase,
7642 usecase->out_snd_device);
7643 }
7644 }
7645
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007646 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007647 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007648 adev->current_call_output = NULL;
7649 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007650 }
7651 pthread_mutex_unlock(&adev->lock);
7652 return 0;
7653}
7654
7655static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7656{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007657 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007658 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007659
7660 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007661 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007662 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007663
Derek Chend2530072014-11-24 12:39:14 -08007664 if (adev->ext_hw_plugin)
7665 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007666
7667 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007668 pthread_mutex_unlock(&adev->lock);
7669
7670 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007671}
7672
7673static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7674{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007675 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007676 return 0;
7677}
7678
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007679static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007680 const struct audio_config *config)
7681{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007682 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007683
Aalique Grahame22e49102018-12-18 14:23:57 -08007684 /* Don't know if USB HIFI in this context so use true to be conservative */
7685 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7686 true /*is_usb_hifi */) != 0)
7687 return 0;
7688
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007689 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7690 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007691}
7692
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007693static bool adev_input_allow_hifi_record(struct audio_device *adev,
7694 audio_devices_t devices,
7695 audio_input_flags_t flags,
7696 audio_source_t source) {
7697 const bool allowed = true;
7698
7699 if (!audio_is_usb_in_device(devices))
7700 return !allowed;
7701
7702 switch (flags) {
7703 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007704 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007705 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7706 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007707 default:
7708 return !allowed;
7709 }
7710
7711 switch (source) {
7712 case AUDIO_SOURCE_DEFAULT:
7713 case AUDIO_SOURCE_MIC:
7714 case AUDIO_SOURCE_UNPROCESSED:
7715 break;
7716 default:
7717 return !allowed;
7718 }
7719
7720 switch (adev->mode) {
7721 case 0:
7722 break;
7723 default:
7724 return !allowed;
7725 }
7726
7727 return allowed;
7728}
7729
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007730static int adev_update_voice_comm_input_stream(struct stream_in *in,
7731 struct audio_config *config)
7732{
7733 bool valid_rate = (config->sample_rate == 8000 ||
7734 config->sample_rate == 16000 ||
7735 config->sample_rate == 32000 ||
7736 config->sample_rate == 48000);
7737 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7738
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007739 if(!voice_extn_is_compress_voip_supported()) {
7740 if (valid_rate && valid_ch &&
kunleizd96526c2018-04-09 11:12:32 +08007741 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007742 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7743 in->config = default_pcm_config_voip_copp;
7744 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7745 DEFAULT_VOIP_BUF_DURATION_MS,
7746 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007747 } else {
7748 ALOGW("%s No valid input in voip, use defaults"
7749 "sample rate %u, channel mask 0x%X",
7750 __func__, config->sample_rate, in->channel_mask);
7751 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007752 in->config.rate = config->sample_rate;
7753 in->sample_rate = config->sample_rate;
7754 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007755 //XXX needed for voice_extn_compress_voip_open_input_stream
7756 in->config.rate = config->sample_rate;
7757 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7758 voice_extn_compress_voip_is_active(in->dev)) &&
7759 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7760 valid_rate && valid_ch) {
7761 voice_extn_compress_voip_open_input_stream(in);
7762 // update rate entries to match config from AF
7763 in->config.rate = config->sample_rate;
7764 in->sample_rate = config->sample_rate;
7765 } else {
7766 ALOGW("%s compress voip not active, use defaults", __func__);
7767 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007768 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007769 return 0;
7770}
7771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007772static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007773 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007774 audio_devices_t devices,
7775 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007776 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307777 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007778 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007779 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007780{
7781 struct audio_device *adev = (struct audio_device *)dev;
7782 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007783 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007784 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007785 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307786 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007787 bool is_usb_dev = audio_is_usb_in_device(devices);
7788 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7789 devices,
7790 flags,
7791 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307792
kunleizdff872d2018-08-20 14:40:33 +08007793 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007794 is_usb_dev = false;
7795 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7796 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7797 __func__, devices);
7798 }
7799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007800 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007801
7802 if (!(is_usb_dev && may_use_hifi_record)) {
7803 if (config->sample_rate == 0)
7804 config->sample_rate = 48000;
7805 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7806 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7807 if (config->format == AUDIO_FORMAT_DEFAULT)
7808 config->format = AUDIO_FORMAT_PCM_16_BIT;
7809
7810 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7811
Aalique Grahame22e49102018-12-18 14:23:57 -08007812 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7813 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007814 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007816
7817 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007818
7819 if (!in) {
7820 ALOGE("failed to allocate input stream");
7821 return -ENOMEM;
7822 }
7823
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307824 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307825 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7826 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007827 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007828 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007830 in->stream.common.get_sample_rate = in_get_sample_rate;
7831 in->stream.common.set_sample_rate = in_set_sample_rate;
7832 in->stream.common.get_buffer_size = in_get_buffer_size;
7833 in->stream.common.get_channels = in_get_channels;
7834 in->stream.common.get_format = in_get_format;
7835 in->stream.common.set_format = in_set_format;
7836 in->stream.common.standby = in_standby;
7837 in->stream.common.dump = in_dump;
7838 in->stream.common.set_parameters = in_set_parameters;
7839 in->stream.common.get_parameters = in_get_parameters;
7840 in->stream.common.add_audio_effect = in_add_audio_effect;
7841 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7842 in->stream.set_gain = in_set_gain;
7843 in->stream.read = in_read;
7844 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08007845 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307846 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007847
7848 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007849 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007850 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007851 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007852 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007853 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007854 in->bit_width = 16;
7855 in->af_period_multiplier = 1;
7856
Aalique Grahame22e49102018-12-18 14:23:57 -08007857 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
7858 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
7859 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
7860 /* Force channel config requested to mono if incall
7861 record is being requested for only uplink/downlink */
7862 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
7863 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7864 ret = -EINVAL;
7865 goto err_open;
7866 }
7867 }
7868
Haynes Mathew George46740472017-10-27 18:40:12 -07007869 /* Update config params with the requested sample rate and channels */
7870 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7871 (adev->mode != AUDIO_MODE_IN_CALL)) {
7872 ret = -EINVAL;
7873 goto err_open;
7874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007875
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007876 if (is_usb_dev && may_use_hifi_record) {
7877 /* HiFi record selects an appropriate format, channel, rate combo
7878 depending on sink capabilities*/
7879 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7880 &config->format,
7881 &in->supported_formats[0],
7882 MAX_SUPPORTED_FORMATS,
7883 &config->channel_mask,
7884 &in->supported_channel_masks[0],
7885 MAX_SUPPORTED_CHANNEL_MASKS,
7886 &config->sample_rate,
7887 &in->supported_sample_rates[0],
7888 MAX_SUPPORTED_SAMPLE_RATES);
7889 if (ret != 0) {
7890 ret = -EINVAL;
7891 goto err_open;
7892 }
7893 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007894 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307895 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307896 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7897 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7898 in->config.format = PCM_FORMAT_S32_LE;
7899 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307900 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7901 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7902 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7903 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7904 bool ret_error = false;
7905 in->bit_width = 24;
7906 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7907 from HAL is 24_packed and 8_24
7908 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7909 24_packed return error indicating supported format is 24_packed
7910 *> In case of any other source requesting 24 bit or float return error
7911 indicating format supported is 16 bit only.
7912
7913 on error flinger will retry with supported format passed
7914 */
7915 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7916 (source != AUDIO_SOURCE_CAMCORDER)) {
7917 config->format = AUDIO_FORMAT_PCM_16_BIT;
7918 if (config->sample_rate > 48000)
7919 config->sample_rate = 48000;
7920 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007921 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7922 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307923 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7924 ret_error = true;
7925 }
7926
7927 if (ret_error) {
7928 ret = -EINVAL;
7929 goto err_open;
7930 }
7931 }
7932
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007933 in->channel_mask = config->channel_mask;
7934 in->format = config->format;
7935
7936 in->usecase = USECASE_AUDIO_RECORD;
7937 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7938 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7939 is_low_latency = true;
7940#if LOW_LATENCY_CAPTURE_USE_CASE
7941 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7942#endif
7943 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08007944 if (!in->realtime) {
7945 in->config = pcm_config_audio_capture;
7946 frame_size = audio_stream_in_frame_size(&in->stream);
7947 buffer_size = get_input_buffer_size(config->sample_rate,
7948 config->format,
7949 channel_count,
7950 is_low_latency);
7951 in->config.period_size = buffer_size / frame_size;
7952 in->config.rate = config->sample_rate;
7953 in->af_period_multiplier = 1;
7954 } else {
7955 // period size is left untouched for rt mode playback
7956 in->config = pcm_config_audio_capture_rt;
7957 in->af_period_multiplier = af_period_multiplier;
7958 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007959 }
7960
7961 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7962 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7963 in->realtime = 0;
7964 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7965 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007966 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08007967 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007968 in->stream.start = in_start;
7969 in->stream.stop = in_stop;
7970 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7971 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007972 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007973 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7974 } else if (in->realtime) {
7975 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007976 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007977 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007978 in->sample_rate = in->config.rate;
7979 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007980 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007981 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7982 in->config = pcm_config_audio_capture;
7983 frame_size = audio_stream_in_frame_size(&in->stream);
7984 buffer_size = get_input_buffer_size(config->sample_rate,
7985 config->format,
7986 channel_count,
7987 false /*is_low_latency*/);
7988 in->config.period_size = buffer_size / frame_size;
7989 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007990 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007991 switch (config->format) {
7992 case AUDIO_FORMAT_PCM_32_BIT:
7993 in->bit_width = 32;
7994 break;
7995 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7996 case AUDIO_FORMAT_PCM_8_24_BIT:
7997 in->bit_width = 24;
7998 break;
7999 default:
8000 in->bit_width = 16;
8001 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008002 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008003 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008004 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308005 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008006 if (config->sample_rate == 0)
8007 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8008 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8009 config->sample_rate != 8000) {
8010 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8011 ret = -EINVAL;
8012 goto err_open;
8013 }
8014 if (config->format == AUDIO_FORMAT_DEFAULT)
8015 config->format = AUDIO_FORMAT_PCM_16_BIT;
8016 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8017 config->format = AUDIO_FORMAT_PCM_16_BIT;
8018 ret = -EINVAL;
8019 goto err_open;
8020 }
8021
8022 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8023 in->config = pcm_config_afe_proxy_record;
8024 in->config.channels = channel_count;
8025 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308026 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008027 in->af_period_multiplier = 1;
8028 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8029 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8030 (config->sample_rate == 8000 ||
8031 config->sample_rate == 16000 ||
8032 config->sample_rate == 32000 ||
8033 config->sample_rate == 48000) &&
8034 channel_count == 1) {
8035 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8036 in->config = pcm_config_audio_capture;
8037 frame_size = audio_stream_in_frame_size(&in->stream);
8038 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8039 config->sample_rate,
8040 config->format,
8041 channel_count, false /*is_low_latency*/);
8042 in->config.period_size = buffer_size / frame_size;
8043 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8044 in->config.rate = config->sample_rate;
8045 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008046 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308047 int ret_val;
8048 pthread_mutex_lock(&adev->lock);
8049 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8050 in, config, &channel_mask_updated);
Samyak Jain15fda662018-12-18 16:40:52 +05308051#ifdef CONCURRENT_CAPTURE_ENABLED
8052 /* Acquire lock to avoid two concurrent use cases initialized to
8053 same pcm record use case*/
8054
8055 if(in->usecase == USECASE_AUDIO_RECORD) {
8056 if (!(adev->pcm_record_uc_state)) {
8057 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8058 adev->pcm_record_uc_state = 1;
8059 } else {
8060 /* Assign compress record use case for second record */
8061 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8062 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8063 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8064 }
8065 }
8066#endif
Revathi Uddarajud2634032017-12-07 14:42:34 +05308067 pthread_mutex_unlock(&adev->lock);
8068
8069 if (!ret_val) {
8070 if (channel_mask_updated == true) {
8071 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8072 __func__, config->channel_mask);
8073 ret = -EINVAL;
8074 goto err_open;
8075 }
8076 ALOGD("%s: created multi-channel session succesfully",__func__);
8077 } else if (audio_extn_compr_cap_enabled() &&
8078 audio_extn_compr_cap_format_supported(config->format) &&
8079 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8080 audio_extn_compr_cap_init(in);
8081 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05308082 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05308083 ret = audio_extn_cin_configure_input_stream(in);
8084 if (ret)
8085 goto err_open;
8086 } else {
8087 in->config = pcm_config_audio_capture;
8088 in->config.rate = config->sample_rate;
8089 in->config.format = pcm_format_from_audio_format(config->format);
8090 in->config.channels = channel_count;
8091 in->sample_rate = config->sample_rate;
8092 in->format = config->format;
8093 frame_size = audio_stream_in_frame_size(&in->stream);
8094 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008095 config->format,
8096 channel_count,
8097 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008098 /* prevent division-by-zero */
8099 if (frame_size == 0) {
8100 ALOGE("%s: Error frame_size==0", __func__);
8101 ret = -EINVAL;
8102 goto err_open;
8103 }
8104
Revathi Uddarajud2634032017-12-07 14:42:34 +05308105 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008106 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008107
Revathi Uddarajud2634032017-12-07 14:42:34 +05308108 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8109 /* optionally use VOIP usecase depending on config(s) */
8110 ret = adev_update_voice_comm_input_stream(in, config);
8111 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008112
Revathi Uddarajud2634032017-12-07 14:42:34 +05308113 if (ret) {
8114 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8115 goto err_open;
8116 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008117 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008118 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308119 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8120 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008121 devices, flags, in->format,
8122 in->sample_rate, in->bit_width,
8123 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308124 register_format(in->format, in->supported_formats);
8125 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8126 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308127
Aalique Grahame22e49102018-12-18 14:23:57 -08008128 in->error_log = error_log_create(
8129 ERROR_LOG_ENTRIES,
8130 1000000000 /* aggregate consecutive identical errors within one second */);
8131
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008132 /* This stream could be for sound trigger lab,
8133 get sound trigger pcm if present */
8134 audio_extn_sound_trigger_check_and_get_session(in);
8135
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308136 lock_input_stream(in);
8137 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8138 pthread_mutex_lock(&adev->lock);
8139 in->card_status = adev->card_status;
8140 pthread_mutex_unlock(&adev->lock);
8141 pthread_mutex_unlock(&in->lock);
8142
Aalique Grahame22e49102018-12-18 14:23:57 -08008143 stream_app_type_cfg_init(&in->app_type_cfg);
8144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008145 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07008146 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008147 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008148
8149err_open:
8150 free(in);
8151 *stream_in = NULL;
8152 return ret;
8153}
8154
8155static void adev_close_input_stream(struct audio_hw_device *dev,
8156 struct audio_stream_in *stream)
8157{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008158 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008159 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008160 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308161
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308162 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008163
kunleiz70e57612018-12-28 17:50:23 +08008164 /* must deregister from sndmonitor first to prevent races
8165 * between the callback and close_stream
8166 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308167 audio_extn_snd_mon_unregister_listener(stream);
8168
kunleiz70e57612018-12-28 17:50:23 +08008169 /* Disable echo reference if there are no active input, hfp call
8170 * and sound trigger while closing input stream
8171 */
8172 if (!adev->active_input &&
8173 !audio_extn_hfp_is_active(adev) &&
8174 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008175 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008176 else
8177 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308178
Aalique Grahame22e49102018-12-18 14:23:57 -08008179 error_log_destroy(in->error_log);
8180 in->error_log = NULL;
8181
Pallavid7c7a272018-01-16 11:22:55 +05308182 if (in == NULL) {
8183 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8184 return;
8185 }
8186
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008187 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308188 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008189 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308190 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008191 if (ret != 0)
8192 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8193 __func__, ret);
8194 } else
8195 in_standby(&stream->common);
8196
Revathi Uddarajud2634032017-12-07 14:42:34 +05308197 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308198 if (in->usecase == USECASE_AUDIO_RECORD) {
8199 adev->pcm_record_uc_state = 0;
8200 }
8201
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008202 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008203 audio_extn_ssr_deinit();
8204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008205
Garmond Leunge2433c32017-09-28 21:51:22 -07008206 if (audio_extn_ffv_get_stream() == in) {
8207 audio_extn_ffv_stream_deinit();
8208 }
8209
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308210 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008211 audio_extn_compr_cap_format_supported(in->config.format))
8212 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308213
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308214 if (audio_extn_cin_attached_usecase(in->usecase))
8215 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008216
Mingming Yinfd7607b2016-01-22 12:48:44 -08008217 if (in->is_st_session) {
8218 ALOGV("%s: sound trigger pcm stop lab", __func__);
8219 audio_extn_sound_trigger_stop_lab(in);
8220 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008221 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308222 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008223 return;
8224}
8225
Aalique Grahame22e49102018-12-18 14:23:57 -08008226/* verifies input and output devices and their capabilities.
8227 *
8228 * This verification is required when enabling extended bit-depth or
8229 * sampling rates, as not all qcom products support it.
8230 *
8231 * Suitable for calling only on initialization such as adev_open().
8232 * It fills the audio_device use_case_table[] array.
8233 *
8234 * Has a side-effect that it needs to configure audio routing / devices
8235 * in order to power up the devices and read the device parameters.
8236 * It does not acquire any hw device lock. Should restore the devices
8237 * back to "normal state" upon completion.
8238 */
8239static int adev_verify_devices(struct audio_device *adev)
8240{
8241 /* enumeration is a bit difficult because one really wants to pull
8242 * the use_case, device id, etc from the hidden pcm_device_table[].
8243 * In this case there are the following use cases and device ids.
8244 *
8245 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8246 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8247 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8248 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8249 * [USECASE_AUDIO_RECORD] = {0, 0},
8250 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8251 * [USECASE_VOICE_CALL] = {2, 2},
8252 *
8253 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8254 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8255 */
8256
8257 /* should be the usecases enabled in adev_open_input_stream() */
8258 static const int test_in_usecases[] = {
8259 USECASE_AUDIO_RECORD,
8260 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8261 };
8262 /* should be the usecases enabled in adev_open_output_stream()*/
8263 static const int test_out_usecases[] = {
8264 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8265 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8266 };
8267 static const usecase_type_t usecase_type_by_dir[] = {
8268 PCM_PLAYBACK,
8269 PCM_CAPTURE,
8270 };
8271 static const unsigned flags_by_dir[] = {
8272 PCM_OUT,
8273 PCM_IN,
8274 };
8275
8276 size_t i;
8277 unsigned dir;
8278 const unsigned card_id = adev->snd_card;
8279
8280 for (dir = 0; dir < 2; ++dir) {
8281 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8282 const unsigned flags_dir = flags_by_dir[dir];
8283 const size_t testsize =
8284 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8285 const int *testcases =
8286 dir ? test_in_usecases : test_out_usecases;
8287 const audio_devices_t audio_device =
8288 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8289
8290 for (i = 0; i < testsize; ++i) {
8291 const audio_usecase_t audio_usecase = testcases[i];
8292 int device_id;
8293 struct pcm_params **pparams;
8294 struct stream_out out;
8295 struct stream_in in;
8296 struct audio_usecase uc_info;
8297 int retval;
8298
8299 pparams = &adev->use_case_table[audio_usecase];
8300 pcm_params_free(*pparams); /* can accept null input */
8301 *pparams = NULL;
8302
8303 /* find the device ID for the use case (signed, for error) */
8304 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8305 if (device_id < 0)
8306 continue;
8307
8308 /* prepare structures for device probing */
8309 memset(&uc_info, 0, sizeof(uc_info));
8310 uc_info.id = audio_usecase;
8311 uc_info.type = usecase_type;
8312 if (dir) {
8313 adev->active_input = &in;
8314 memset(&in, 0, sizeof(in));
8315 in.device = audio_device;
8316 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8317 uc_info.stream.in = &in;
8318 } else {
8319 adev->active_input = NULL;
8320 }
8321 memset(&out, 0, sizeof(out));
8322 out.devices = audio_device; /* only field needed in select_devices */
8323 uc_info.stream.out = &out;
8324 uc_info.devices = audio_device;
8325 uc_info.in_snd_device = SND_DEVICE_NONE;
8326 uc_info.out_snd_device = SND_DEVICE_NONE;
8327 list_add_tail(&adev->usecase_list, &uc_info.list);
8328
8329 /* select device - similar to start_(in/out)put_stream() */
8330 retval = select_devices(adev, audio_usecase);
8331 if (retval >= 0) {
8332 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8333#if LOG_NDEBUG == 0
8334 if (*pparams) {
8335 ALOGV("%s: (%s) card %d device %d", __func__,
8336 dir ? "input" : "output", card_id, device_id);
8337 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8338 } else {
8339 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8340 }
8341#endif
8342 }
8343
8344 /* deselect device - similar to stop_(in/out)put_stream() */
8345 /* 1. Get and set stream specific mixer controls */
8346 retval = disable_audio_route(adev, &uc_info);
8347 /* 2. Disable the rx device */
8348 retval = disable_snd_device(adev,
8349 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8350 list_remove(&uc_info.list);
8351 }
8352 }
8353 adev->active_input = NULL; /* restore adev state */
8354 return 0;
8355}
8356
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308357int adev_create_audio_patch(struct audio_hw_device *dev,
8358 unsigned int num_sources,
8359 const struct audio_port_config *sources,
8360 unsigned int num_sinks,
8361 const struct audio_port_config *sinks,
8362 audio_patch_handle_t *handle)
8363{
8364
8365
8366 return audio_extn_hw_loopback_create_audio_patch(dev,
8367 num_sources,
8368 sources,
8369 num_sinks,
8370 sinks,
8371 handle);
8372
8373}
8374
8375int adev_release_audio_patch(struct audio_hw_device *dev,
8376 audio_patch_handle_t handle)
8377{
8378 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
8379}
8380
8381int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8382{
8383 return audio_extn_hw_loopback_get_audio_port(dev, config);
8384}
8385
8386int adev_set_audio_port_config(struct audio_hw_device *dev,
8387 const struct audio_port_config *config)
8388{
8389 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8390}
8391
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008392static int adev_dump(const audio_hw_device_t *device __unused,
8393 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008394{
8395 return 0;
8396}
8397
8398static int adev_close(hw_device_t *device)
8399{
Aalique Grahame22e49102018-12-18 14:23:57 -08008400 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008401 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008402
8403 if (!adev)
8404 return 0;
8405
8406 pthread_mutex_lock(&adev_init_lock);
8407
8408 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308409 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008410 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008411 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008412 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008413 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308414 audio_extn_utils_release_streams_cfg_lists(
8415 &adev->streams_output_cfg_list,
8416 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308417 if (audio_extn_qaf_is_enabled())
8418 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008419 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008420 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008421 free(adev->snd_dev_ref_cnt);
8422 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008423 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8424 pcm_params_free(adev->use_case_table[i]);
8425 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008426 if (adev->adm_deinit)
8427 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308428 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008429 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308430 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308431 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008432 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308433 if (adev->device_cfg_params) {
8434 free(adev->device_cfg_params);
8435 adev->device_cfg_params = NULL;
8436 }
Derek Chend2530072014-11-24 12:39:14 -08008437 if(adev->ext_hw_plugin)
8438 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008439 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008440 free(device);
8441 adev = NULL;
8442 }
8443 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308444 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008445 return 0;
8446}
8447
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008448/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8449 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8450 * just that it _might_ work.
8451 */
8452static int period_size_is_plausible_for_low_latency(int period_size)
8453{
8454 switch (period_size) {
8455 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008456 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008457 case 240:
8458 case 320:
8459 case 480:
8460 return 1;
8461 default:
8462 return 0;
8463 }
8464}
8465
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308466static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8467{
8468 bool is_snd_card_status = false;
8469 bool is_ext_device_status = false;
8470 char value[32];
8471 int card = -1;
8472 card_status_t status;
8473
8474 if (cookie != adev || !parms)
8475 return;
8476
8477 if (!parse_snd_card_status(parms, &card, &status)) {
8478 is_snd_card_status = true;
8479 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8480 is_ext_device_status = true;
8481 } else {
8482 // not a valid event
8483 return;
8484 }
8485
8486 pthread_mutex_lock(&adev->lock);
8487 if (card == adev->snd_card || is_ext_device_status) {
8488 if (is_snd_card_status && adev->card_status != status) {
8489 adev->card_status = status;
8490 platform_snd_card_update(adev->platform, status);
8491 audio_extn_fm_set_parameters(adev, parms);
8492 } else if (is_ext_device_status) {
8493 platform_set_parameters(adev->platform, parms);
8494 }
8495 }
8496 pthread_mutex_unlock(&adev->lock);
8497 return;
8498}
8499
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308500/* out and adev lock held */
8501static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8502{
8503 struct audio_usecase *uc_info;
8504 float left_p;
8505 float right_p;
8506 audio_devices_t devices;
8507
8508 uc_info = get_usecase_from_list(adev, out->usecase);
8509 if (uc_info == NULL) {
8510 ALOGE("%s: Could not find the usecase (%d) in the list",
8511 __func__, out->usecase);
8512 return -EINVAL;
8513 }
8514
8515 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8516 out->usecase, use_case_table[out->usecase]);
8517
8518 if (restore) {
8519 // restore A2DP device for active usecases and unmute if required
8520 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8521 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8522 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8523 select_devices(adev, uc_info->id);
8524 pthread_mutex_lock(&out->compr_mute_lock);
8525 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8526 (out->a2dp_compress_mute)) {
8527 out->a2dp_compress_mute = false;
8528 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8529 }
8530 pthread_mutex_unlock(&out->compr_mute_lock);
8531 }
8532 } else {
8533 // mute compress stream if suspended
8534 pthread_mutex_lock(&out->compr_mute_lock);
8535 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8536 (!out->a2dp_compress_mute)) {
8537 if (!out->standby) {
8538 ALOGD("%s: selecting speaker and muting stream", __func__);
8539 devices = out->devices;
8540 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8541 left_p = out->volume_l;
8542 right_p = out->volume_r;
8543 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8544 compress_pause(out->compr);
8545 out_set_compr_volume(&out->stream, (float)0, (float)0);
8546 out->a2dp_compress_mute = true;
8547 select_devices(adev, out->usecase);
8548 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8549 compress_resume(out->compr);
8550 out->devices = devices;
8551 out->volume_l = left_p;
8552 out->volume_r = right_p;
8553 }
8554 }
8555 pthread_mutex_unlock(&out->compr_mute_lock);
8556 }
8557 ALOGV("%s: exit", __func__);
8558 return 0;
8559}
8560
8561int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8562{
8563 int ret = 0;
8564
8565 lock_output_stream(out);
8566 pthread_mutex_lock(&adev->lock);
8567
8568 ret = check_a2dp_restore_l(adev, out, restore);
8569
8570 pthread_mutex_unlock(&adev->lock);
8571 pthread_mutex_unlock(&out->lock);
8572 return ret;
8573}
8574
Haynes Mathew George01156f92018-04-13 15:29:54 -07008575void adev_on_battery_status_changed(bool charging)
8576{
8577 pthread_mutex_lock(&adev->lock);
8578 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8579 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008580 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008581 pthread_mutex_unlock(&adev->lock);
8582}
8583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008584static int adev_open(const hw_module_t *module, const char *name,
8585 hw_device_t **device)
8586{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308587 int ret;
8588
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008589 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008590 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8591
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008592 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008593 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008594 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008595 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008596 ALOGD("%s: returning existing instance of adev", __func__);
8597 ALOGD("%s: exit", __func__);
8598 pthread_mutex_unlock(&adev_init_lock);
8599 return 0;
8600 }
8601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008602 adev = calloc(1, sizeof(struct audio_device));
8603
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008604 if (!adev) {
8605 pthread_mutex_unlock(&adev_init_lock);
8606 return -ENOMEM;
8607 }
8608
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008609 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8610
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008611 // register audio ext hidl at the earliest
8612 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308613#ifdef DYNAMIC_LOG_ENABLED
8614 register_for_dynamic_logging("hal");
8615#endif
8616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008617 adev->device.common.tag = HARDWARE_DEVICE_TAG;
8618 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
8619 adev->device.common.module = (struct hw_module_t *)module;
8620 adev->device.common.close = adev_close;
8621
8622 adev->device.init_check = adev_init_check;
8623 adev->device.set_voice_volume = adev_set_voice_volume;
8624 adev->device.set_master_volume = adev_set_master_volume;
8625 adev->device.get_master_volume = adev_get_master_volume;
8626 adev->device.set_master_mute = adev_set_master_mute;
8627 adev->device.get_master_mute = adev_get_master_mute;
8628 adev->device.set_mode = adev_set_mode;
8629 adev->device.set_mic_mute = adev_set_mic_mute;
8630 adev->device.get_mic_mute = adev_get_mic_mute;
8631 adev->device.set_parameters = adev_set_parameters;
8632 adev->device.get_parameters = adev_get_parameters;
8633 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8634 adev->device.open_output_stream = adev_open_output_stream;
8635 adev->device.close_output_stream = adev_close_output_stream;
8636 adev->device.open_input_stream = adev_open_input_stream;
8637 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308638 adev->device.create_audio_patch = adev_create_audio_patch;
8639 adev->device.release_audio_patch = adev_release_audio_patch;
8640 adev->device.get_audio_port = adev_get_audio_port;
8641 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008642 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308643 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008644
8645 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008646 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008647 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008648 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008649 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008650 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008651 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008652 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308653 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008654 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008655 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008656 /* Init audio feature manager */
8657 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008658 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008659 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008660 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008661 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308662 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308663 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308664 adev->perf_lock_opts[0] = 0x101;
8665 adev->perf_lock_opts[1] = 0x20E;
8666 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008667 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008669 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008670 adev->platform = platform_init(adev);
8671 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008672 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008673 free(adev->snd_dev_ref_cnt);
8674 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008675 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008676 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8677 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008678 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008679 return -EINVAL;
8680 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008681
Aalique Grahame22e49102018-12-18 14:23:57 -08008682 adev->extspk = audio_extn_extspk_init(adev);
8683
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308684 if (audio_extn_qaf_is_enabled()) {
8685 ret = audio_extn_qaf_init(adev);
8686 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008687 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308688 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008689 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308690 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8691 *device = NULL;
8692 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308693 return ret;
8694 }
8695
8696 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8697 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8698 }
8699
Derek Chenae7b0342019-02-08 15:17:04 -08008700 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08008701 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8702
Eric Laurentc4aef752013-09-12 17:45:53 -07008703 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8704 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8705 if (adev->visualizer_lib == NULL) {
8706 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8707 } else {
8708 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8709 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008710 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008711 "visualizer_hal_start_output");
8712 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008713 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008714 "visualizer_hal_stop_output");
8715 }
8716 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308717 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008718 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008719 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008720 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308721 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008722 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008723
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008724 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8725 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8726 if (adev->offload_effects_lib == NULL) {
8727 ALOGE("%s: DLOPEN failed for %s", __func__,
8728 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8729 } else {
8730 ALOGV("%s: DLOPEN successful for %s", __func__,
8731 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8732 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308733 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008734 "offload_effects_bundle_hal_start_output");
8735 adev->offload_effects_stop_output =
8736 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8737 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008738 adev->offload_effects_set_hpx_state =
8739 (int (*)(bool))dlsym(adev->offload_effects_lib,
8740 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308741 adev->offload_effects_get_parameters =
8742 (void (*)(struct str_parms *, struct str_parms *))
8743 dlsym(adev->offload_effects_lib,
8744 "offload_effects_bundle_get_parameters");
8745 adev->offload_effects_set_parameters =
8746 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8747 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008748 }
8749 }
8750
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008751 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8752 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8753 if (adev->adm_lib == NULL) {
8754 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8755 } else {
8756 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8757 adev->adm_init = (adm_init_t)
8758 dlsym(adev->adm_lib, "adm_init");
8759 adev->adm_deinit = (adm_deinit_t)
8760 dlsym(adev->adm_lib, "adm_deinit");
8761 adev->adm_register_input_stream = (adm_register_input_stream_t)
8762 dlsym(adev->adm_lib, "adm_register_input_stream");
8763 adev->adm_register_output_stream = (adm_register_output_stream_t)
8764 dlsym(adev->adm_lib, "adm_register_output_stream");
8765 adev->adm_deregister_stream = (adm_deregister_stream_t)
8766 dlsym(adev->adm_lib, "adm_deregister_stream");
8767 adev->adm_request_focus = (adm_request_focus_t)
8768 dlsym(adev->adm_lib, "adm_request_focus");
8769 adev->adm_abandon_focus = (adm_abandon_focus_t)
8770 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008771 adev->adm_set_config = (adm_set_config_t)
8772 dlsym(adev->adm_lib, "adm_set_config");
8773 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8774 dlsym(adev->adm_lib, "adm_request_focus_v2");
8775 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8776 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8777 adev->adm_on_routing_change = (adm_on_routing_change_t)
8778 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008779 }
8780 }
8781
Aalique Grahame22e49102018-12-18 14:23:57 -08008782 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008783 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008784 //initialize this to false for now,
8785 //this will be set to true through set param
8786 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008787
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008788 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008789 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08008790
8791 if (k_enable_extended_precision)
8792 adev_verify_devices(adev);
8793
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008794 adev->dsp_bit_width_enforce_mode =
8795 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008796
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308797 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8798 &adev->streams_output_cfg_list,
8799 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008800
Kiran Kandi910e1862013-10-29 13:29:42 -07008801 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008802
8803 char value[PROPERTY_VALUE_MAX];
8804 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08008805 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
8806 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008807 trial = atoi(value);
8808 if (period_size_is_plausible_for_low_latency(trial)) {
8809 pcm_config_low_latency.period_size = trial;
8810 pcm_config_low_latency.start_threshold = trial / 4;
8811 pcm_config_low_latency.avail_min = trial / 4;
8812 configured_low_latency_capture_period_size = trial;
8813 }
8814 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008815 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
8816 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008817 trial = atoi(value);
8818 if (period_size_is_plausible_for_low_latency(trial)) {
8819 configured_low_latency_capture_period_size = trial;
8820 }
8821 }
8822
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008823 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8824
Aalique Grahame22e49102018-12-18 14:23:57 -08008825 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
8826 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008827 af_period_multiplier = atoi(value);
8828 if (af_period_multiplier < 0)
8829 af_period_multiplier = 2;
8830 else if (af_period_multiplier > 4)
8831 af_period_multiplier = 4;
8832
8833 ALOGV("new period_multiplier = %d", af_period_multiplier);
8834 }
8835
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008836 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008837
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008838 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008839 pthread_mutex_unlock(&adev_init_lock);
8840
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008841 if (adev->adm_init)
8842 adev->adm_data = adev->adm_init();
8843
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308844 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308845 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008846 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308847
8848 audio_extn_snd_mon_init();
8849 pthread_mutex_lock(&adev->lock);
8850 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8851 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008852 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8853 /*
8854 * if the battery state callback happens before charging can be queried,
8855 * it will be guarded with the adev->lock held in the cb function and so
8856 * the callback value will reflect the latest state
8857 */
8858 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308859 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008860 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8861 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308862 /* Allocate memory for Device config params */
8863 adev->device_cfg_params = (struct audio_device_config_param*)
8864 calloc(platform_get_max_codec_backend(),
8865 sizeof(struct audio_device_config_param));
8866 if (adev->device_cfg_params == NULL)
8867 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308868
Eric Laurent994a6932013-07-17 11:51:42 -07008869 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008870 return 0;
8871}
8872
8873static struct hw_module_methods_t hal_module_methods = {
8874 .open = adev_open,
8875};
8876
8877struct audio_module HAL_MODULE_INFO_SYM = {
8878 .common = {
8879 .tag = HARDWARE_MODULE_TAG,
8880 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8881 .hal_api_version = HARDWARE_HAL_API_VERSION,
8882 .id = AUDIO_HARDWARE_MODULE_ID,
8883 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008884 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885 .methods = &hal_module_methods,
8886 },
8887};