blob: c53fa31390fe814bd9d751e0170ba7e1120826fe [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"
justinweng20fb6d82019-02-21 18:49:00 -070078#include "audio_extn/audiozoom.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097
Aalique Grahame22e49102018-12-18 14:23:57 -080098#define RECORD_GAIN_MIN 0.0f
99#define RECORD_GAIN_MAX 1.0f
100#define RECORD_VOLUME_CTL_MAX 0x2000
101
102/* treat as unsigned Q1.13 */
103#define APP_TYPE_GAIN_DEFAULT 0x2000
104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700105#define PROXY_OPEN_RETRY_COUNT 100
106#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800108#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
109 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
110 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
111#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
112 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800113
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700114#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700115#define DEFAULT_VOIP_BUF_DURATION_MS 20
116#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
117#define DEFAULT_VOIP_SAMP_RATE 48000
118
119#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
120
121struct pcm_config default_pcm_config_voip_copp = {
122 .channels = 1,
123 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
124 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
125 .period_count = 2,
126 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800127 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
128 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700129};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700130
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700131#define MIN_CHANNEL_COUNT 1
132#define DEFAULT_CHANNEL_COUNT 2
133#define MAX_HIFI_CHANNEL_COUNT 8
134
Aalique Grahame22e49102018-12-18 14:23:57 -0800135#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
136#define MAX_CHANNEL_COUNT 1
137#else
138#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
139#define XSTR(x) STR(x)
140#define STR(x) #x
141#endif
142
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700143static unsigned int configured_low_latency_capture_period_size =
144 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
145
Haynes Mathew George16081042017-05-31 17:16:49 -0700146#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
147#define MMAP_PERIOD_COUNT_MIN 32
148#define MMAP_PERIOD_COUNT_MAX 512
149#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
150
Aalique Grahame22e49102018-12-18 14:23:57 -0800151/* This constant enables extended precision handling.
152 * TODO The flag is off until more testing is done.
153 */
154static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700155extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800156
Eric Laurentb23d5282013-05-14 15:27:20 -0700157struct pcm_config pcm_config_deep_buffer = {
158 .channels = 2,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
161 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
164 .stop_threshold = INT_MAX,
165 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166};
167
168struct pcm_config pcm_config_low_latency = {
169 .channels = 2,
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
171 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
172 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
175 .stop_threshold = INT_MAX,
176 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177};
178
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800179struct pcm_config pcm_config_haptics_audio = {
180 .channels = 1,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
183 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_haptics = {
191 .channels = 1,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700201static int af_period_multiplier = 4;
202struct pcm_config pcm_config_rt = {
203 .channels = 2,
204 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
205 .period_size = ULL_PERIOD_SIZE, //1 ms
206 .period_count = 512, //=> buffer size is 512ms
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
209 .stop_threshold = INT_MAX,
210 .silence_threshold = 0,
211 .silence_size = 0,
212 .avail_min = ULL_PERIOD_SIZE, //1 ms
213};
214
Eric Laurentb23d5282013-05-14 15:27:20 -0700215struct pcm_config pcm_config_hdmi_multi = {
216 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
218 .period_size = HDMI_MULTI_PERIOD_SIZE,
219 .period_count = HDMI_MULTI_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = 0,
222 .stop_threshold = INT_MAX,
223 .avail_min = 0,
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_playback = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = MMAP_PERIOD_SIZE*8,
233 .stop_threshold = INT32_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700239struct pcm_config pcm_config_hifi = {
240 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
241 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
242 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
243 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
244 .format = PCM_FORMAT_S24_3LE,
245 .start_threshold = 0,
246 .stop_threshold = INT_MAX,
247 .avail_min = 0,
248};
249
Eric Laurentb23d5282013-05-14 15:27:20 -0700250struct pcm_config pcm_config_audio_capture = {
251 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
253 .format = PCM_FORMAT_S16_LE,
254};
255
Haynes Mathew George16081042017-05-31 17:16:49 -0700256struct pcm_config pcm_config_mmap_capture = {
257 .channels = 2,
258 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
259 .period_size = MMAP_PERIOD_SIZE,
260 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
261 .format = PCM_FORMAT_S16_LE,
262 .start_threshold = 0,
263 .stop_threshold = INT_MAX,
264 .silence_threshold = 0,
265 .silence_size = 0,
266 .avail_min = MMAP_PERIOD_SIZE, //1 ms
267};
268
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700269#define AFE_PROXY_CHANNEL_COUNT 2
270#define AFE_PROXY_SAMPLING_RATE 48000
271
272#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
273#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
274
275struct pcm_config pcm_config_afe_proxy_playback = {
276 .channels = AFE_PROXY_CHANNEL_COUNT,
277 .rate = AFE_PROXY_SAMPLING_RATE,
278 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
279 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
280 .format = PCM_FORMAT_S16_LE,
281 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
282 .stop_threshold = INT_MAX,
283 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284};
285
286#define AFE_PROXY_RECORD_PERIOD_SIZE 768
287#define AFE_PROXY_RECORD_PERIOD_COUNT 4
288
Aalique Grahame22e49102018-12-18 14:23:57 -0800289struct pcm_config pcm_config_audio_capture_rt = {
290 .channels = 2,
291 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
292 .period_size = ULL_PERIOD_SIZE,
293 .period_count = 512,
294 .format = PCM_FORMAT_S16_LE,
295 .start_threshold = 0,
296 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
297 .silence_threshold = 0,
298 .silence_size = 0,
299 .avail_min = ULL_PERIOD_SIZE, //1 ms
300};
301
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700302struct pcm_config pcm_config_afe_proxy_record = {
303 .channels = AFE_PROXY_CHANNEL_COUNT,
304 .rate = AFE_PROXY_SAMPLING_RATE,
305 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
306 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
307 .format = PCM_FORMAT_S16_LE,
308 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
309 .stop_threshold = INT_MAX,
310 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
311};
312
Ashish Jainf1eaa582016-05-23 20:54:24 +0530313#define AUDIO_MAX_PCM_FORMATS 7
314
315const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
316 [AUDIO_FORMAT_DEFAULT] = 0,
317 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
318 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
319 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
322 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
323};
324
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800325const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
327 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800328 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700329 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
330 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700331 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700332 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700341 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
342 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700343 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800344 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700345
Eric Laurentb23d5282013-05-14 15:27:20 -0700346 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700347 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530348 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
349 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
350 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530351 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
352 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700353 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700354 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700355 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700356 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800358 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800359 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700360 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700361
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 [USECASE_VOICE2_CALL] = "voice2-call",
363 [USECASE_VOLTE_CALL] = "volte-call",
364 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800365 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800366 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
367 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800368 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700369 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
370 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
371 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800372 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
373 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
375
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700376 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
377 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
379 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700380
381 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
382 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530383 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700384
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530385 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
387 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
389 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
390 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530391 /* For Interactive Audio Streams */
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700400
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800401 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
402
403 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700404};
405
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700406static const audio_usecase_t offload_usecases[] = {
407 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700408 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700416};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800417
Varun Balaraje49253e2017-07-06 19:48:56 +0530418static const audio_usecase_t interactive_usecases[] = {
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
427};
428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429#define STRING_TO_ENUM(string) { #string, string }
430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431struct string_to_enum {
432 const char *name;
433 uint32_t value;
434};
435
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700436static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700445 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
446 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
447 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456};
457
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700458static const struct string_to_enum formats_name_to_enum_table[] = {
459 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
460 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
461 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700462 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
463 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
464 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700465 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800466 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
467 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700468 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800469};
470
471//list of all supported sample rates by HDMI specification.
472static const int out_hdmi_sample_rates[] = {
473 32000, 44100, 48000, 88200, 96000, 176400, 192000,
474};
475
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700476static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800477 STRING_TO_ENUM(32000),
478 STRING_TO_ENUM(44100),
479 STRING_TO_ENUM(48000),
480 STRING_TO_ENUM(88200),
481 STRING_TO_ENUM(96000),
482 STRING_TO_ENUM(176400),
483 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700484};
485
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700486static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700487static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700488static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700489//cache last MBDRC cal step level
490static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700491
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530492static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
493static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700494static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800495static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530496static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530497
Vatsal Buchac09ae062018-11-14 13:25:08 +0530498#ifdef AUDIO_FEATURE_ENABLED_GCOV
499extern void __gcov_flush();
500static void enable_gcov()
501{
502 __gcov_flush();
503}
504#else
505static void enable_gcov()
506{
507}
508#endif
509
justinweng20fb6d82019-02-21 18:49:00 -0700510static int in_set_microphone_direction(const struct audio_stream_in *stream,
511 audio_microphone_direction_t dir);
512static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
513
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
516 int flags __unused)
517{
518 int dir = 0;
519 switch (uc_id) {
520 case USECASE_AUDIO_RECORD_LOW_LATENCY:
521 dir = 1;
522 case USECASE_AUDIO_PLAYBACK_ULL:
523 break;
524 default:
525 return false;
526 }
527
528 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
529 PCM_PLAYBACK : PCM_CAPTURE);
530 if (adev->adm_is_noirq_avail)
531 return adev->adm_is_noirq_avail(adev->adm_data,
532 adev->snd_card, dev_id, dir);
533 return false;
534}
535
536static void register_out_stream(struct stream_out *out)
537{
538 struct audio_device *adev = out->dev;
539 if (is_offload_usecase(out->usecase) ||
540 !adev->adm_register_output_stream)
541 return;
542
543 // register stream first for backward compatibility
544 adev->adm_register_output_stream(adev->adm_data,
545 out->handle,
546 out->flags);
547
548 if (!adev->adm_set_config)
549 return;
550
551 if (out->realtime)
552 adev->adm_set_config(adev->adm_data,
553 out->handle,
554 out->pcm, &out->config);
555}
556
557static void register_in_stream(struct stream_in *in)
558{
559 struct audio_device *adev = in->dev;
560 if (!adev->adm_register_input_stream)
561 return;
562
563 adev->adm_register_input_stream(adev->adm_data,
564 in->capture_handle,
565 in->flags);
566
567 if (!adev->adm_set_config)
568 return;
569
570 if (in->realtime)
571 adev->adm_set_config(adev->adm_data,
572 in->capture_handle,
573 in->pcm,
574 &in->config);
575}
576
577static void request_out_focus(struct stream_out *out, long ns)
578{
579 struct audio_device *adev = out->dev;
580
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700581 if (adev->adm_request_focus_v2)
582 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
583 else if (adev->adm_request_focus)
584 adev->adm_request_focus(adev->adm_data, out->handle);
585}
586
587static void request_in_focus(struct stream_in *in, long ns)
588{
589 struct audio_device *adev = in->dev;
590
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700591 if (adev->adm_request_focus_v2)
592 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
593 else if (adev->adm_request_focus)
594 adev->adm_request_focus(adev->adm_data, in->capture_handle);
595}
596
597static void release_out_focus(struct stream_out *out)
598{
599 struct audio_device *adev = out->dev;
600
601 if (adev->adm_abandon_focus)
602 adev->adm_abandon_focus(adev->adm_data, out->handle);
603}
604
605static void release_in_focus(struct stream_in *in)
606{
607 struct audio_device *adev = in->dev;
608 if (adev->adm_abandon_focus)
609 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
610}
611
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530612static int parse_snd_card_status(struct str_parms *parms, int *card,
613 card_status_t *status)
614{
615 char value[32]={0};
616 char state[32]={0};
617
618 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
619 if (ret < 0)
620 return -1;
621
622 // sscanf should be okay as value is of max length 32.
623 // same as sizeof state.
624 if (sscanf(value, "%d,%s", card, state) < 2)
625 return -1;
626
627 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
628 CARD_STATUS_OFFLINE;
629 return 0;
630}
631
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700632static inline void adjust_frames_for_device_delay(struct stream_out *out,
633 uint32_t *dsp_frames) {
634 // Adjustment accounts for A2dp encoder latency with offload usecases
635 // Note: Encoder latency is returned in ms.
636 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
637 unsigned long offset =
638 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
639 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
640 }
641}
642
vivek mehtaa76401a2015-04-24 14:12:15 -0700643__attribute__ ((visibility ("default")))
644bool audio_hw_send_gain_dep_calibration(int level) {
645 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700646 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700647
648 pthread_mutex_lock(&adev_init_lock);
649
650 if (adev != NULL && adev->platform != NULL) {
651 pthread_mutex_lock(&adev->lock);
652 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700653
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530654 // cache level info for any of the use case which
655 // was not started.
656 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700657
vivek mehtaa76401a2015-04-24 14:12:15 -0700658 pthread_mutex_unlock(&adev->lock);
659 } else {
660 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
661 }
662
663 pthread_mutex_unlock(&adev_init_lock);
664
665 return ret_val;
666}
667
Ashish Jain5106d362016-05-11 19:23:33 +0530668static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
669{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800670 bool gapless_enabled = false;
671 const char *mixer_ctl_name = "Compress Gapless Playback";
672 struct mixer_ctl *ctl;
673
674 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700675 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530676
677 /*Disable gapless if its AV playback*/
678 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800679
680 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
681 if (!ctl) {
682 ALOGE("%s: Could not get ctl for mixer cmd - %s",
683 __func__, mixer_ctl_name);
684 return -EINVAL;
685 }
686
687 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
688 ALOGE("%s: Could not set gapless mode %d",
689 __func__, gapless_enabled);
690 return -EINVAL;
691 }
692 return 0;
693}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700694
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700695__attribute__ ((visibility ("default")))
696int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
697 int table_size) {
698 int ret_val = 0;
699 ALOGV("%s: enter ... ", __func__);
700
701 pthread_mutex_lock(&adev_init_lock);
702 if (adev == NULL) {
703 ALOGW("%s: adev is NULL .... ", __func__);
704 goto done;
705 }
706
707 pthread_mutex_lock(&adev->lock);
708 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
709 pthread_mutex_unlock(&adev->lock);
710done:
711 pthread_mutex_unlock(&adev_init_lock);
712 ALOGV("%s: exit ... ", __func__);
713 return ret_val;
714}
715
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800716bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800717{
718 bool ret = false;
719 ALOGV("%s: enter ...", __func__);
720
721 pthread_mutex_lock(&adev_init_lock);
722
723 if (adev != NULL && adev->platform != NULL) {
724 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800725 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800726 pthread_mutex_unlock(&adev->lock);
727 }
728
729 pthread_mutex_unlock(&adev_init_lock);
730
731 ALOGV("%s: exit with ret %d", __func__, ret);
732 return ret;
733}
Aalique Grahame22e49102018-12-18 14:23:57 -0800734
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700735static bool is_supported_format(audio_format_t format)
736{
Eric Laurent86e17132013-09-12 17:49:30 -0700737 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530738 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530739 format == AUDIO_FORMAT_AAC_LC ||
740 format == AUDIO_FORMAT_AAC_HE_V1 ||
741 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530742 format == AUDIO_FORMAT_AAC_ADTS_LC ||
743 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
744 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530745 format == AUDIO_FORMAT_AAC_LATM_LC ||
746 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
747 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530748 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
749 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530750 format == AUDIO_FORMAT_PCM_FLOAT ||
751 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700752 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530753 format == AUDIO_FORMAT_AC3 ||
754 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700755 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530756 format == AUDIO_FORMAT_DTS ||
757 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800758 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530759 format == AUDIO_FORMAT_ALAC ||
760 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530761 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530762 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800763 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530764 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700765 format == AUDIO_FORMAT_APTX ||
766 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800767 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700768
769 return false;
770}
771
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700772static inline bool is_mmap_usecase(audio_usecase_t uc_id)
773{
774 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
775 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
776}
777
Avinash Vaish71a8b972014-07-24 15:36:33 +0530778static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
779 struct audio_usecase *uc_info)
780{
781 struct listnode *node;
782 struct audio_usecase *usecase;
783
784 if (uc_info == NULL)
785 return -EINVAL;
786
787 /* Re-route all voice usecases on the shared backend other than the
788 specified usecase to new snd devices */
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800791 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530792 enable_audio_route(adev, usecase);
793 }
794 return 0;
795}
796
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530797static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530798{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530799 ALOGV("%s", __func__);
800 audio_route_apply_and_update_path(adev->audio_route,
801 "asrc-mode");
802 adev->asrc_mode_enabled = true;
803}
804
805static void disable_asrc_mode(struct audio_device *adev)
806{
807 ALOGV("%s", __func__);
808 audio_route_reset_and_update_path(adev->audio_route,
809 "asrc-mode");
810 adev->asrc_mode_enabled = false;
811}
812
813/*
814 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
815 * 44.1 or Native DSD backends are enabled for any of current use case.
816 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
817 * - Disable current mix path use case(Headphone backend) and re-enable it with
818 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
819 * e.g. Naitve DSD or Headphone 44.1 -> + 48
820 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530821static void check_and_set_asrc_mode(struct audio_device *adev,
822 struct audio_usecase *uc_info,
823 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530824{
825 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530826 int i, num_new_devices = 0;
827 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
828 /*
829 *Split snd device for new combo use case
830 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
831 */
832 if (platform_split_snd_device(adev->platform,
833 snd_device,
834 &num_new_devices,
835 split_new_snd_devices) == 0) {
836 for (i = 0; i < num_new_devices; i++)
837 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
838 } else {
839 int new_backend_idx = platform_get_backend_index(snd_device);
840 if (((new_backend_idx == HEADPHONE_BACKEND) ||
841 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
842 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
843 !adev->asrc_mode_enabled) {
844 struct listnode *node = NULL;
845 struct audio_usecase *uc = NULL;
846 struct stream_out *curr_out = NULL;
847 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
848 int i, num_devices, ret = 0;
849 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530850
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530851 list_for_each(node, &adev->usecase_list) {
852 uc = node_to_item(node, struct audio_usecase, list);
853 curr_out = (struct stream_out*) uc->stream.out;
854 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
855 /*
856 *Split snd device for existing combo use case
857 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
858 */
859 ret = platform_split_snd_device(adev->platform,
860 uc->out_snd_device,
861 &num_devices,
862 split_snd_devices);
863 if (ret < 0 || num_devices == 0) {
864 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
865 split_snd_devices[0] = uc->out_snd_device;
866 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800867 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530868 for (i = 0; i < num_devices; i++) {
869 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
870 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
871 if((new_backend_idx == HEADPHONE_BACKEND) &&
872 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
873 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
874 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
875 __func__);
876 enable_asrc_mode(adev);
877 break;
878 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
879 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
880 (usecase_backend_idx == HEADPHONE_BACKEND)) {
881 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
882 __func__);
883 disable_audio_route(adev, uc);
884 disable_snd_device(adev, uc->out_snd_device);
885 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
886 if (new_backend_idx == DSD_NATIVE_BACKEND)
887 audio_route_apply_and_update_path(adev->audio_route,
888 "hph-true-highquality-mode");
889 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
890 (curr_out->bit_width >= 24))
891 audio_route_apply_and_update_path(adev->audio_route,
892 "hph-highquality-mode");
893 enable_asrc_mode(adev);
894 enable_snd_device(adev, uc->out_snd_device);
895 enable_audio_route(adev, uc);
896 break;
897 }
898 }
899 // reset split devices count
900 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800901 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530902 if (adev->asrc_mode_enabled)
903 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530904 }
905 }
906 }
907}
908
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700909static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
910 struct audio_effect_config effect_config,
911 unsigned int param_value)
912{
913 char mixer_ctl_name[] = "Audio Effect";
914 struct mixer_ctl *ctl;
915 long set_values[6];
916 struct stream_in *in = adev->active_input;
917
918 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
919 if (!ctl) {
920 ALOGE("%s: Could not get mixer ctl - %s",
921 __func__, mixer_ctl_name);
922 return -EINVAL;
923 }
924
925 set_values[0] = 1; //0:Rx 1:Tx
926 set_values[1] = in->app_type_cfg.app_type;
927 set_values[2] = (long)effect_config.module_id;
928 set_values[3] = (long)effect_config.instance_id;
929 set_values[4] = (long)effect_config.param_id;
930 set_values[5] = param_value;
931
932 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
933
934 return 0;
935
936}
937
938static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
939 int effect_type, unsigned int *param_value)
940{
941 int ret = 0;
942 struct audio_effect_config other_effect_config;
943 struct audio_usecase *usecase = NULL;
944 struct stream_in *in = adev->active_input;
945
946 usecase = get_usecase_from_list(adev, in->usecase);
947 if (!usecase)
948 return -EINVAL;
949
950 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
951 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
952 if (ret < 0) {
953 ALOGE("%s Failed to get effect params %d", __func__, ret);
954 return ret;
955 }
956
957 if (module_id == other_effect_config.module_id) {
958 //Same module id for AEC/NS. Values need to be combined
959 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
960 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
961 *param_value |= other_effect_config.param_value;
962 }
963 }
964
965 return ret;
966}
967
968static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800969{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700970 struct audio_effect_config effect_config;
971 struct audio_usecase *usecase = NULL;
972 int ret = 0;
973 unsigned int param_value = 0;
974 struct stream_in *in = adev->active_input;
975
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800976 if(!voice_extn_is_dynamic_ecns_enabled())
977 return ENOSYS;
978
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700979 if (!in) {
980 ALOGE("%s: Invalid input stream", __func__);
981 return -EINVAL;
982 }
983
984 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
985
986 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800987 if (usecase == NULL) {
988 ALOGE("%s: Could not find the usecase (%d) in the list",
989 __func__, in->usecase);
990 return -EINVAL;
991 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700992
993 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
994 if (ret < 0) {
995 ALOGE("%s Failed to get module id %d", __func__, ret);
996 return ret;
997 }
998 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
999 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1000
1001 if(enable)
1002 param_value = effect_config.param_value;
1003
1004 /*Special handling for AEC & NS effects Param values need to be
1005 updated if module ids are same*/
1006
1007 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1008 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1009 if (ret < 0)
1010 return ret;
1011 }
1012
1013 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1014
1015 return ret;
1016}
1017
1018static void check_and_enable_effect(struct audio_device *adev)
1019{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001020 if(!voice_extn_is_dynamic_ecns_enabled())
1021 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001022
1023 if (adev->active_input->enable_aec) {
1024 enable_disable_effect(adev, EFFECT_AEC, true);
1025 }
1026
1027 if (adev->active_input->enable_ns &&
1028 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1029 enable_disable_effect(adev, EFFECT_NS, true);
1030 }
1031}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001033int pcm_ioctl(struct pcm *pcm, int request, ...)
1034{
1035 va_list ap;
1036 void * arg;
1037 int pcm_fd = *(int*)pcm;
1038
1039 va_start(ap, request);
1040 arg = va_arg(ap, void *);
1041 va_end(ap);
1042
1043 return ioctl(pcm_fd, request, arg);
1044}
1045
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001046int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001047 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001050 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301051 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301052 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001053
1054 if (usecase == NULL)
1055 return -EINVAL;
1056
1057 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1058
Surendar Karka93cd25a2018-08-28 14:21:37 +05301059 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001061 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001063
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001064#ifdef DS1_DOLBY_DAP_ENABLED
1065 audio_extn_dolby_set_dmid(adev);
1066 audio_extn_dolby_set_endpoint(adev);
1067#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001068 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001069 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301070 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001071 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301072 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301073 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1074 out = usecase->stream.out;
1075 if (out && out->compr)
1076 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1077 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301078 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301079
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001080 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001081 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001082 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301083 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1084 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1085 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1086 if (parms) {
1087 audio_extn_fm_set_parameters(adev, parms);
1088 str_parms_destroy(parms);
1089 }
1090 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 ALOGV("%s: exit", __func__);
1092 return 0;
1093}
1094
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001095int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001096 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001099 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001100
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301101 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001102 return -EINVAL;
1103
1104 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301105 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001106 snd_device = usecase->in_snd_device;
1107 else
1108 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001109 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001110 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001111 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001112 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001113 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301114 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301115 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301116 if (usecase->stream.out != NULL)
1117 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118 ALOGV("%s: exit", __func__);
1119 return 0;
1120}
1121
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001122int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001123 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301125 int i, num_devices = 0;
1126 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001127 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1128
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129 if (snd_device < SND_DEVICE_MIN ||
1130 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001131 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001132 return -EINVAL;
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001135 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001136 ALOGE("%s: Invalid sound device returned", __func__);
1137 return -EINVAL;
1138 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001139
1140 adev->snd_dev_ref_cnt[snd_device]++;
1141
1142 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1143 (platform_split_snd_device(adev->platform,
1144 snd_device,
1145 &num_devices,
1146 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001147 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001148 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 return 0;
1150 }
1151
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001152 if (audio_extn_spkr_prot_is_enabled())
1153 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001154
Aalique Grahame22e49102018-12-18 14:23:57 -08001155 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1156
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001157 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1158 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001159 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1160 goto err;
1161 }
1162 audio_extn_dev_arbi_acquire(snd_device);
1163 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001164 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001165 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001166 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001167 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001168 } else if (platform_split_snd_device(adev->platform,
1169 snd_device,
1170 &num_devices,
1171 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301172 for (i = 0; i < num_devices; i++) {
1173 enable_snd_device(adev, new_snd_devices[i]);
1174 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001175 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001176 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001177 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301178
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301179
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001180 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1181 (audio_extn_a2dp_start_playback() < 0)) {
1182 ALOGE(" fail to configure A2dp Source control path ");
1183 goto err;
1184 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001185
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001186 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1187 (audio_extn_a2dp_start_capture() < 0)) {
1188 ALOGE(" fail to configure A2dp Sink control path ");
1189 goto err;
1190 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301191
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001192 /* due to the possibility of calibration overwrite between listen
1193 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001194 audio_extn_sound_trigger_update_device_status(snd_device,
1195 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301196 audio_extn_listen_update_device_status(snd_device,
1197 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001198 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001199 audio_extn_sound_trigger_update_device_status(snd_device,
1200 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301201 audio_extn_listen_update_device_status(snd_device,
1202 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001203 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001204 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001205 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001206 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301207
1208 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1209 !adev->native_playback_enabled &&
1210 audio_is_true_native_stream_active(adev)) {
1211 ALOGD("%s: %d: napb: enabling native mode in hardware",
1212 __func__, __LINE__);
1213 audio_route_apply_and_update_path(adev->audio_route,
1214 "true-native-mode");
1215 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301216 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301217 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1218 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001219 (audio_extn_ffv_get_stream() == adev->active_input)) {
1220 ALOGD("%s: init ec ref loopback", __func__);
1221 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001225err:
1226 adev->snd_dev_ref_cnt[snd_device]--;
1227 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228}
1229
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001230int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001231 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301233 int i, num_devices = 0;
1234 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001235 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1236
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001237 if (snd_device < SND_DEVICE_MIN ||
1238 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001239 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001240 return -EINVAL;
1241 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001242
1243 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1244 ALOGE("%s: Invalid sound device returned", __func__);
1245 return -EINVAL;
1246 }
1247
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001248 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1249 ALOGE("%s: device ref cnt is already 0", __func__);
1250 return -EINVAL;
1251 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001252
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001253 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001254
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001255
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001257 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301258
Aalique Grahame22e49102018-12-18 14:23:57 -08001259 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1260
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001261 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1262 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001263 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001264
1265 // when speaker device is disabled, reset swap.
1266 // will be renabled on usecase start
1267 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001268 } else if (platform_split_snd_device(adev->platform,
1269 snd_device,
1270 &num_devices,
1271 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301272 for (i = 0; i < num_devices; i++) {
1273 disable_snd_device(adev, new_snd_devices[i]);
1274 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001275 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001276 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001277 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001278 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001279
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001280 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301281 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001282 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001283 audio_extn_a2dp_stop_capture();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001284 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
1285 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301286 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001287 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301288 adev->native_playback_enabled) {
1289 ALOGD("%s: %d: napb: disabling native mode in hardware",
1290 __func__, __LINE__);
1291 audio_route_reset_and_update_path(adev->audio_route,
1292 "true-native-mode");
1293 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001294 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301295 adev->asrc_mode_enabled) {
1296 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301297 disable_asrc_mode(adev);
1298 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001299 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301300 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001301 (audio_extn_ffv_get_stream() == adev->active_input)) {
1302 ALOGD("%s: deinit ec ref loopback", __func__);
1303 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1304 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001305
1306 audio_extn_utils_release_snd_device(snd_device);
1307 } else {
1308 if (platform_split_snd_device(adev->platform,
1309 snd_device,
1310 &num_devices,
1311 new_snd_devices) == 0) {
1312 for (i = 0; i < num_devices; i++) {
1313 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1314 }
1315 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 return 0;
1319}
1320
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001321/*
1322 legend:
1323 uc - existing usecase
1324 new_uc - new usecase
1325 d1, d11, d2 - SND_DEVICE enums
1326 a1, a2 - corresponding ANDROID device enums
1327 B1, B2 - backend strings
1328
1329case 1
1330 uc->dev d1 (a1) B1
1331 new_uc->dev d1 (a1), d2 (a2) B1, B2
1332
1333 resolution: disable and enable uc->dev on d1
1334
1335case 2
1336 uc->dev d1 (a1) B1
1337 new_uc->dev d11 (a1) B1
1338
1339 resolution: need to switch uc since d1 and d11 are related
1340 (e.g. speaker and voice-speaker)
1341 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1342
1343case 3
1344 uc->dev d1 (a1) B1
1345 new_uc->dev d2 (a2) B2
1346
1347 resolution: no need to switch uc
1348
1349case 4
1350 uc->dev d1 (a1) B1
1351 new_uc->dev d2 (a2) B1
1352
1353 resolution: disable enable uc-dev on d2 since backends match
1354 we cannot enable two streams on two different devices if they
1355 share the same backend. e.g. if offload is on speaker device using
1356 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1357 using the same backend, offload must also be switched to voice-handset.
1358
1359case 5
1360 uc->dev d1 (a1) B1
1361 new_uc->dev d1 (a1), d2 (a2) B1
1362
1363 resolution: disable enable uc-dev on d2 since backends match
1364 we cannot enable two streams on two different devices if they
1365 share the same backend.
1366
1367case 6
1368 uc->dev d1 (a1) B1
1369 new_uc->dev d2 (a1) B2
1370
1371 resolution: no need to switch
1372
1373case 7
1374 uc->dev d1 (a1), d2 (a2) B1, B2
1375 new_uc->dev d1 (a1) B1
1376
1377 resolution: no need to switch
1378
Zhou Song4ba65882018-07-09 14:48:07 +08001379case 8
1380 uc->dev d1 (a1) B1
1381 new_uc->dev d11 (a1), d2 (a2) B1, B2
1382 resolution: compared to case 1, for this case, d1 and d11 are related
1383 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001384*/
1385static snd_device_t derive_playback_snd_device(void * platform,
1386 struct audio_usecase *uc,
1387 struct audio_usecase *new_uc,
1388 snd_device_t new_snd_device)
1389{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301390 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001391
1392 snd_device_t d1 = uc->out_snd_device;
1393 snd_device_t d2 = new_snd_device;
1394
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301395 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301396 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301397 a1 = uc->stream.inout->out_config.devices;
1398 a2 = new_uc->stream.inout->out_config.devices;
1399 break;
1400 default :
1401 a1 = uc->stream.out->devices;
1402 a2 = new_uc->stream.out->devices;
1403 break;
1404 }
1405
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001406 // Treat as a special case when a1 and a2 are not disjoint
1407 if ((a1 != a2) && (a1 & a2)) {
1408 snd_device_t d3[2];
1409 int num_devices = 0;
1410 int ret = platform_split_snd_device(platform,
1411 popcount(a1) > 1 ? d1 : d2,
1412 &num_devices,
1413 d3);
1414 if (ret < 0) {
1415 if (ret != -ENOSYS) {
1416 ALOGW("%s failed to split snd_device %d",
1417 __func__,
1418 popcount(a1) > 1 ? d1 : d2);
1419 }
1420 goto end;
1421 }
1422
1423 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1424 // But if it does happen, we need to give priority to d2 if
1425 // the combo devices active on the existing usecase share a backend.
1426 // This is because we cannot have a usecase active on a combo device
1427 // and a new usecase requests one device in this combo pair.
1428 if (platform_check_backends_match(d3[0], d3[1])) {
1429 return d2; // case 5
1430 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001431 // check if d1 is related to any of d3's
1432 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001433 return d1; // case 1
1434 else
1435 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001436 }
1437 } else {
1438 if (platform_check_backends_match(d1, d2)) {
1439 return d2; // case 2, 4
1440 } else {
1441 return d1; // case 6, 3
1442 }
1443 }
1444
1445end:
1446 return d2; // return whatever was calculated before.
1447}
1448
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301450 struct audio_usecase *uc_info,
1451 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452{
1453 struct listnode *node;
1454 struct audio_usecase *usecase;
1455 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301456 snd_device_t uc_derive_snd_device;
1457 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001458 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1459 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001460 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301461 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 /*
1463 * This function is to make sure that all the usecases that are active on
1464 * the hardware codec backend are always routed to any one device that is
1465 * handled by the hardware codec.
1466 * For example, if low-latency and deep-buffer usecases are currently active
1467 * on speaker and out_set_parameters(headset) is received on low-latency
1468 * output, then we have to make sure deep-buffer is also switched to headset,
1469 * because of the limitation that both the devices cannot be enabled
1470 * at the same time as they share the same backend.
1471 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001472 /*
1473 * This call is to check if we need to force routing for a particular stream
1474 * If there is a backend configuration change for the device when a
1475 * new stream starts, then ADM needs to be closed and re-opened with the new
1476 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001477 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001478 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001479 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1480 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301481 /* For a2dp device reconfigure all active sessions
1482 * with new AFE encoder format based on a2dp state
1483 */
1484 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1485 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1486 audio_extn_a2dp_is_force_device_switch()) {
1487 force_routing = true;
1488 force_restart_session = true;
1489 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301490 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1491
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001493 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001494 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1496 switch_device[i] = false;
1497
1498 list_for_each(node, &adev->usecase_list) {
1499 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001500
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301501 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1502 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301503 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301504 platform_get_snd_device_name(usecase->out_snd_device),
1505 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301506 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1507 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1508 usecase, uc_info, snd_device);
1509 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1510 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1511 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1512 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001513 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301514 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1515 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1516 ((force_restart_session) ||
1517 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301518 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1519 __func__, use_case_table[usecase->id],
1520 platform_get_snd_device_name(usecase->out_snd_device));
1521 disable_audio_route(adev, usecase);
1522 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301523 /* Enable existing usecase on derived playback device */
1524 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301525 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 }
1528 }
1529
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301530 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1531 num_uc_to_switch);
1532
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001533 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001534 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301536 /* Make sure the previous devices to be disabled first and then enable the
1537 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 list_for_each(node, &adev->usecase_list) {
1539 usecase = node_to_item(node, struct audio_usecase, list);
1540 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001541 /* Check if output sound device to be switched can be split and if any
1542 of the split devices match with derived sound device */
1543 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1544 &num_devices, split_snd_devices) == 0) {
1545 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1546 for (i = 0; i < num_devices; i++) {
1547 /* Disable devices that do not match with derived sound device */
1548 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1549 disable_snd_device(adev, split_snd_devices[i]);
1550 }
1551 } else {
1552 disable_snd_device(adev, usecase->out_snd_device);
1553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 }
1555 }
1556
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001557 list_for_each(node, &adev->usecase_list) {
1558 usecase = node_to_item(node, struct audio_usecase, list);
1559 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001560 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1561 &num_devices, split_snd_devices) == 0) {
1562 /* Enable derived sound device only if it does not match with
1563 one of the split sound devices. This is because the matching
1564 sound device was not disabled */
1565 bool should_enable = true;
1566 for (i = 0; i < num_devices; i++) {
1567 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1568 should_enable = false;
1569 break;
1570 }
1571 }
1572 if (should_enable)
1573 enable_snd_device(adev, derive_snd_device[usecase->id]);
1574 } else {
1575 enable_snd_device(adev, derive_snd_device[usecase->id]);
1576 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001577 }
1578 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 /* Re-route all the usecases on the shared backend other than the
1581 specified usecase to new snd devices */
1582 list_for_each(node, &adev->usecase_list) {
1583 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301584 /* Update the out_snd_device only before enabling the audio route */
1585 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301586 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301587 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301588 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301589 use_case_table[usecase->id],
1590 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001591 /* Update voc calibration before enabling VoIP route */
1592 if (usecase->type == VOIP_CALL)
1593 status = platform_switch_voice_call_device_post(adev->platform,
1594 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001595 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301596 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001597 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1598 out_set_voip_volume(&usecase->stream.out->stream,
1599 usecase->stream.out->volume_l,
1600 usecase->stream.out->volume_r);
1601 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301602 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 }
1604 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 }
1606}
1607
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301608static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001609 struct audio_usecase *uc_info,
1610 snd_device_t snd_device)
1611{
1612 struct listnode *node;
1613 struct audio_usecase *usecase;
1614 bool switch_device[AUDIO_USECASE_MAX];
1615 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301616 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001617 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001618
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301619 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1620 snd_device);
1621 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301622
1623 /*
1624 * Make sure out devices is checked against out codec backend device and
1625 * also in devices against in codec backend. Checking out device against in
1626 * codec backend or vice versa causes issues.
1627 */
1628 if (uc_info->type == PCM_CAPTURE)
1629 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001630 /*
1631 * This function is to make sure that all the active capture usecases
1632 * are always routed to the same input sound device.
1633 * For example, if audio-record and voice-call usecases are currently
1634 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1635 * is received for voice call then we have to make sure that audio-record
1636 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1637 * because of the limitation that two devices cannot be enabled
1638 * at the same time if they share the same backend.
1639 */
1640 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1641 switch_device[i] = false;
1642
1643 list_for_each(node, &adev->usecase_list) {
1644 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301645 /*
1646 * TODO: Enhance below condition to handle BT sco/USB multi recording
1647 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001648 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001649 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301650 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301651 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301652 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301653 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001654 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001655 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1656 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001657 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001658 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001659 switch_device[usecase->id] = true;
1660 num_uc_to_switch++;
1661 }
1662 }
1663
1664 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001665 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001666
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301667 /* Make sure the previous devices to be disabled first and then enable the
1668 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001669 list_for_each(node, &adev->usecase_list) {
1670 usecase = node_to_item(node, struct audio_usecase, list);
1671 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001672 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001673 }
1674 }
1675
1676 list_for_each(node, &adev->usecase_list) {
1677 usecase = node_to_item(node, struct audio_usecase, list);
1678 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001679 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001680 }
1681 }
1682
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001683 /* Re-route all the usecases on the shared backend other than the
1684 specified usecase to new snd devices */
1685 list_for_each(node, &adev->usecase_list) {
1686 usecase = node_to_item(node, struct audio_usecase, list);
1687 /* Update the in_snd_device only before enabling the audio route */
1688 if (switch_device[usecase->id] ) {
1689 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001690 if (usecase->type != VOICE_CALL) {
1691 /* Update voc calibration before enabling VoIP route */
1692 if (usecase->type == VOIP_CALL)
1693 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001694 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001695 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301696 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001697 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001698 }
1699 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001700 }
1701}
1702
Mingming Yin3a941d42016-02-17 18:08:05 -08001703static void reset_hdmi_sink_caps(struct stream_out *out) {
1704 int i = 0;
1705
1706 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1707 out->supported_channel_masks[i] = 0;
1708 }
1709 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1710 out->supported_formats[i] = 0;
1711 }
1712 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1713 out->supported_sample_rates[i] = 0;
1714 }
1715}
1716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001718static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719{
Mingming Yin3a941d42016-02-17 18:08:05 -08001720 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001721 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
Mingming Yin3a941d42016-02-17 18:08:05 -08001723 reset_hdmi_sink_caps(out);
1724
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001725 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001726 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001727 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001728 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001729 }
1730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001733 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001734 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001735 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1736 case 6:
1737 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1738 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1739 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1740 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1741 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1742 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 break;
1744 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001745 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001746 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 break;
1748 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001749
1750 // check channel format caps
1751 i = 0;
1752 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1753 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1754 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1755 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1756 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1757 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1758 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1759 }
1760
Ben Romberger1aaaf862017-04-06 17:49:46 -07001761 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1762 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1763 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1764 }
1765
Mingming Yin3a941d42016-02-17 18:08:05 -08001766 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1767 ALOGV(":%s HDMI supports DTS format", __func__);
1768 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1769 }
1770
1771 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1772 ALOGV(":%s HDMI supports DTS HD format", __func__);
1773 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1774 }
1775
Naresh Tanniru928f0862017-04-07 16:44:23 -07001776 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1777 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1778 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1779 }
1780
Mingming Yin3a941d42016-02-17 18:08:05 -08001781
1782 // check sample rate caps
1783 i = 0;
1784 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1785 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1786 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1787 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1788 }
1789 }
1790
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792}
1793
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001794static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1795 uint32_t *supported_sample_rates __unused,
1796 uint32_t max_rates __unused)
1797{
1798 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1799 supported_sample_rates,
1800 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301801 ssize_t i = 0;
1802
1803 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001804 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1805 supported_sample_rates[i]);
1806 }
1807 return count;
1808}
1809
1810static inline int read_usb_sup_channel_masks(bool is_playback,
1811 audio_channel_mask_t *supported_channel_masks,
1812 uint32_t max_masks)
1813{
1814 int channels = audio_extn_usb_get_max_channels(is_playback);
1815 int channel_count;
1816 uint32_t num_masks = 0;
1817 if (channels > MAX_HIFI_CHANNEL_COUNT)
1818 channels = MAX_HIFI_CHANNEL_COUNT;
1819
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301820 channel_count = DEFAULT_CHANNEL_COUNT;
1821
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001822 if (is_playback) {
1823 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001824 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301825 // above 2 but we want indexed masks here.
1826 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001827 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001828 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1829 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301830 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001831 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301832
1833 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1834 (num_masks < max_masks)); channel_count--) {
1835 supported_channel_masks[num_masks++] =
1836 audio_channel_mask_for_index_assignment_from_count(channel_count);
1837 }
1838
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001839 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1840 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1841 return num_masks;
1842}
1843
1844static inline int read_usb_sup_formats(bool is_playback __unused,
1845 audio_format_t *supported_formats,
1846 uint32_t max_formats __unused)
1847{
1848 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1849 switch (bitwidth) {
1850 case 24:
1851 // XXX : usb.c returns 24 for s24 and s24_le?
1852 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1853 break;
1854 case 32:
1855 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1856 break;
1857 case 16:
1858 default :
1859 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1860 break;
1861 }
1862 ALOGV("%s: %s supported format %d", __func__,
1863 is_playback ? "P" : "C", bitwidth);
1864 return 1;
1865}
1866
1867static inline int read_usb_sup_params_and_compare(bool is_playback,
1868 audio_format_t *format,
1869 audio_format_t *supported_formats,
1870 uint32_t max_formats,
1871 audio_channel_mask_t *mask,
1872 audio_channel_mask_t *supported_channel_masks,
1873 uint32_t max_masks,
1874 uint32_t *rate,
1875 uint32_t *supported_sample_rates,
1876 uint32_t max_rates) {
1877 int ret = 0;
1878 int num_formats;
1879 int num_masks;
1880 int num_rates;
1881 int i;
1882
1883 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1884 max_formats);
1885 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1886 max_masks);
1887
1888 num_rates = read_usb_sup_sample_rates(is_playback,
1889 supported_sample_rates, max_rates);
1890
1891#define LUT(table, len, what, dflt) \
1892 for (i=0; i<len && (table[i] != what); i++); \
1893 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1894
1895 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1896 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1897 LUT(supported_sample_rates, num_rates, *rate, 0);
1898
1899#undef LUT
1900 return ret < 0 ? -EINVAL : 0; // HACK TBD
1901}
1902
Alexy Josephb1379942016-01-29 15:49:38 -08001903audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001904 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001905{
1906 struct audio_usecase *usecase;
1907 struct listnode *node;
1908
1909 list_for_each(node, &adev->usecase_list) {
1910 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001911 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001912 ALOGV("%s: usecase id %d", __func__, usecase->id);
1913 return usecase->id;
1914 }
1915 }
1916 return USECASE_INVALID;
1917}
1918
Alexy Josephb1379942016-01-29 15:49:38 -08001919struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001920 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001921{
1922 struct audio_usecase *usecase;
1923 struct listnode *node;
1924
1925 list_for_each(node, &adev->usecase_list) {
1926 usecase = node_to_item(node, struct audio_usecase, list);
1927 if (usecase->id == uc_id)
1928 return usecase;
1929 }
1930 return NULL;
1931}
1932
Dhananjay Kumard4833242016-10-06 22:09:12 +05301933struct stream_in *get_next_active_input(const struct audio_device *adev)
1934{
1935 struct audio_usecase *usecase;
1936 struct listnode *node;
1937
1938 list_for_each_reverse(node, &adev->usecase_list) {
1939 usecase = node_to_item(node, struct audio_usecase, list);
1940 if (usecase->type == PCM_CAPTURE)
1941 return usecase->stream.in;
1942 }
1943 return NULL;
1944}
1945
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301946/*
1947 * is a true native playback active
1948 */
1949bool audio_is_true_native_stream_active(struct audio_device *adev)
1950{
1951 bool active = false;
1952 int i = 0;
1953 struct listnode *node;
1954
1955 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1956 ALOGV("%s:napb: not in true mode or non hdphones device",
1957 __func__);
1958 active = false;
1959 goto exit;
1960 }
1961
1962 list_for_each(node, &adev->usecase_list) {
1963 struct audio_usecase *uc;
1964 uc = node_to_item(node, struct audio_usecase, list);
1965 struct stream_out *curr_out =
1966 (struct stream_out*) uc->stream.out;
1967
1968 if (curr_out && PCM_PLAYBACK == uc->type) {
1969 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1970 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1971 uc->id, curr_out->sample_rate,
1972 curr_out->bit_width,
1973 platform_get_snd_device_name(uc->out_snd_device));
1974
1975 if (is_offload_usecase(uc->id) &&
1976 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1977 active = true;
1978 ALOGD("%s:napb:native stream detected", __func__);
1979 }
1980 }
1981 }
1982exit:
1983 return active;
1984}
1985
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001986uint32_t adev_get_dsp_bit_width_enforce_mode()
1987{
1988 if (adev == NULL) {
1989 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1990 return 0;
1991 }
1992 return adev->dsp_bit_width_enforce_mode;
1993}
1994
1995static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1996{
1997 char value[PROPERTY_VALUE_MAX];
1998 int trial;
1999 uint32_t dsp_bit_width_enforce_mode = 0;
2000
2001 if (!mixer) {
2002 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2003 __func__);
2004 return 0;
2005 }
2006
2007 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2008 value, NULL) > 0) {
2009 trial = atoi(value);
2010 switch (trial) {
2011 case 16:
2012 dsp_bit_width_enforce_mode = 16;
2013 break;
2014 case 24:
2015 dsp_bit_width_enforce_mode = 24;
2016 break;
2017 case 32:
2018 dsp_bit_width_enforce_mode = 32;
2019 break;
2020 default:
2021 dsp_bit_width_enforce_mode = 0;
2022 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2023 break;
2024 }
2025 }
2026
2027 return dsp_bit_width_enforce_mode;
2028}
2029
2030static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2031 uint32_t enforce_mode,
2032 bool enable)
2033{
2034 struct mixer_ctl *ctl = NULL;
2035 const char *mixer_ctl_name = "ASM Bit Width";
2036 uint32_t asm_bit_width_mode = 0;
2037
2038 if (enforce_mode == 0) {
2039 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2040 return;
2041 }
2042
2043 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2044 if (!ctl) {
2045 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2046 __func__, mixer_ctl_name);
2047 return;
2048 }
2049
2050 if (enable)
2051 asm_bit_width_mode = enforce_mode;
2052 else
2053 asm_bit_width_mode = 0;
2054
2055 ALOGV("%s DSP bit width feature status is %d width=%d",
2056 __func__, enable, asm_bit_width_mode);
2057 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2058 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2059 asm_bit_width_mode);
2060
2061 return;
2062}
2063
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302064/*
2065 * if native DSD playback active
2066 */
2067bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2068{
2069 bool active = false;
2070 struct listnode *node = NULL;
2071 struct audio_usecase *uc = NULL;
2072 struct stream_out *curr_out = NULL;
2073
2074 list_for_each(node, &adev->usecase_list) {
2075 uc = node_to_item(node, struct audio_usecase, list);
2076 curr_out = (struct stream_out*) uc->stream.out;
2077
2078 if (curr_out && PCM_PLAYBACK == uc->type &&
2079 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2080 active = true;
2081 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302082 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302083 }
2084 }
2085 return active;
2086}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302087
2088static bool force_device_switch(struct audio_usecase *usecase)
2089{
2090 bool ret = false;
2091 bool is_it_true_mode = false;
2092
Zhou Song30f2c3e2018-02-08 14:02:15 +08002093 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302094 usecase->type == TRANSCODE_LOOPBACK_RX ||
2095 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002096 return false;
2097 }
2098
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002099 if(usecase->stream.out == NULL) {
2100 ALOGE("%s: stream.out is NULL", __func__);
2101 return false;
2102 }
2103
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302104 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002105 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2106 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2107 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302108 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2109 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2110 (!is_it_true_mode && adev->native_playback_enabled)){
2111 ret = true;
2112 ALOGD("napb: time to toggle native mode");
2113 }
2114 }
2115
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302116 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302117 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2118 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002119 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302120 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302121 ALOGD("Force a2dp device switch to update new encoder config");
2122 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002123 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302124
Florian Pfister1a84f312018-07-19 14:38:18 +02002125 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302126 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2127 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002128 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302129 return ret;
2130}
2131
Aalique Grahame22e49102018-12-18 14:23:57 -08002132static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2133{
2134 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2135}
2136
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302137bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2138{
2139 bool ret=false;
2140 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2141 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2142 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2143 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2144 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2145 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2146 ret = true;
2147
2148 return ret;
2149}
2150
2151bool is_a2dp_device(snd_device_t out_snd_device)
2152{
2153 bool ret=false;
2154 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2155 ret = true;
2156
2157 return ret;
2158}
2159
2160bool is_bt_soc_on(struct audio_device *adev)
2161{
2162 struct mixer_ctl *ctl;
2163 char *mixer_ctl_name = "BT SOC status";
2164 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2165 bool bt_soc_status = true;
2166 if (!ctl) {
2167 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2168 __func__, mixer_ctl_name);
2169 /*This is to ensure we dont break targets which dont have the kernel change*/
2170 return true;
2171 }
2172 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2173 ALOGD("BT SOC status: %d",bt_soc_status);
2174 return bt_soc_status;
2175}
2176
2177int out_standby_l(struct audio_stream *stream);
2178
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002179int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002181 snd_device_t out_snd_device = SND_DEVICE_NONE;
2182 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183 struct audio_usecase *usecase = NULL;
2184 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002185 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002186 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302187 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002188 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002189 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302191 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2192
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002193 usecase = get_usecase_from_list(adev, uc_id);
2194 if (usecase == NULL) {
2195 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2196 return -EINVAL;
2197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002199 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002200 (usecase->type == VOIP_CALL) ||
2201 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302202 if(usecase->stream.out == NULL) {
2203 ALOGE("%s: stream.out is NULL", __func__);
2204 return -EINVAL;
2205 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002206 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002207 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002208 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002209 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302210 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302211 if (usecase->stream.inout == NULL) {
2212 ALOGE("%s: stream.inout is NULL", __func__);
2213 return -EINVAL;
2214 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302215 stream_out.devices = usecase->stream.inout->out_config.devices;
2216 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2217 stream_out.format = usecase->stream.inout->out_config.format;
2218 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2219 out_snd_device = platform_get_output_snd_device(adev->platform,
2220 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302221 usecase->devices = out_snd_device;
2222 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2223 if (usecase->stream.inout == NULL) {
2224 ALOGE("%s: stream.inout is NULL", __func__);
2225 return -EINVAL;
2226 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302227 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302228 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002229 } else {
2230 /*
2231 * If the voice call is active, use the sound devices of voice call usecase
2232 * so that it would not result any device switch. All the usecases will
2233 * be switched to new device when select_devices() is called for voice call
2234 * usecase. This is to avoid switching devices for voice call when
2235 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002236 * choose voice call device only if the use case device is
2237 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002239 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002240 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002241 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002242 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2243 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302244 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2245 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002246 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 in_snd_device = vc_usecase->in_snd_device;
2248 out_snd_device = vc_usecase->out_snd_device;
2249 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002250 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002251 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002252 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002253 if ((voip_usecase != NULL) &&
2254 (usecase->type == PCM_PLAYBACK) &&
2255 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002256 out_snd_device_backend_match = platform_check_backends_match(
2257 voip_usecase->out_snd_device,
2258 platform_get_output_snd_device(
2259 adev->platform,
2260 usecase->stream.out));
2261 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002262 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002263 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2264 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002265 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002266 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002267 in_snd_device = voip_usecase->in_snd_device;
2268 out_snd_device = voip_usecase->out_snd_device;
2269 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002270 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002271 hfp_ucid = audio_extn_hfp_get_usecase();
2272 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002273 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002274 in_snd_device = hfp_usecase->in_snd_device;
2275 out_snd_device = hfp_usecase->out_snd_device;
2276 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 }
2278 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302279 if (usecase->stream.out == NULL) {
2280 ALOGE("%s: stream.out is NULL", __func__);
2281 return -EINVAL;
2282 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002283 usecase->devices = usecase->stream.out->devices;
2284 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002285 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002286 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002287 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002288 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002289 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002290 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2291
2292 if ((usecase->stream.out != NULL &&
2293 voip_usecase != NULL &&
2294 usecase->stream.out->usecase == voip_usecase->id) &&
2295 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002296 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2297 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002298 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002299 select_devices(adev, adev->active_input->usecase);
2300 }
2301 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002302 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302303 if (usecase->stream.in == NULL) {
2304 ALOGE("%s: stream.in is NULL", __func__);
2305 return -EINVAL;
2306 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 usecase->devices = usecase->stream.in->device;
2308 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002309 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002310 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002311 if (adev->active_input &&
2312 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302313 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002314 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2315 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2316 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2317 out_device = voip_usecase->stream.out->devices;
2318 else if (adev->primary_output && !adev->primary_output->standby)
2319 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002320 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002321 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2322 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002323 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002324 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002325 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002326 }
2327 }
2328
2329 if (out_snd_device == usecase->out_snd_device &&
2330 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302331
2332 if (!force_device_switch(usecase))
2333 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 }
2335
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302336 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002337 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302338 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2339 return 0;
2340 }
2341
Aalique Grahame22e49102018-12-18 14:23:57 -08002342 if (out_snd_device != SND_DEVICE_NONE &&
2343 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2344 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2345 __func__,
2346 use_case_table[uc_id],
2347 adev->last_logged_snd_device[uc_id][0],
2348 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2349 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2350 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2351 -1,
2352 out_snd_device,
2353 platform_get_snd_device_name(out_snd_device),
2354 platform_get_snd_device_acdb_id(out_snd_device));
2355 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2356 }
2357 if (in_snd_device != SND_DEVICE_NONE &&
2358 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2359 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2360 __func__,
2361 use_case_table[uc_id],
2362 adev->last_logged_snd_device[uc_id][1],
2363 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2364 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2365 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2366 -1,
2367 in_snd_device,
2368 platform_get_snd_device_name(in_snd_device),
2369 platform_get_snd_device_acdb_id(in_snd_device));
2370 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2371 }
2372
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 /*
2375 * Limitation: While in call, to do a device switch we need to disable
2376 * and enable both RX and TX devices though one of them is same as current
2377 * device.
2378 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002379 if ((usecase->type == VOICE_CALL) &&
2380 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2381 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002382 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002383 }
2384
2385 if (((usecase->type == VOICE_CALL) ||
2386 (usecase->type == VOIP_CALL)) &&
2387 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2388 /* Disable sidetone only if voice/voip call already exists */
2389 if (voice_is_call_state_active(adev) ||
2390 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002391 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002392
2393 /* Disable aanc only if voice call exists */
2394 if (voice_is_call_state_active(adev))
2395 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002396 }
2397
Aalique Grahame22e49102018-12-18 14:23:57 -08002398 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2399 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002400 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302401 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002402 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2403 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2404 else
2405 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302406 }
2407
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002408 /* Disable current sound devices */
2409 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002410 disable_audio_route(adev, usecase);
2411 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 }
2413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002414 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002415 disable_audio_route(adev, usecase);
2416 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417 }
2418
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002419 /* Applicable only on the targets that has external modem.
2420 * New device information should be sent to modem before enabling
2421 * the devices to reduce in-call device switch time.
2422 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002423 if ((usecase->type == VOICE_CALL) &&
2424 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2425 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002426 status = platform_switch_voice_call_enable_device_config(adev->platform,
2427 out_snd_device,
2428 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002429 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431 /* Enable new sound devices */
2432 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002433 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302434 if (platform_check_codec_asrc_support(adev->platform))
2435 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002436 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 }
2438
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002439 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302440 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002441 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002443
Avinash Vaish71a8b972014-07-24 15:36:33 +05302444 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002445 status = platform_switch_voice_call_device_post(adev->platform,
2446 out_snd_device,
2447 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302448 enable_audio_route_for_voice_usecases(adev, usecase);
2449 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002450
sangwoo170731f2013-06-08 15:36:36 +09002451 usecase->in_snd_device = in_snd_device;
2452 usecase->out_snd_device = out_snd_device;
2453
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302454 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2455 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302456 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002457 if ((24 == usecase->stream.out->bit_width) &&
2458 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2459 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2460 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2461 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2462 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2463 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2464 /*
2465 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2466 * configured device sample rate, if not update the COPP rate to be equal to the
2467 * device sample rate, else open COPP at stream sample rate
2468 */
2469 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2470 usecase->stream.out->sample_rate,
2471 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302472 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2473 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002474 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2475 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2476 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2477 }
2478
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002479 /* Notify device change info to effect clients registered */
2480 audio_extn_gef_notify_device_config(
2481 usecase->stream.out->devices,
2482 usecase->stream.out->channel_mask,
2483 usecase->stream.out->app_type_cfg.sample_rate,
2484 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302485 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002486 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002487
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002488 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002489
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002490 /* If input stream is already running then effect needs to be
2491 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002492 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2493 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002494 check_and_enable_effect(adev);
2495
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002496 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002497 /* Enable aanc only if voice call exists */
2498 if (voice_is_call_state_active(adev))
2499 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2500
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002501 /* Enable sidetone only if other voice/voip call already exists */
2502 if (voice_is_call_state_active(adev) ||
2503 voice_extn_compress_voip_is_started(adev))
2504 voice_set_sidetone(adev, out_snd_device, true);
2505 }
2506
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002507 /* Applicable only on the targets that has external modem.
2508 * Enable device command should be sent to modem only after
2509 * enabling voice call mixer controls
2510 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002511 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002512 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2513 out_snd_device,
2514 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302515
2516 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2517
2518 if (usecase->type == VOIP_CALL) {
2519 if (adev->active_input != NULL &&
2520 !adev->active_input->standby) {
2521 if (is_bt_soc_on(adev) == false){
2522 ALOGD("BT SCO MIC disconnected while in connection");
2523 if (adev->active_input->pcm != NULL)
2524 pcm_stop(adev->active_input->pcm);
2525 }
2526 }
2527 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2528 && usecase->stream.out->started) {
2529 if (is_bt_soc_on(adev) == false) {
2530 ALOGD("BT SCO/A2DP disconnected while in connection");
2531 out_standby_l(&usecase->stream.out->stream.common);
2532 }
2533 }
2534 } else if ((usecase->stream.out != NULL) &&
2535 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302536 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2537 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302538 usecase->stream.out->started) {
2539 if (is_bt_soc_on(adev) == false) {
2540 ALOGD("BT SCO/A2dp disconnected while in connection");
2541 out_standby_l(&usecase->stream.out->stream.common);
2542 }
2543 }
2544 }
2545
Aalique Grahame22e49102018-12-18 14:23:57 -08002546 if (usecase == voip_usecase) {
2547 struct stream_out *voip_out = voip_usecase->stream.out;
2548 audio_extn_utils_send_app_type_gain(adev,
2549 voip_out->app_type_cfg.app_type,
2550 &voip_out->app_type_cfg.gain[0]);
2551 }
2552
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302553 ALOGD("%s: done",__func__);
2554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 return status;
2556}
2557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558static int stop_input_stream(struct stream_in *in)
2559{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302560 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302562
2563 if (in == NULL) {
2564 ALOGE("%s: stream_in ptr is NULL", __func__);
2565 return -EINVAL;
2566 }
2567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 struct audio_device *adev = in->dev;
2569
Eric Laurent994a6932013-07-17 11:51:42 -07002570 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002571 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 uc_info = get_usecase_from_list(adev, in->usecase);
2573 if (uc_info == NULL) {
2574 ALOGE("%s: Could not find the usecase (%d) in the list",
2575 __func__, in->usecase);
2576 return -EINVAL;
2577 }
2578
Derek Chenea197282019-01-07 17:35:01 -08002579 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2580 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002581
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002582 /* Close in-call recording streams */
2583 voice_check_and_stop_incall_rec_usecase(adev, in);
2584
Eric Laurent150dbfe2013-02-27 14:31:02 -08002585 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002586 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002587
2588 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002589 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002591 list_remove(&uc_info->list);
2592 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002594 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302595 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002596 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 return ret;
2598}
2599
2600int start_input_stream(struct stream_in *in)
2601{
2602 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002603 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302605
2606 if (in == NULL) {
2607 ALOGE("%s: stream_in ptr is NULL", __func__);
2608 return -EINVAL;
2609 }
2610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002612 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002613 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614
Mingming Yin2664a5b2015-09-03 10:53:11 -07002615 if (get_usecase_from_list(adev, usecase) == NULL)
2616 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302617 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2618 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002619
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302620 if (CARD_STATUS_OFFLINE == in->card_status||
2621 CARD_STATUS_OFFLINE == adev->card_status) {
2622 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302623 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624 goto error_config;
2625 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302626
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302627 if (audio_is_bluetooth_sco_device(in->device)) {
2628 if (!adev->bt_sco_on) {
2629 ALOGE("%s: SCO profile is not ready, return error", __func__);
2630 ret = -EIO;
2631 goto error_config;
2632 }
2633 }
2634
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002635 /* Check if source matches incall recording usecase criteria */
2636 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2637 if (ret)
2638 goto error_config;
2639 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002640 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2641
2642 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2643 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2644 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002645 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002646 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002647
Eric Laurentb23d5282013-05-14 15:27:20 -07002648 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 if (in->pcm_device_id < 0) {
2650 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2651 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002652 ret = -EINVAL;
2653 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002655
2656 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002658
2659 if (!uc_info) {
2660 ret = -ENOMEM;
2661 goto error_config;
2662 }
2663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 uc_info->id = in->usecase;
2665 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002666 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002667 uc_info->devices = in->device;
2668 uc_info->in_snd_device = SND_DEVICE_NONE;
2669 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002671 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302672 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2673 adev->perf_lock_opts,
2674 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002675 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676
Derek Chenea197282019-01-07 17:35:01 -08002677 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2678 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002679
Haynes Mathew George16081042017-05-31 17:16:49 -07002680 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302681 ret = audio_extn_cin_start_input_stream(in);
2682 if (ret)
2683 goto error_open;
2684 else
2685 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002686 }
2687
Haynes Mathew George16081042017-05-31 17:16:49 -07002688 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002689 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002690 ALOGE("%s: pcm stream not ready", __func__);
2691 goto error_open;
2692 }
2693 ret = pcm_start(in->pcm);
2694 if (ret < 0) {
2695 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2696 goto error_open;
2697 }
2698 } else {
2699 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2700 unsigned int pcm_open_retry_count = 0;
2701
2702 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2703 flags |= PCM_MMAP | PCM_NOIRQ;
2704 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2705 } else if (in->realtime) {
2706 flags |= PCM_MMAP | PCM_NOIRQ;
2707 }
2708
Garmond Leunge2433c32017-09-28 21:51:22 -07002709 if (audio_extn_ffv_get_stream() == in) {
2710 ALOGD("%s: ffv stream, update pcm config", __func__);
2711 audio_extn_ffv_update_pcm_config(&config);
2712 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002713 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2714 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2715
2716 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002717 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002718 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002719 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002720 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302721 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302722 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2723 adev->card_status = CARD_STATUS_OFFLINE;
2724 in->card_status = CARD_STATUS_OFFLINE;
2725 ret = -EIO;
2726 goto error_open;
2727 }
2728
Haynes Mathew George16081042017-05-31 17:16:49 -07002729 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2730 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2731 if (in->pcm != NULL) {
2732 pcm_close(in->pcm);
2733 in->pcm = NULL;
2734 }
2735 if (pcm_open_retry_count-- == 0) {
2736 ret = -EIO;
2737 goto error_open;
2738 }
2739 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2740 continue;
2741 }
2742 break;
2743 }
2744
2745 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002746 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002747 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002748 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002749 if (ret < 0) {
2750 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2751 pcm_close(in->pcm);
2752 in->pcm = NULL;
2753 goto error_open;
2754 }
2755 register_in_stream(in);
2756 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002757 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002758 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002759 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002760 if (ret < 0) {
2761 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002762 pcm_close(in->pcm);
2763 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002764 goto error_open;
2765 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002766 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002767 }
2768
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002769 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002770 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2771 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002772
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302773done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302774 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002775 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302776 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002777 return ret;
2778
2779error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302780 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002782error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302783 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302784 /*
2785 * sleep 50ms to allow sufficient time for kernel
2786 * drivers to recover incases like SSR.
2787 */
2788 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002789 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302790 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792}
2793
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002794void lock_input_stream(struct stream_in *in)
2795{
2796 pthread_mutex_lock(&in->pre_lock);
2797 pthread_mutex_lock(&in->lock);
2798 pthread_mutex_unlock(&in->pre_lock);
2799}
2800
2801void lock_output_stream(struct stream_out *out)
2802{
2803 pthread_mutex_lock(&out->pre_lock);
2804 pthread_mutex_lock(&out->lock);
2805 pthread_mutex_unlock(&out->pre_lock);
2806}
2807
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808/* must be called with out->lock locked */
2809static int send_offload_cmd_l(struct stream_out* out, int command)
2810{
2811 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2812
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002813 if (!cmd) {
2814 ALOGE("failed to allocate mem for command 0x%x", command);
2815 return -ENOMEM;
2816 }
2817
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 ALOGVV("%s %d", __func__, command);
2819
2820 cmd->cmd = command;
2821 list_add_tail(&out->offload_cmd_list, &cmd->node);
2822 pthread_cond_signal(&out->offload_cond);
2823 return 0;
2824}
2825
2826/* must be called iwth out->lock locked */
2827static void stop_compressed_output_l(struct stream_out *out)
2828{
2829 out->offload_state = OFFLOAD_STATE_IDLE;
2830 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002831 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 if (out->compr != NULL) {
2833 compress_stop(out->compr);
2834 while (out->offload_thread_blocked) {
2835 pthread_cond_wait(&out->cond, &out->lock);
2836 }
2837 }
2838}
2839
Varun Balaraje49253e2017-07-06 19:48:56 +05302840bool is_interactive_usecase(audio_usecase_t uc_id)
2841{
2842 unsigned int i;
2843 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2844 if (uc_id == interactive_usecases[i])
2845 return true;
2846 }
2847 return false;
2848}
2849
2850static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2851{
2852 audio_usecase_t ret_uc = USECASE_INVALID;
2853 unsigned int intract_uc_index;
2854 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2855
2856 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2857 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2858 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2859 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2860 ret_uc = interactive_usecases[intract_uc_index];
2861 break;
2862 }
2863 }
2864
2865 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2866 return ret_uc;
2867}
2868
2869static void free_interactive_usecase(struct audio_device *adev,
2870 audio_usecase_t uc_id)
2871{
2872 unsigned int interact_uc_index;
2873 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2874
2875 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2876 if (interactive_usecases[interact_uc_index] == uc_id) {
2877 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2878 break;
2879 }
2880 }
2881 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2882}
2883
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002884bool is_offload_usecase(audio_usecase_t uc_id)
2885{
2886 unsigned int i;
2887 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2888 if (uc_id == offload_usecases[i])
2889 return true;
2890 }
2891 return false;
2892}
2893
Dhananjay Kumarac341582017-02-23 23:42:25 +05302894static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002895{
vivek mehta446c3962015-09-14 10:57:35 -07002896 audio_usecase_t ret_uc = USECASE_INVALID;
2897 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002898 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002899 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302900 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002901 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2902 else
2903 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002904
vivek mehta446c3962015-09-14 10:57:35 -07002905 pthread_mutex_lock(&adev->lock);
2906 if (get_usecase_from_list(adev, ret_uc) != NULL)
2907 ret_uc = USECASE_INVALID;
2908 pthread_mutex_unlock(&adev->lock);
2909
2910 return ret_uc;
2911 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002912
2913 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002914 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2915 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2916 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2917 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002918 break;
2919 }
2920 }
vivek mehta446c3962015-09-14 10:57:35 -07002921
2922 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2923 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002924}
2925
2926static void free_offload_usecase(struct audio_device *adev,
2927 audio_usecase_t uc_id)
2928{
vivek mehta446c3962015-09-14 10:57:35 -07002929 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002930 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002931
2932 if (!adev->multi_offload_enable)
2933 return;
2934
2935 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2936 if (offload_usecases[offload_uc_index] == uc_id) {
2937 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002938 break;
2939 }
2940 }
2941 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2942}
2943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944static void *offload_thread_loop(void *context)
2945{
2946 struct stream_out *out = (struct stream_out *) context;
2947 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002948 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002951 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2953
2954 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002955 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 for (;;) {
2957 struct offload_cmd *cmd = NULL;
2958 stream_callback_event_t event;
2959 bool send_callback = false;
2960
2961 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2962 __func__, list_empty(&out->offload_cmd_list),
2963 out->offload_state);
2964 if (list_empty(&out->offload_cmd_list)) {
2965 ALOGV("%s SLEEPING", __func__);
2966 pthread_cond_wait(&out->offload_cond, &out->lock);
2967 ALOGV("%s RUNNING", __func__);
2968 continue;
2969 }
2970
2971 item = list_head(&out->offload_cmd_list);
2972 cmd = node_to_item(item, struct offload_cmd, node);
2973 list_remove(item);
2974
2975 ALOGVV("%s STATE %d CMD %d out->compr %p",
2976 __func__, out->offload_state, cmd->cmd, out->compr);
2977
2978 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2979 free(cmd);
2980 break;
2981 }
2982
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002983 // allow OFFLOAD_CMD_ERROR reporting during standby
2984 // this is needed to handle failures during compress_open
2985 // Note however that on a pause timeout, the stream is closed
2986 // and no offload usecase will be active. Therefore this
2987 // special case is needed for compress_open failures alone
2988 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2989 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002990 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002991 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 pthread_cond_signal(&out->cond);
2993 continue;
2994 }
2995 out->offload_thread_blocked = true;
2996 pthread_mutex_unlock(&out->lock);
2997 send_callback = false;
2998 switch(cmd->cmd) {
2999 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003000 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003002 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 send_callback = true;
3004 event = STREAM_CBK_EVENT_WRITE_READY;
3005 break;
3006 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003007 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303008 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003009 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303010 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003011 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303012 if (ret < 0)
3013 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303014 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303015 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003016 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003017 else
3018 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003019 if (-ENETRESET != ret && !(-EINTR == ret &&
3020 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303021 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303022 pthread_mutex_lock(&out->lock);
3023 out->send_new_metadata = 1;
3024 out->send_next_track_params = true;
3025 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303026 event = STREAM_CBK_EVENT_DRAIN_READY;
3027 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3028 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303029 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 break;
3031 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003032 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003033 ret = compress_drain(out->compr);
3034 ALOGD("copl(%p):out of compress_drain", out);
3035 // EINTR check avoids drain interruption due to SSR
3036 if (-ENETRESET != ret && !(-EINTR == ret &&
3037 CARD_STATUS_OFFLINE == out->card_status)) {
3038 send_callback = true;
3039 event = STREAM_CBK_EVENT_DRAIN_READY;
3040 } else
3041 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303043 case OFFLOAD_CMD_ERROR:
3044 ALOGD("copl(%p): sending error callback to AF", out);
3045 send_callback = true;
3046 event = STREAM_CBK_EVENT_ERROR;
3047 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 default:
3049 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3050 break;
3051 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003052 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 out->offload_thread_blocked = false;
3054 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003055 if (send_callback && out->client_callback) {
3056 ALOGVV("%s: sending client_callback event %d", __func__, event);
3057 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 free(cmd);
3060 }
3061
3062 pthread_cond_signal(&out->cond);
3063 while (!list_empty(&out->offload_cmd_list)) {
3064 item = list_head(&out->offload_cmd_list);
3065 list_remove(item);
3066 free(node_to_item(item, struct offload_cmd, node));
3067 }
3068 pthread_mutex_unlock(&out->lock);
3069
3070 return NULL;
3071}
3072
3073static int create_offload_callback_thread(struct stream_out *out)
3074{
3075 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3076 list_init(&out->offload_cmd_list);
3077 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3078 offload_thread_loop, out);
3079 return 0;
3080}
3081
3082static int destroy_offload_callback_thread(struct stream_out *out)
3083{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003084 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 stop_compressed_output_l(out);
3086 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3087
3088 pthread_mutex_unlock(&out->lock);
3089 pthread_join(out->offload_thread, (void **) NULL);
3090 pthread_cond_destroy(&out->offload_cond);
3091
3092 return 0;
3093}
3094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095static int stop_output_stream(struct stream_out *out)
3096{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303097 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 struct audio_usecase *uc_info;
3099 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003100 bool has_voip_usecase =
3101 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102
Eric Laurent994a6932013-07-17 11:51:42 -07003103 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003104 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 uc_info = get_usecase_from_list(adev, out->usecase);
3106 if (uc_info == NULL) {
3107 ALOGE("%s: Could not find the usecase (%d) in the list",
3108 __func__, out->usecase);
3109 return -EINVAL;
3110 }
3111
Derek Chenea197282019-01-07 17:35:01 -08003112 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3113 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003114
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003115 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303116 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003117 if (adev->visualizer_stop_output != NULL)
3118 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003119
3120 audio_extn_dts_remove_state_notifier_node(out->usecase);
3121
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003122 if (adev->offload_effects_stop_output != NULL)
3123 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3124 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003125
Arun Mirpurief53ce52018-09-11 18:00:09 -07003126 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3127 voice_set_device_mute_flag(adev, false);
3128
Eric Laurent150dbfe2013-02-27 14:31:02 -08003129 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003130 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003131
3132 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003133 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Aalique Grahame22e49102018-12-18 14:23:57 -08003135 audio_extn_extspk_update(adev->extspk);
3136
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003137 if (is_offload_usecase(out->usecase)) {
3138 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3139 adev->dsp_bit_width_enforce_mode,
3140 false);
3141 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003142 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3143 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3144 false);
3145
3146 if (ret != 0)
3147 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3148 /* default service interval was successfully updated,
3149 reopen USB backend with new service interval */
3150 ret = 0;
3151 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003152
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003153 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303154 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003155 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303156 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003157 ALOGV("Disable passthrough , reset mixer to pcm");
3158 /* NO_PASSTHROUGH */
3159 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003160 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003161 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3162 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003163
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303164 /* Must be called after removing the usecase from list */
3165 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303166 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303167
Manish Dewangan21a850a2017-08-14 12:03:55 +05303168 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003169 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3170 if (ret < 0)
3171 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3172 }
3173
Aalique Grahame22e49102018-12-18 14:23:57 -08003174 if (has_voip_usecase ||
3175 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3176 struct listnode *node;
3177 struct audio_usecase *usecase;
3178 list_for_each(node, &adev->usecase_list) {
3179 usecase = node_to_item(node, struct audio_usecase, list);
3180 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3181 continue;
3182
3183 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3184 __func__, usecase->id, use_case_table[usecase->id],
3185 out->usecase, use_case_table[out->usecase]);
3186 select_devices(adev, usecase->id);
3187 }
3188 }
3189
Garmond Leung5fd0b552018-04-17 11:56:12 -07003190 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003191 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 return ret;
3193}
3194
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003195struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3196 unsigned int flags, unsigned int pcm_open_retry_count,
3197 struct pcm_config *config)
3198{
3199 struct pcm* pcm = NULL;
3200
3201 while (1) {
3202 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3203 if (pcm == NULL || !pcm_is_ready(pcm)) {
3204 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3205 if (pcm != NULL) {
3206 pcm_close(pcm);
3207 pcm = NULL;
3208 }
3209 if (pcm_open_retry_count-- == 0)
3210 return NULL;
3211
3212 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3213 continue;
3214 }
3215 break;
3216 }
3217
3218 if (pcm_is_ready(pcm)) {
3219 int ret = pcm_prepare(pcm);
3220 if (ret < 0) {
3221 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3222 pcm_close(pcm);
3223 pcm = NULL;
3224 }
3225 }
3226
3227 return pcm;
3228}
3229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230int start_output_stream(struct stream_out *out)
3231{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 struct audio_usecase *uc_info;
3234 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003235 char mixer_ctl_name[128];
3236 struct mixer_ctl *ctl = NULL;
3237 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303238 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003239 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240
Haynes Mathew George380745d2017-10-04 15:27:45 -07003241 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003242 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3243 ret = -EINVAL;
3244 goto error_config;
3245 }
3246
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003247 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303248 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003249 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303250
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303251 if (CARD_STATUS_OFFLINE == out->card_status ||
3252 CARD_STATUS_OFFLINE == adev->card_status) {
3253 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303254 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303255 goto error_config;
3256 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303257
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303258 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003259 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003260 if (out->devices &
3261 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303262 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303263 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303264 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3265 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3266 ret = -EAGAIN;
3267 goto error_config;
3268 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303269 }
3270 }
3271 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303272 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3273 if (!adev->bt_sco_on) {
3274 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3275 //combo usecase just by pass a2dp
3276 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3277 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3278 } else {
3279 ALOGE("%s: SCO profile is not ready, return error", __func__);
3280 ret = -EAGAIN;
3281 goto error_config;
3282 }
3283 }
3284 }
3285
Eric Laurentb23d5282013-05-14 15:27:20 -07003286 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 if (out->pcm_device_id < 0) {
3288 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3289 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003290 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003291 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 }
3293
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003294 if (is_haptic_usecase) {
3295 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3296 if (adev->haptic_pcm_device_id < 0) {
3297 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3298 __func__, adev->haptic_pcm_device_id, out->usecase);
3299 ret = -EINVAL;
3300 goto error_config;
3301 }
3302 }
3303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003305
3306 if (!uc_info) {
3307 ret = -ENOMEM;
3308 goto error_config;
3309 }
3310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 uc_info->id = out->usecase;
3312 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003313 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003314 uc_info->devices = out->devices;
3315 uc_info->in_snd_device = SND_DEVICE_NONE;
3316 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003317
3318 /* This must be called before adding this usecase to the list */
3319 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3320 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3321 /* USB backend is not reopened immediately.
3322 This is eventually done as part of select_devices */
3323 }
3324
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003325 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303327 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3328 adev->perf_lock_opts,
3329 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303330
3331 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303332 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303333 if (audio_extn_passthru_is_enabled() &&
3334 audio_extn_passthru_is_passthrough_stream(out)) {
3335 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303336 }
3337 }
3338
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303339 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003340 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303341 if (!a2dp_combo) {
3342 check_a2dp_restore_l(adev, out, false);
3343 } else {
3344 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003345 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3346 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3347 else
3348 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303349 select_devices(adev, out->usecase);
3350 out->devices = dev;
3351 }
3352 } else {
3353 select_devices(adev, out->usecase);
3354 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003355
Arun Mirpurief53ce52018-09-11 18:00:09 -07003356 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3357 voice_set_device_mute_flag(adev, true);
3358
Derek Chenea197282019-01-07 17:35:01 -08003359 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3360 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003361
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003362 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3363 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003364
3365 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003366 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003367 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3368 ALOGE("%s: pcm stream not ready", __func__);
3369 goto error_open;
3370 }
3371 ret = pcm_start(out->pcm);
3372 if (ret < 0) {
3373 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3374 goto error_open;
3375 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003376 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003377 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003378 unsigned int flags = PCM_OUT;
3379 unsigned int pcm_open_retry_count = 0;
3380 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3381 flags |= PCM_MMAP | PCM_NOIRQ;
3382 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003383 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003384 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003385 } else
3386 flags |= PCM_MONOTONIC;
3387
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003388 if ((adev->vr_audio_mode_enabled) &&
3389 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3390 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3391 "PCM_Dev %d Topology", out->pcm_device_id);
3392 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3393 if (!ctl) {
3394 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3395 __func__, mixer_ctl_name);
3396 } else {
3397 //if success use ULLPP
3398 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3399 __func__, mixer_ctl_name, out->pcm_device_id);
3400 //There is a still a possibility that some sessions
3401 // that request for FAST|RAW when 3D audio is active
3402 //can go through ULLPP. Ideally we expects apps to
3403 //listen to audio focus and stop concurrent playback
3404 //Also, we will look for mode flag (voice_in_communication)
3405 //before enabling the realtime flag.
3406 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3407 }
3408 }
3409
Surendar Karka91fa3682018-07-02 18:12:12 +05303410 if (out->realtime)
3411 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3412 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3413
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003414 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3415 flags, pcm_open_retry_count,
3416 &(out->config));
3417 if (out->pcm == NULL) {
3418 ret = -EIO;
3419 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003420 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003421
3422 if (is_haptic_usecase) {
3423 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3424 adev->haptic_pcm_device_id,
3425 flags, pcm_open_retry_count,
3426 &(adev->haptics_config));
3427 // failure to open haptics pcm shouldnt stop audio,
3428 // so do not close audio pcm in case of error
3429 }
3430
Surendar Karka91fa3682018-07-02 18:12:12 +05303431 if (!out->realtime)
3432 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303433 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003434
Zhou Song2b8f28f2017-09-11 10:51:38 +08003435 // apply volume for voip playback after path is set up
3436 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3437 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303438 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3439 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303440 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3441 out->apply_volume = false;
3442 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003444 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303445 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003446 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3447 adev->dsp_bit_width_enforce_mode,
3448 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003450 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003451 out->compr = compress_open(adev->snd_card,
3452 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003454 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303455 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303456 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3457 adev->card_status = CARD_STATUS_OFFLINE;
3458 out->card_status = CARD_STATUS_OFFLINE;
3459 ret = -EIO;
3460 goto error_open;
3461 }
3462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003464 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 compress_close(out->compr);
3466 out->compr = NULL;
3467 ret = -EIO;
3468 goto error_open;
3469 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303470 /* compress_open sends params of the track, so reset the flag here */
3471 out->is_compr_metadata_avail = false;
3472
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003473 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003475
Fred Oh3f43e742015-03-04 18:42:34 -08003476 /* Since small bufs uses blocking writes, a write will be blocked
3477 for the default max poll time (20s) in the event of an SSR.
3478 Reduce the poll time to observe and deal with SSR faster.
3479 */
Ashish Jain5106d362016-05-11 19:23:33 +05303480 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003481 compress_set_max_poll_wait(out->compr, 1000);
3482 }
3483
Manish Dewangan69426c82017-01-30 17:35:36 +05303484 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303485 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303486
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003487 audio_extn_dts_create_state_notifier_node(out->usecase);
3488 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3489 popcount(out->channel_mask),
3490 out->playback_started);
3491
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003492#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303493 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003494 audio_extn_dolby_send_ddp_endp_params(adev);
3495#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303496 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3497 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003498 if (adev->visualizer_start_output != NULL)
3499 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3500 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303501 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003502 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003505
3506 if (ret == 0) {
3507 register_out_stream(out);
3508 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003509 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3510 ALOGE("%s: pcm stream not ready", __func__);
3511 goto error_open;
3512 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003513 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003514 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003515 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003516 if (ret < 0)
3517 goto error_open;
3518 }
3519 }
3520
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303521 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003522 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003523
Manish Dewangan21a850a2017-08-14 12:03:55 +05303524 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003525 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003526 if (ret < 0)
3527 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3528 }
3529
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003530 // consider a scenario where on pause lower layers are tear down.
3531 // so on resume, swap mixer control need to be sent only when
3532 // backend is active, hence rather than sending from enable device
3533 // sending it from start of streamtream
3534
3535 platform_set_swap_channels(adev, true);
3536
Haynes Mathew George380745d2017-10-04 15:27:45 -07003537 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303538 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003539 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003541 if (adev->haptic_pcm) {
3542 pcm_close(adev->haptic_pcm);
3543 adev->haptic_pcm = NULL;
3544 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303545 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003547error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303548 /*
3549 * sleep 50ms to allow sufficient time for kernel
3550 * drivers to recover incases like SSR.
3551 */
3552 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003553 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303554 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003555 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556}
3557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558static int check_input_parameters(uint32_t sample_rate,
3559 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003560 int channel_count,
3561 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303565 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3566 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3567 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003568 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003569 !audio_extn_compr_cap_format_supported(format) &&
3570 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003571 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003572
Aalique Grahame22e49102018-12-18 14:23:57 -08003573 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3574 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3575 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3576 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3577 return -EINVAL;
3578 }
3579
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003580 switch (channel_count) {
3581 case 1:
3582 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303583 case 3:
3584 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003585 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003586 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003587 break;
3588 default:
3589 ret = -EINVAL;
3590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591
3592 switch (sample_rate) {
3593 case 8000:
3594 case 11025:
3595 case 12000:
3596 case 16000:
3597 case 22050:
3598 case 24000:
3599 case 32000:
3600 case 44100:
3601 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003602 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303603 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003604 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303605 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 break;
3607 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003608 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 }
3610
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
Naresh Tanniru04f71882018-06-26 17:46:22 +05303614
3615/** Add a value in a list if not already present.
3616 * @return true if value was successfully inserted or already present,
3617 * false if the list is full and does not contain the value.
3618 */
3619static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3620 for (size_t i = 0; i < list_length; i++) {
3621 if (list[i] == value) return true; // value is already present
3622 if (list[i] == 0) { // no values in this slot
3623 list[i] = value;
3624 return true; // value inserted
3625 }
3626 }
3627 return false; // could not insert value
3628}
3629
3630/** Add channel_mask in supported_channel_masks if not already present.
3631 * @return true if channel_mask was successfully inserted or already present,
3632 * false if supported_channel_masks is full and does not contain channel_mask.
3633 */
3634static void register_channel_mask(audio_channel_mask_t channel_mask,
3635 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3636 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3637 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3638}
3639
3640/** Add format in supported_formats if not already present.
3641 * @return true if format was successfully inserted or already present,
3642 * false if supported_formats is full and does not contain format.
3643 */
3644static void register_format(audio_format_t format,
3645 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3646 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3647 "%s: stream can not declare supporting its format %x", __func__, format);
3648}
3649/** Add sample_rate in supported_sample_rates if not already present.
3650 * @return true if sample_rate was successfully inserted or already present,
3651 * false if supported_sample_rates is full and does not contain sample_rate.
3652 */
3653static void register_sample_rate(uint32_t sample_rate,
3654 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3655 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3656 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3657}
3658
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003659static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3660{
3661 uint32_t high = num1, low = num2, temp = 0;
3662
3663 if (!num1 || !num2)
3664 return 0;
3665
3666 if (num1 < num2) {
3667 high = num2;
3668 low = num1;
3669 }
3670
3671 while (low != 0) {
3672 temp = low;
3673 low = high % low;
3674 high = temp;
3675 }
3676 return (num1 * num2)/high;
3677}
3678
3679static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3680{
3681 uint32_t remainder = 0;
3682
3683 if (!multiplier)
3684 return num;
3685
3686 remainder = num % multiplier;
3687 if (remainder)
3688 num += (multiplier - remainder);
3689
3690 return num;
3691}
3692
Aalique Grahame22e49102018-12-18 14:23:57 -08003693static size_t get_stream_buffer_size(size_t duration_ms,
3694 uint32_t sample_rate,
3695 audio_format_t format,
3696 int channel_count,
3697 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698{
3699 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003700 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701
Aalique Grahame22e49102018-12-18 14:23:57 -08003702 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003703 if (is_low_latency)
3704 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303705
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003706 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003707 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Ralf Herzbd08d632018-09-28 15:50:49 +02003709 /* make sure the size is multiple of 32 bytes and additionally multiple of
3710 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003711 * At 48 kHz mono 16-bit PCM:
3712 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3713 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003714 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003715 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003716 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003717
3718 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719}
3720
Aalique Grahame22e49102018-12-18 14:23:57 -08003721static size_t get_input_buffer_size(uint32_t sample_rate,
3722 audio_format_t format,
3723 int channel_count,
3724 bool is_low_latency)
3725{
3726 /* Don't know if USB HIFI in this context so use true to be conservative */
3727 if (check_input_parameters(sample_rate, format, channel_count,
3728 true /*is_usb_hifi */) != 0)
3729 return 0;
3730
3731 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3732 sample_rate,
3733 format,
3734 channel_count,
3735 is_low_latency);
3736}
3737
Ashish Jain058165c2016-09-28 23:18:48 +05303738static size_t get_output_period_size(uint32_t sample_rate,
3739 audio_format_t format,
3740 int channel_count,
3741 int duration /*in millisecs*/)
3742{
3743 size_t size = 0;
3744 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3745
3746 if ((duration == 0) || (sample_rate == 0) ||
3747 (bytes_per_sample == 0) || (channel_count == 0)) {
3748 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3749 bytes_per_sample, channel_count);
3750 return -EINVAL;
3751 }
3752
3753 size = (sample_rate *
3754 duration *
3755 bytes_per_sample *
3756 channel_count) / 1000;
3757 /*
3758 * To have same PCM samples for all channels, the buffer size requires to
3759 * be multiple of (number of channels * bytes per sample)
3760 * For writes to succeed, the buffer must be written at address which is multiple of 32
3761 */
3762 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3763
3764 return (size/(channel_count * bytes_per_sample));
3765}
3766
Zhou Song48453a02018-01-10 17:50:59 +08003767static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303768{
3769 uint64_t actual_frames_rendered = 0;
3770 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3771
3772 /* This adjustment accounts for buffering after app processor.
3773 * It is based on estimated DSP latency per use case, rather than exact.
3774 */
3775 int64_t platform_latency = platform_render_latency(out->usecase) *
3776 out->sample_rate / 1000000LL;
3777
Zhou Song48453a02018-01-10 17:50:59 +08003778 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303779 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3780 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3781 * hence only estimate.
3782 */
3783 int64_t signed_frames = out->written - kernel_buffer_size;
3784
3785 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3786
Zhou Song48453a02018-01-10 17:50:59 +08003787 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303788 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003789 if (timestamp != NULL )
3790 *timestamp = out->writeAt;
3791 } else if (timestamp != NULL) {
3792 clock_gettime(CLOCK_MONOTONIC, timestamp);
3793 }
3794 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303795
3796 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3797 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3798 (long long int)out->written, (int)kernel_buffer_size,
3799 audio_bytes_per_sample(out->compr_config.codec->format),
3800 popcount(out->channel_mask));
3801
3802 return actual_frames_rendered;
3803}
3804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3806{
3807 struct stream_out *out = (struct stream_out *)stream;
3808
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810}
3811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003812static int out_set_sample_rate(struct audio_stream *stream __unused,
3813 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814{
3815 return -ENOSYS;
3816}
3817
3818static size_t out_get_buffer_size(const struct audio_stream *stream)
3819{
3820 struct stream_out *out = (struct stream_out *)stream;
3821
Varun Balaraje49253e2017-07-06 19:48:56 +05303822 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303823 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303824 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303825 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3826 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3827 else
3828 return out->compr_config.fragment_size;
3829 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003830 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003831 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3832 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 +05303833 else if (is_offload_usecase(out->usecase) &&
3834 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303835 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003837 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003838 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839}
3840
3841static uint32_t out_get_channels(const struct audio_stream *stream)
3842{
3843 struct stream_out *out = (struct stream_out *)stream;
3844
3845 return out->channel_mask;
3846}
3847
3848static audio_format_t out_get_format(const struct audio_stream *stream)
3849{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 struct stream_out *out = (struct stream_out *)stream;
3851
3852 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853}
3854
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003855static int out_set_format(struct audio_stream *stream __unused,
3856 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857{
3858 return -ENOSYS;
3859}
3860
3861static int out_standby(struct audio_stream *stream)
3862{
3863 struct stream_out *out = (struct stream_out *)stream;
3864 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003865 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003866
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303867 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3868 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003870 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003872 if (adev->adm_deregister_stream)
3873 adev->adm_deregister_stream(adev->adm_data, out->handle);
3874
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003875 if (is_offload_usecase(out->usecase))
3876 stop_compressed_output_l(out);
3877
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003878 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003880 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3881 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303882 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003883 pthread_mutex_unlock(&adev->lock);
3884 pthread_mutex_unlock(&out->lock);
3885 ALOGD("VOIP output entered standby");
3886 return 0;
3887 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003888 if (out->pcm) {
3889 pcm_close(out->pcm);
3890 out->pcm = NULL;
3891 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003892 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3893 do_stop = out->playback_started;
3894 out->playback_started = false;
3895 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003896 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003897 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303898 out->send_next_track_params = false;
3899 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003900 out->gapless_mdata.encoder_delay = 0;
3901 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 if (out->compr != NULL) {
3903 compress_close(out->compr);
3904 out->compr = NULL;
3905 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003906 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003907 if (do_stop) {
3908 stop_output_stream(out);
3909 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003910 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911 }
3912 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303913 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 return 0;
3915}
3916
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303917static int out_on_error(struct audio_stream *stream)
3918{
3919 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003920 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303921
3922 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003923 // always send CMD_ERROR for offload streams, this
3924 // is needed e.g. when SSR happens within compress_open
3925 // since the stream is active, offload_callback_thread is also active.
3926 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3927 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003928 }
3929 pthread_mutex_unlock(&out->lock);
3930
3931 status = out_standby(&out->stream.common);
3932
3933 lock_output_stream(out);
3934 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003935 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303936 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303937
3938 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3939 ALOGD("Setting previous card status if offline");
3940 out->prev_card_status_offline = true;
3941 }
3942
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303943 pthread_mutex_unlock(&out->lock);
3944
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003945 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303946}
3947
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303948/*
3949 *standby implementation without locks, assumes that the callee already
3950 *has taken adev and out lock.
3951 */
3952int out_standby_l(struct audio_stream *stream)
3953{
3954 struct stream_out *out = (struct stream_out *)stream;
3955 struct audio_device *adev = out->dev;
3956
3957 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3958 stream, out->usecase, use_case_table[out->usecase]);
3959
3960 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003961 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303962 if (adev->adm_deregister_stream)
3963 adev->adm_deregister_stream(adev->adm_data, out->handle);
3964
3965 if (is_offload_usecase(out->usecase))
3966 stop_compressed_output_l(out);
3967
3968 out->standby = true;
3969 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3970 voice_extn_compress_voip_close_output_stream(stream);
3971 out->started = 0;
3972 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003973 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303974 return 0;
3975 } else if (!is_offload_usecase(out->usecase)) {
3976 if (out->pcm) {
3977 pcm_close(out->pcm);
3978 out->pcm = NULL;
3979 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003980 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3981 if (adev->haptic_pcm) {
3982 pcm_close(adev->haptic_pcm);
3983 adev->haptic_pcm = NULL;
3984 }
3985
3986 if (adev->haptic_buffer != NULL) {
3987 free(adev->haptic_buffer);
3988 adev->haptic_buffer = NULL;
3989 adev->haptic_buffer_size = 0;
3990 }
3991 adev->haptic_pcm_device_id = 0;
3992 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303993 } else {
3994 ALOGD("copl(%p):standby", out);
3995 out->send_next_track_params = false;
3996 out->is_compr_metadata_avail = false;
3997 out->gapless_mdata.encoder_delay = 0;
3998 out->gapless_mdata.encoder_padding = 0;
3999 if (out->compr != NULL) {
4000 compress_close(out->compr);
4001 out->compr = NULL;
4002 }
4003 }
4004 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004005 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304006 }
4007 ALOGD("%s: exit", __func__);
4008 return 0;
4009}
4010
Aalique Grahame22e49102018-12-18 14:23:57 -08004011static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012{
Aalique Grahame22e49102018-12-18 14:23:57 -08004013 struct stream_out *out = (struct stream_out *)stream;
4014
4015 // We try to get the lock for consistency,
4016 // but it isn't necessary for these variables.
4017 // If we're not in standby, we may be blocked on a write.
4018 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4019 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4020 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4021
4022 if (locked) {
4023 pthread_mutex_unlock(&out->lock);
4024 }
4025
4026 // dump error info
4027 (void)error_log_dump(
4028 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030 return 0;
4031}
4032
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004033static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4034{
4035 int ret = 0;
4036 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004037
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004038 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004039 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004040 return -EINVAL;
4041 }
4042
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304043 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004044
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004045 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4046 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304047 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004048 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004049 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4050 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304051 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004052 }
4053
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004054 ALOGV("%s new encoder delay %u and padding %u", __func__,
4055 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4056
4057 return 0;
4058}
4059
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004060static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4061{
4062 return out == adev->primary_output || out == adev->voice_tx_output;
4063}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004064
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304065// note: this call is safe only if the stream_cb is
4066// removed first in close_output_stream (as is done now).
4067static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4068{
4069 if (!stream || !parms)
4070 return;
4071
4072 struct stream_out *out = (struct stream_out *)stream;
4073 struct audio_device *adev = out->dev;
4074
4075 card_status_t status;
4076 int card;
4077 if (parse_snd_card_status(parms, &card, &status) < 0)
4078 return;
4079
4080 pthread_mutex_lock(&adev->lock);
4081 bool valid_cb = (card == adev->snd_card);
4082 pthread_mutex_unlock(&adev->lock);
4083
4084 if (!valid_cb)
4085 return;
4086
4087 lock_output_stream(out);
4088 if (out->card_status != status)
4089 out->card_status = status;
4090 pthread_mutex_unlock(&out->lock);
4091
4092 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4093 use_case_table[out->usecase],
4094 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4095
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304096 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304097 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304098 if (voice_is_call_state_active(adev) &&
4099 out == adev->primary_output) {
4100 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4101 pthread_mutex_lock(&adev->lock);
4102 voice_stop_call(adev);
4103 adev->mode = AUDIO_MODE_NORMAL;
4104 pthread_mutex_unlock(&adev->lock);
4105 }
4106 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304107 return;
4108}
4109
Kevin Rocardfce19002017-08-07 19:21:36 -07004110static int get_alive_usb_card(struct str_parms* parms) {
4111 int card;
4112 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4113 !audio_extn_usb_alive(card)) {
4114 return card;
4115 }
4116 return -ENODEV;
4117}
4118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4120{
4121 struct stream_out *out = (struct stream_out *)stream;
4122 struct audio_device *adev = out->dev;
4123 struct str_parms *parms;
4124 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004125 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304126 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004127 bool reconfig = false;
4128 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129
sangwoobc677242013-08-08 16:53:43 +09004130 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004131 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304133 if (!parms)
4134 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004135 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4136 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004138 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004139 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004141 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004142 * When HDMI cable is unplugged the music playback is paused and
4143 * the policy manager sends routing=0. But the audioflinger continues
4144 * to write data until standby time (3sec). As the HDMI core is
4145 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004146 * Avoid this by routing audio to speaker until standby.
4147 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004148 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4149 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304150 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004151 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4152 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004153 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304154 /*
4155 * When A2DP is disconnected the
4156 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004157 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304158 * (3sec). As BT is turned off, the write gets blocked.
4159 * Avoid this by routing audio to speaker until standby.
4160 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004161 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004162 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004163 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304164 val = AUDIO_DEVICE_OUT_SPEAKER;
4165 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304166 /*
4167 * When USB headset is disconnected the music platback paused
4168 * and the policy manager send routing=0. But if the USB is connected
4169 * back before the standby time, AFE is not closed and opened
4170 * when USB is connected back. So routing to speker will guarantee
4171 * AFE reconfiguration and AFE will be opend once USB is connected again
4172 */
4173 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4174 (val == AUDIO_DEVICE_NONE) &&
4175 !audio_extn_usb_connected(parms)) {
4176 val = AUDIO_DEVICE_OUT_SPEAKER;
4177 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304178 /* To avoid a2dp to sco overlapping / BT device improper state
4179 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304180 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304181 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004182 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004183 if (val &
4184 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304185 //combo usecase just by pass a2dp
4186 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304187 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304188 } else {
4189 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4190 /* update device to a2dp and don't route as BT returned error
4191 * However it is still possible a2dp routing called because
4192 * of current active device disconnection (like wired headset)
4193 */
4194 out->devices = val;
4195 pthread_mutex_unlock(&out->lock);
4196 pthread_mutex_unlock(&adev->lock);
4197 goto error;
4198 }
4199 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304200 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004201
4202 audio_devices_t new_dev = val;
4203
4204 // Workaround: If routing to an non existing usb device, fail gracefully
4205 // The routing request will otherwise block during 10 second
4206 int card;
4207 if (audio_is_usb_out_device(new_dev) &&
4208 (card = get_alive_usb_card(parms)) >= 0) {
4209
4210 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4211 pthread_mutex_unlock(&adev->lock);
4212 pthread_mutex_unlock(&out->lock);
4213 ret = -ENOSYS;
4214 goto routing_fail;
4215 }
4216
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004217 /*
4218 * select_devices() call below switches all the usecases on the same
4219 * backend to the new device. Refer to check_usecases_codec_backend() in
4220 * the select_devices(). But how do we undo this?
4221 *
4222 * For example, music playback is active on headset (deep-buffer usecase)
4223 * and if we go to ringtones and select a ringtone, low-latency usecase
4224 * will be started on headset+speaker. As we can't enable headset+speaker
4225 * and headset devices at the same time, select_devices() switches the music
4226 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4227 * So when the ringtone playback is completed, how do we undo the same?
4228 *
4229 * We are relying on the out_set_parameters() call on deep-buffer output,
4230 * once the ringtone playback is ended.
4231 * NOTE: We should not check if the current devices are same as new devices.
4232 * Because select_devices() must be called to switch back the music
4233 * playback to headset.
4234 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004235 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004236 audio_devices_t new_dev = val;
4237 bool same_dev = out->devices == new_dev;
4238 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004239
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004240 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004241 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004242 if (adev->mode == AUDIO_MODE_IN_CALL) {
4243 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004244 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4245 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4246 audio_extn_usb_set_service_interval(true /*playback*/,
4247 service_interval,
4248 &reconfig);
4249 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4250 }
4251 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004252 }
4253 } else {
4254 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004255 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004256 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004257 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004258
4259 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004260 if (!same_dev) {
4261 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304262 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4263 adev->perf_lock_opts,
4264 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004265 if (adev->adm_on_routing_change)
4266 adev->adm_on_routing_change(adev->adm_data,
4267 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004268 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304269 if (!bypass_a2dp) {
4270 select_devices(adev, out->usecase);
4271 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004272 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4273 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4274 else
4275 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304276 select_devices(adev, out->usecase);
4277 out->devices = new_dev;
4278 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004279
4280 if (!same_dev) {
4281 // on device switch force swap, lower functions will make sure
4282 // to check if swap is allowed or not.
4283 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304284 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004285 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304286 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4287 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004288 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304289 pthread_mutex_lock(&out->compr_mute_lock);
4290 out->a2dp_compress_mute = false;
4291 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4292 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004293 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4294 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304295 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004296 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004297 }
4298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004300 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004301
4302 /*handles device and call state changes*/
4303 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004305 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004306
4307 if (out == adev->primary_output) {
4308 pthread_mutex_lock(&adev->lock);
4309 audio_extn_set_parameters(adev, parms);
4310 pthread_mutex_unlock(&adev->lock);
4311 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004312 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004313 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004314 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004315
4316 audio_extn_dts_create_state_notifier_node(out->usecase);
4317 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4318 popcount(out->channel_mask),
4319 out->playback_started);
4320
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004321 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004322 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004323
Surendar Karkaf51b5842018-04-26 11:28:38 +05304324 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4325 sizeof(value));
4326 if (err >= 0) {
4327 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4328 audio_extn_send_dual_mono_mixing_coefficients(out);
4329 }
4330
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304331 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4332 if (err >= 0) {
4333 strlcpy(out->profile, value, sizeof(out->profile));
4334 ALOGV("updating stream profile with value '%s'", out->profile);
4335 lock_output_stream(out);
4336 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4337 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004338 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304339 out->sample_rate, out->bit_width,
4340 out->channel_mask, out->profile,
4341 &out->app_type_cfg);
4342 pthread_mutex_unlock(&out->lock);
4343 }
4344
Alexy Joseph98988832017-01-13 14:56:59 -08004345 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004346 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4347 // and vendor.audio.hal.output.suspend.supported is set to true
4348 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004349 //check suspend parameter only for low latency and if the property
4350 //is enabled
4351 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4352 ALOGI("%s: got suspend_playback %s", __func__, value);
4353 lock_output_stream(out);
4354 if (!strncmp(value, "false", 5)) {
4355 //suspend_playback=false is supposed to set QOS value back to 75%
4356 //the mixer control sent with value Enable will achieve that
4357 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4358 } else if (!strncmp (value, "true", 4)) {
4359 //suspend_playback=true is supposed to remove QOS value
4360 //resetting the mixer control will set the default value
4361 //for the mixer control which is Disable and this removes the QOS vote
4362 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4363 } else {
4364 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4365 " got %s", __func__, value);
4366 ret = -1;
4367 }
4368
4369 if (ret != 0) {
4370 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4371 __func__, out->pm_qos_mixer_path, ret);
4372 }
4373
4374 pthread_mutex_unlock(&out->lock);
4375 }
4376 }
4377 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304379error:
Eric Laurent994a6932013-07-17 11:51:42 -07004380 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 return ret;
4382}
4383
Paul McLeana50b7332018-12-17 08:24:21 -07004384static int in_set_microphone_direction(const struct audio_stream_in *stream,
4385 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004386 struct stream_in *in = (struct stream_in *)stream;
4387
4388 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4389
4390 in->direction = dir;
4391
4392 if (in->standby)
4393 return 0;
4394
4395 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004396}
4397
4398static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004399 struct stream_in *in = (struct stream_in *)stream;
4400
4401 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4402
4403 if (zoom > 1.0 || zoom < -1.0)
4404 return -EINVAL;
4405
4406 in->zoom = zoom;
4407
4408 if (in->standby)
4409 return 0;
4410
4411 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004412}
4413
4414
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004415static bool stream_get_parameter_channels(struct str_parms *query,
4416 struct str_parms *reply,
4417 audio_channel_mask_t *supported_channel_masks) {
4418 int ret = -1;
4419 char value[512];
4420 bool first = true;
4421 size_t i, j;
4422
4423 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4424 ret = 0;
4425 value[0] = '\0';
4426 i = 0;
4427 while (supported_channel_masks[i] != 0) {
4428 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4429 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4430 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304431 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004432
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304433 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004434 first = false;
4435 break;
4436 }
4437 }
4438 i++;
4439 }
4440 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4441 }
4442 return ret == 0;
4443}
4444
4445static bool stream_get_parameter_formats(struct str_parms *query,
4446 struct str_parms *reply,
4447 audio_format_t *supported_formats) {
4448 int ret = -1;
4449 char value[256];
4450 size_t i, j;
4451 bool first = true;
4452
4453 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4454 ret = 0;
4455 value[0] = '\0';
4456 i = 0;
4457 while (supported_formats[i] != 0) {
4458 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4459 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4460 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304461 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004462 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304463 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004464 first = false;
4465 break;
4466 }
4467 }
4468 i++;
4469 }
4470 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4471 }
4472 return ret == 0;
4473}
4474
4475static bool stream_get_parameter_rates(struct str_parms *query,
4476 struct str_parms *reply,
4477 uint32_t *supported_sample_rates) {
4478
4479 int i;
4480 char value[256];
4481 int ret = -1;
4482 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4483 ret = 0;
4484 value[0] = '\0';
4485 i=0;
4486 int cursor = 0;
4487 while (supported_sample_rates[i]) {
4488 int avail = sizeof(value) - cursor;
4489 ret = snprintf(value + cursor, avail, "%s%d",
4490 cursor > 0 ? "|" : "",
4491 supported_sample_rates[i]);
4492 if (ret < 0 || ret >= avail) {
4493 // if cursor is at the last element of the array
4494 // overwrite with \0 is duplicate work as
4495 // snprintf already put a \0 in place.
4496 // else
4497 // we had space to write the '|' at value[cursor]
4498 // (which will be overwritten) or no space to fill
4499 // the first element (=> cursor == 0)
4500 value[cursor] = '\0';
4501 break;
4502 }
4503 cursor += ret;
4504 ++i;
4505 }
4506 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4507 value);
4508 }
4509 return ret >= 0;
4510}
4511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4513{
4514 struct stream_out *out = (struct stream_out *)stream;
4515 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004516 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 char value[256];
4518 struct str_parms *reply = str_parms_create();
4519 size_t i, j;
4520 int ret;
4521 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004522
4523 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004524 if (reply) {
4525 str_parms_destroy(reply);
4526 }
4527 if (query) {
4528 str_parms_destroy(query);
4529 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004530 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4531 return NULL;
4532 }
4533
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004534 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4536 if (ret >= 0) {
4537 value[0] = '\0';
4538 i = 0;
4539 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004540 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4541 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004543 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004545 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 first = false;
4547 break;
4548 }
4549 }
4550 i++;
4551 }
4552 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4553 str = str_parms_to_str(reply);
4554 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004555 voice_extn_out_get_parameters(out, query, reply);
4556 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004558
Alexy Joseph62142aa2015-11-16 15:10:34 -08004559
4560 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4561 if (ret >= 0) {
4562 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304563 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4564 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004565 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304566 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004567 } else {
4568 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304569 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004570 }
4571 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004572 if (str)
4573 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004574 str = str_parms_to_str(reply);
4575 }
4576
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004577 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4578 if (ret >= 0) {
4579 value[0] = '\0';
4580 i = 0;
4581 first = true;
4582 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004583 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4584 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004585 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004586 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004587 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004588 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004589 first = false;
4590 break;
4591 }
4592 }
4593 i++;
4594 }
4595 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004596 if (str)
4597 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004598 str = str_parms_to_str(reply);
4599 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004600
4601 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4602 if (ret >= 0) {
4603 value[0] = '\0';
4604 i = 0;
4605 first = true;
4606 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004607 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4608 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004609 if (!first) {
4610 strlcat(value, "|", sizeof(value));
4611 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004612 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004613 first = false;
4614 break;
4615 }
4616 }
4617 i++;
4618 }
4619 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4620 if (str)
4621 free(str);
4622 str = str_parms_to_str(reply);
4623 }
4624
Alexy Joseph98988832017-01-13 14:56:59 -08004625 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4626 //only low latency track supports suspend_resume
4627 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004628 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004629 if (str)
4630 free(str);
4631 str = str_parms_to_str(reply);
4632 }
4633
4634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 str_parms_destroy(query);
4636 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004637 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638 return str;
4639}
4640
4641static uint32_t out_get_latency(const struct audio_stream_out *stream)
4642{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004643 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004645 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646
Alexy Josephaa54c872014-12-03 02:46:47 -08004647 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304648 lock_output_stream(out);
4649 latency = audio_extn_utils_compress_get_dsp_latency(out);
4650 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004651 } else if ((out->realtime) ||
4652 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004653 // since the buffer won't be filled up faster than realtime,
4654 // return a smaller number
4655 if (out->config.rate)
4656 period_ms = (out->af_period_multiplier * out->config.period_size *
4657 1000) / (out->config.rate);
4658 else
4659 period_ms = 0;
4660 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004661 } else {
4662 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004663 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004664 }
4665
yidongh0515e042017-07-06 15:00:34 +08004666 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004667 latency += audio_extn_a2dp_get_encoder_latency();
4668
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304669 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004670 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671}
4672
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304673static float AmpToDb(float amplification)
4674{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304675 float db = DSD_VOLUME_MIN_DB;
4676 if (amplification > 0) {
4677 db = 20 * log10(amplification);
4678 if(db < DSD_VOLUME_MIN_DB)
4679 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304680 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304681 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304682}
4683
Arun Mirpuri5d170872019-03-26 13:21:31 -07004684static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4685 float right)
4686{
4687 struct stream_out *out = (struct stream_out *)stream;
4688 long volume = 0;
4689 char mixer_ctl_name[128] = "";
4690 struct audio_device *adev = out->dev;
4691 struct mixer_ctl *ctl = NULL;
4692 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4693 PCM_PLAYBACK);
4694
4695 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4696 "Playback %d Volume", pcm_device_id);
4697 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4698 if (!ctl) {
4699 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4700 __func__, mixer_ctl_name);
4701 return -EINVAL;
4702 }
4703 if (left != right)
4704 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4705 __func__, left, right);
4706 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4707 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4708 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4709 __func__, mixer_ctl_name, volume);
4710 return -EINVAL;
4711 }
4712 return 0;
4713}
4714
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304715static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4716 float right)
4717{
4718 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304719 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304720 char mixer_ctl_name[128];
4721 struct audio_device *adev = out->dev;
4722 struct mixer_ctl *ctl;
4723 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4724 PCM_PLAYBACK);
4725
4726 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4727 "Compress Playback %d Volume", pcm_device_id);
4728 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4729 if (!ctl) {
4730 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4731 __func__, mixer_ctl_name);
4732 return -EINVAL;
4733 }
4734 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4735 __func__, mixer_ctl_name, left, right);
4736 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4737 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4738 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4739
4740 return 0;
4741}
4742
Zhou Song2b8f28f2017-09-11 10:51:38 +08004743static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4744 float right)
4745{
4746 struct stream_out *out = (struct stream_out *)stream;
4747 char mixer_ctl_name[] = "App Type Gain";
4748 struct audio_device *adev = out->dev;
4749 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304750 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004751
4752 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4753 if (!ctl) {
4754 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4755 __func__, mixer_ctl_name);
4756 return -EINVAL;
4757 }
4758
4759 set_values[0] = 0; //0: Rx Session 1:Tx Session
4760 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304761 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4762 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004763
4764 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4765 return 0;
4766}
4767
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304768static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4769 float right)
4770{
4771 struct stream_out *out = (struct stream_out *)stream;
4772 /* Volume control for pcm playback */
4773 if (left != right) {
4774 return -EINVAL;
4775 } else {
4776 char mixer_ctl_name[128];
4777 struct audio_device *adev = out->dev;
4778 struct mixer_ctl *ctl;
4779 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4780 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4781 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4782 if (!ctl) {
4783 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4784 return -EINVAL;
4785 }
4786
4787 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4788 int ret = mixer_ctl_set_value(ctl, 0, volume);
4789 if (ret < 0) {
4790 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4791 return -EINVAL;
4792 }
4793
4794 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4795
4796 return 0;
4797 }
4798}
4799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800static int out_set_volume(struct audio_stream_out *stream, float left,
4801 float right)
4802{
Eric Laurenta9024de2013-04-04 09:19:12 -07004803 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004804 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304805 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004806
Arun Mirpuri5d170872019-03-26 13:21:31 -07004807 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004808 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4809 /* only take left channel into account: the API is for stereo anyway */
4810 out->muted = (left == 0.0f);
4811 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004812 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304813 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004814 /*
4815 * Set mute or umute on HDMI passthrough stream.
4816 * Only take left channel into account.
4817 * Mute is 0 and unmute 1
4818 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304819 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304820 } else if (out->format == AUDIO_FORMAT_DSD){
4821 char mixer_ctl_name[128] = "DSD Volume";
4822 struct audio_device *adev = out->dev;
4823 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4824
4825 if (!ctl) {
4826 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4827 __func__, mixer_ctl_name);
4828 return -EINVAL;
4829 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304830 volume[0] = (long)(AmpToDb(left));
4831 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304832 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4833 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004834 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304835 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004836 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304837 if (!out->a2dp_compress_mute)
4838 ret = out_set_compr_volume(stream, left, right);
4839 out->volume_l = left;
4840 out->volume_r = right;
4841 pthread_mutex_unlock(&out->compr_mute_lock);
4842 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004843 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004844 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004845 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4846 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4847 if (!out->standby) {
4848 audio_extn_utils_send_app_type_gain(out->dev,
4849 out->app_type_cfg.app_type,
4850 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004851 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004852 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004853 out->volume_l = left;
4854 out->volume_r = right;
4855 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004856 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4857 ALOGV("%s: MMAP set volume called", __func__);
4858 if (!out->standby)
4859 ret = out_set_mmap_volume(stream, left, right);
4860 out->volume_l = left;
4861 out->volume_r = right;
4862 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304863 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304864 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4865 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304866 /* Volume control for pcm playback */
4867 if (!out->standby)
4868 ret = out_set_pcm_volume(stream, left, right);
4869 else
4870 out->apply_volume = true;
4871
4872 out->volume_l = left;
4873 out->volume_r = right;
4874 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004875 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 return -ENOSYS;
4878}
4879
Zhou Songc9672822017-08-16 16:01:39 +08004880static void update_frames_written(struct stream_out *out, size_t bytes)
4881{
4882 size_t bpf = 0;
4883
4884 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4885 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4886 bpf = 1;
4887 else if (!is_offload_usecase(out->usecase))
4888 bpf = audio_bytes_per_sample(out->format) *
4889 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004890
4891 pthread_mutex_lock(&out->position_query_lock);
4892 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004893 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004894 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4895 }
4896 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004897}
4898
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004899int split_and_write_audio_haptic_data(struct stream_out *out,
4900 const void *buffer, size_t bytes_to_write)
4901{
4902 struct audio_device *adev = out->dev;
4903
4904 int ret = 0;
4905 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4906 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4907 size_t frame_size = channel_count * bytes_per_sample;
4908 size_t frame_count = bytes_to_write / frame_size;
4909
4910 bool force_haptic_path =
4911 property_get_bool("vendor.audio.test_haptic", false);
4912
4913 // extract Haptics data from Audio buffer
4914 bool alloc_haptic_buffer = false;
4915 int haptic_channel_count = adev->haptics_config.channels;
4916 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4917 size_t audio_frame_size = frame_size - haptic_frame_size;
4918 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4919
4920 if (adev->haptic_buffer == NULL) {
4921 alloc_haptic_buffer = true;
4922 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4923 free(adev->haptic_buffer);
4924 adev->haptic_buffer_size = 0;
4925 alloc_haptic_buffer = true;
4926 }
4927
4928 if (alloc_haptic_buffer) {
4929 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4930 adev->haptic_buffer_size = total_haptic_buffer_size;
4931 }
4932
4933 size_t src_index = 0, aud_index = 0, hap_index = 0;
4934 uint8_t *audio_buffer = (uint8_t *)buffer;
4935 uint8_t *haptic_buffer = adev->haptic_buffer;
4936
4937 // This is required for testing only. This works for stereo data only.
4938 // One channel is fed to audio stream and other to haptic stream for testing.
4939 if (force_haptic_path)
4940 audio_frame_size = haptic_frame_size = bytes_per_sample;
4941
4942 for (size_t i = 0; i < frame_count; i++) {
4943 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4944 audio_frame_size);
4945 aud_index += audio_frame_size;
4946 src_index += audio_frame_size;
4947
4948 if (adev->haptic_pcm)
4949 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4950 haptic_frame_size);
4951 hap_index += haptic_frame_size;
4952 src_index += haptic_frame_size;
4953
4954 // This is required for testing only.
4955 // Discard haptic channel data.
4956 if (force_haptic_path)
4957 src_index += haptic_frame_size;
4958 }
4959
4960 // write to audio pipeline
4961 ret = pcm_write(out->pcm, (void *)audio_buffer,
4962 frame_count * audio_frame_size);
4963
4964 // write to haptics pipeline
4965 if (adev->haptic_pcm)
4966 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4967 frame_count * haptic_frame_size);
4968
4969 return ret;
4970}
4971
Aalique Grahame22e49102018-12-18 14:23:57 -08004972#ifdef NO_AUDIO_OUT
4973static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4974 const void *buffer __unused, size_t bytes)
4975{
4976 struct stream_out *out = (struct stream_out *)stream;
4977
4978 /* No Output device supported other than BT for playback.
4979 * Sleep for the amount of buffer duration
4980 */
4981 lock_output_stream(out);
4982 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4983 (const struct audio_stream_out *)&out->stream) /
4984 out_get_sample_rate(&out->stream.common));
4985 pthread_mutex_unlock(&out->lock);
4986 return bytes;
4987}
4988#endif
4989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4991 size_t bytes)
4992{
4993 struct stream_out *out = (struct stream_out *)stream;
4994 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004995 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304996 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004997 const size_t frame_size = audio_stream_out_frame_size(stream);
4998 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05304999 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000
Haynes Mathew George380745d2017-10-04 15:27:45 -07005001 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005002 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305003
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305004 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005005
Dhananjay Kumarac341582017-02-23 23:42:25 +05305006 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305007 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305008 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5009 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005010 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305011 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305012 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305013 ALOGD(" %s: sound card is not active/SSR state", __func__);
5014 ret= -EIO;
5015 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305016 }
5017 }
5018
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305019 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305020 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305021 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305022 goto exit;
5023 }
5024
Haynes Mathew George16081042017-05-31 17:16:49 -07005025 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5026 ret = -EINVAL;
5027 goto exit;
5028 }
5029
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305030 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5031 !out->is_iec61937_info_available) {
5032
5033 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5034 out->is_iec61937_info_available = true;
5035 } else if (audio_extn_passthru_is_enabled()) {
5036 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305037 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305038
5039 if((out->format == AUDIO_FORMAT_DTS) ||
5040 (out->format == AUDIO_FORMAT_DTS_HD)) {
5041 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5042 buffer, bytes);
5043 if (ret) {
5044 if (ret != -ENOSYS) {
5045 out->is_iec61937_info_available = false;
5046 ALOGD("iec61937 transmission info not yet updated retry");
5047 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305048 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305049 /* if stream has started and after that there is
5050 * stream config change (iec transmission config)
5051 * then trigger select_device to update backend configuration.
5052 */
5053 out->stream_config_changed = true;
5054 pthread_mutex_lock(&adev->lock);
5055 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305056 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
5057 ret = -EINVAL;
5058 goto exit;
5059 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305060 pthread_mutex_unlock(&adev->lock);
5061 out->stream_config_changed = false;
5062 out->is_iec61937_info_available = true;
5063 }
5064 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305065
Garmond Leung317cbf12017-09-13 16:20:50 -07005066 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305067 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5068 (out->is_iec61937_info_available == true)) {
5069 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5070 ret = -EINVAL;
5071 goto exit;
5072 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305073 }
5074 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305075
5076 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005077 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005078 if (!(out->devices &
5079 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305080 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305081 ret = -EIO;
5082 goto exit;
5083 }
5084 }
5085 }
5086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005088 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005089 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005090 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5091 ret = voice_extn_compress_voip_start_output_stream(out);
5092 else
5093 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005094 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005095 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005097 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 goto exit;
5099 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305100 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005101 if (last_known_cal_step != -1) {
5102 ALOGD("%s: retry previous failed cal level set", __func__);
5103 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305104 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005105 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305106
5107 if ((out->is_iec61937_info_available == true) &&
5108 (audio_extn_passthru_is_passthrough_stream(out))&&
5109 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5110 ret = -EINVAL;
5111 goto exit;
5112 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305113 if (out->set_dual_mono)
5114 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005116
Ashish Jain81eb2a82015-05-13 10:52:34 +05305117 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005118 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305119 adev->is_channel_status_set = true;
5120 }
5121
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305122 if ((adev->use_old_pspd_mix_ctrl == true) &&
5123 (out->pspd_coeff_sent == false)) {
5124 /*
5125 * Need to resend pspd coefficients after stream started for
5126 * older kernel version as it does not save the coefficients
5127 * and also stream has to be started for coeff to apply.
5128 */
5129 usecase = get_usecase_from_list(adev, out->usecase);
5130 if (usecase != NULL) {
5131 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5132 out->pspd_coeff_sent = true;
5133 }
5134 }
5135
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005136 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005137 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005138 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005139 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005140 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5141 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305142 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5143 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005144 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305145 out->send_next_track_params = false;
5146 out->is_compr_metadata_avail = false;
5147 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005148 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305149 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305150 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005151
Ashish Jain83a6cc22016-06-28 14:34:17 +05305152 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305153 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305154 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305155 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005156 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305157 return -EINVAL;
5158 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305159 audio_format_t dst_format = out->hal_op_format;
5160 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305161
Dieter Luecking5d57def2018-09-07 14:23:37 +02005162 /* prevent division-by-zero */
5163 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5164 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5165 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5166 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305167 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005168 ATRACE_END();
5169 return -EINVAL;
5170 }
5171
Ashish Jainf1eaa582016-05-23 20:54:24 +05305172 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5173 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5174
Ashish Jain83a6cc22016-06-28 14:34:17 +05305175 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305176 dst_format,
5177 buffer,
5178 src_format,
5179 frames);
5180
Ashish Jain83a6cc22016-06-28 14:34:17 +05305181 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305182 bytes_to_write);
5183
5184 /*Convert written bytes in audio flinger format*/
5185 if (ret > 0)
5186 ret = ((ret * format_to_bitwidth_table[out->format]) /
5187 format_to_bitwidth_table[dst_format]);
5188 }
5189 } else
5190 ret = compress_write(out->compr, buffer, bytes);
5191
Zhou Songc9672822017-08-16 16:01:39 +08005192 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5193 update_frames_written(out, bytes);
5194
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305195 if (ret < 0)
5196 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005197 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305198 /*msg to cb thread only if non blocking write is enabled*/
5199 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305200 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005201 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305202 } else if (-ENETRESET == ret) {
5203 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305204 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305205 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305206 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005207 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305208 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005209 }
Ashish Jain5106d362016-05-11 19:23:33 +05305210
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305211 /* Call compr start only when non-zero bytes of data is there to be rendered */
5212 if (!out->playback_started && ret > 0) {
5213 int status = compress_start(out->compr);
5214 if (status < 0) {
5215 ret = status;
5216 ALOGE("%s: compr start failed with err %d", __func__, errno);
5217 goto exit;
5218 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005219 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005220 out->playback_started = 1;
5221 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005222
5223 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5224 popcount(out->channel_mask),
5225 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005226 }
5227 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005228 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005229 return ret;
5230 } else {
5231 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005232 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005233 if (out->muted)
5234 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005235 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5236 __func__, frames, frame_size, bytes_to_write);
5237
Aalique Grahame22e49102018-12-18 14:23:57 -08005238 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005239 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005240 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5241 int16_t *src = (int16_t *)buffer;
5242 int16_t *dst = (int16_t *)buffer;
5243
5244 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5245 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005246 "out_write called for %s use case with wrong properties",
5247 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005248
5249 /*
5250 * FIXME: this can be removed once audio flinger mixer supports
5251 * mono output
5252 */
5253
5254 /*
5255 * Code below goes over each frame in the buffer and adds both
5256 * L and R samples and then divides by 2 to convert to mono
5257 */
5258 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5259 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5260 }
5261 bytes_to_write /= 2;
5262 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005263
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305264 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005265
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005266 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005267
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005268 if (out->config.rate)
5269 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5270 out->config.rate;
5271
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005272 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005273 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5274
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005275 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005276 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005277 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305278 out->convert_buffer != NULL) {
5279
5280 memcpy_by_audio_format(out->convert_buffer,
5281 out->hal_op_format,
5282 buffer,
5283 out->hal_ip_format,
5284 out->config.period_size * out->config.channels);
5285
5286 ret = pcm_write(out->pcm, out->convert_buffer,
5287 (out->config.period_size *
5288 out->config.channels *
5289 format_to_bitwidth_table[out->hal_op_format]));
5290 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305291 /*
5292 * To avoid underrun in DSP when the application is not pumping
5293 * data at required rate, check for the no. of bytes and ignore
5294 * pcm_write if it is less than actual buffer size.
5295 * It is a work around to a change in compress VOIP driver.
5296 */
5297 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5298 bytes < (out->config.period_size * out->config.channels *
5299 audio_bytes_per_sample(out->format))) {
5300 size_t voip_buf_size =
5301 out->config.period_size * out->config.channels *
5302 audio_bytes_per_sample(out->format);
5303 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5304 __func__, bytes, voip_buf_size);
5305 usleep(((uint64_t)voip_buf_size - bytes) *
5306 1000000 / audio_stream_out_frame_size(stream) /
5307 out_get_sample_rate(&out->stream.common));
5308 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005309 } else {
5310 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5311 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5312 else
5313 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5314 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305315 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005316
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005317 release_out_focus(out);
5318
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305319 if (ret < 0)
5320 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005321 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305322 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005323 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324 }
5325
5326exit:
Zhou Songc9672822017-08-16 16:01:39 +08005327 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305328 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305329 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331 pthread_mutex_unlock(&out->lock);
5332
5333 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005334 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005335 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305336 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305337 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305338 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305339 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305340 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305341 out->standby = true;
5342 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305343 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005344 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5345 /* prevent division-by-zero */
5346 uint32_t stream_size = audio_stream_out_frame_size(stream);
5347 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005348
Dieter Luecking5d57def2018-09-07 14:23:37 +02005349 if ((stream_size == 0) || (srate == 0)) {
5350 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5351 ATRACE_END();
5352 return -EINVAL;
5353 }
5354 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5355 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005356 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305357 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005358 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005359 return ret;
5360 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005361 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005362 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363 return bytes;
5364}
5365
5366static int out_get_render_position(const struct audio_stream_out *stream,
5367 uint32_t *dsp_frames)
5368{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005369 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005370
5371 if (dsp_frames == NULL)
5372 return -EINVAL;
5373
5374 *dsp_frames = 0;
5375 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005376 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305377
5378 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5379 * this operation and adev_close_output_stream(where out gets reset).
5380 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305381 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005382 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305383 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005384 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305385 return 0;
5386 }
5387
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005388 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305389 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305390 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005391 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305392 if (ret < 0)
5393 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005394 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305395 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005396 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305397 if (-ENETRESET == ret) {
5398 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305399 out->card_status = CARD_STATUS_OFFLINE;
5400 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305401 } else if(ret < 0) {
5402 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305403 ret = -EINVAL;
5404 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305405 /*
5406 * Handle corner case where compress session is closed during SSR
5407 * and timestamp is queried
5408 */
5409 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305410 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305411 } else if (out->prev_card_status_offline) {
5412 ALOGE("ERROR: previously sound card was offline,return error");
5413 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305414 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305415 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005416 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305417 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305418 pthread_mutex_unlock(&out->lock);
5419 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005420 } else if (audio_is_linear_pcm(out->format)) {
5421 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005422 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005423 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005424 } else
5425 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426}
5427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005428static int out_add_audio_effect(const struct audio_stream *stream __unused,
5429 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430{
5431 return 0;
5432}
5433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005434static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5435 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005436{
5437 return 0;
5438}
5439
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005440static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5441 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305443 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444}
5445
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005446static int out_get_presentation_position(const struct audio_stream_out *stream,
5447 uint64_t *frames, struct timespec *timestamp)
5448{
5449 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305450 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005451 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005452
Ashish Jain5106d362016-05-11 19:23:33 +05305453 /* below piece of code is not guarded against any lock because audioFliner serializes
5454 * this operation and adev_close_output_stream( where out gets reset).
5455 */
5456 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305457 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005458 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305459 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5460 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5461 return 0;
5462 }
5463
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005464 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005465
Ashish Jain5106d362016-05-11 19:23:33 +05305466 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5467 ret = compress_get_tstamp(out->compr, &dsp_frames,
5468 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005469 // Adjustment accounts for A2dp encoder latency with offload usecases
5470 // Note: Encoder latency is returned in ms.
5471 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5472 unsigned long offset =
5473 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5474 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5475 }
Ashish Jain5106d362016-05-11 19:23:33 +05305476 ALOGVV("%s rendered frames %ld sample_rate %d",
5477 __func__, dsp_frames, out->sample_rate);
5478 *frames = dsp_frames;
5479 if (ret < 0)
5480 ret = -errno;
5481 if (-ENETRESET == ret) {
5482 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305483 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305484 ret = -EINVAL;
5485 } else
5486 ret = 0;
5487 /* this is the best we can do */
5488 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005489 } else {
5490 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005491 unsigned int avail;
5492 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5493 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5494 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5495 // This adjustment accounts for buffering after app processor.
5496 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005497 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005498 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005499
Weiyin Jiangd4633762018-03-16 12:05:03 +08005500 // Adjustment accounts for A2dp encoder latency with non offload usecases
5501 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5502 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5503 signed_frames -=
5504 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5505 }
5506
5507 // It would be unusual for this value to be negative, but check just in case ...
5508 if (signed_frames >= 0) {
5509 *frames = signed_frames;
5510 ret = 0;
5511 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005512 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305513 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305514 *frames = out->written;
5515 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305516 if (is_offload_usecase(out->usecase))
5517 ret = -EINVAL;
5518 else
5519 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005520 }
5521 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005522 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005523 return ret;
5524}
5525
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005526static int out_set_callback(struct audio_stream_out *stream,
5527 stream_callback_t callback, void *cookie)
5528{
5529 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005530 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005531
5532 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005533 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005534 out->client_callback = callback;
5535 out->client_cookie = cookie;
5536 if (out->adsp_hdlr_stream_handle) {
5537 ret = audio_extn_adsp_hdlr_stream_set_callback(
5538 out->adsp_hdlr_stream_handle,
5539 callback,
5540 cookie);
5541 if (ret)
5542 ALOGW("%s:adsp hdlr callback registration failed %d",
5543 __func__, ret);
5544 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005545 pthread_mutex_unlock(&out->lock);
5546 return 0;
5547}
5548
5549static int out_pause(struct audio_stream_out* stream)
5550{
5551 struct stream_out *out = (struct stream_out *)stream;
5552 int status = -ENOSYS;
5553 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005554 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005555 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005556 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005557 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305558 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305559 status = compress_pause(out->compr);
5560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005561 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005562
Mingming Yin21854652016-04-13 11:54:02 -07005563 if (audio_extn_passthru_is_active()) {
5564 ALOGV("offload use case, pause passthru");
5565 audio_extn_passthru_on_pause(out);
5566 }
5567
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305568 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005569 audio_extn_dts_notify_playback_state(out->usecase, 0,
5570 out->sample_rate, popcount(out->channel_mask),
5571 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005572 }
5573 pthread_mutex_unlock(&out->lock);
5574 }
5575 return status;
5576}
5577
5578static int out_resume(struct audio_stream_out* stream)
5579{
5580 struct stream_out *out = (struct stream_out *)stream;
5581 int status = -ENOSYS;
5582 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005583 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005584 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005585 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005586 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005587 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305588 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305589 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005590 }
5591 if (!status) {
5592 out->offload_state = OFFLOAD_STATE_PLAYING;
5593 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305594 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005595 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5596 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005597 }
5598 pthread_mutex_unlock(&out->lock);
5599 }
5600 return status;
5601}
5602
5603static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5604{
5605 struct stream_out *out = (struct stream_out *)stream;
5606 int status = -ENOSYS;
5607 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005608 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005609 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5611 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5612 else
5613 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5614 pthread_mutex_unlock(&out->lock);
5615 }
5616 return status;
5617}
5618
5619static int out_flush(struct audio_stream_out* stream)
5620{
5621 struct stream_out *out = (struct stream_out *)stream;
5622 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005623 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005624 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005625 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005626 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5627 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005628 } else {
5629 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5630 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005631 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005632 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005633 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005634 return 0;
5635 }
5636 return -ENOSYS;
5637}
5638
Haynes Mathew George16081042017-05-31 17:16:49 -07005639static int out_stop(const struct audio_stream_out* stream)
5640{
5641 struct stream_out *out = (struct stream_out *)stream;
5642 struct audio_device *adev = out->dev;
5643 int ret = -ENOSYS;
5644
5645 ALOGV("%s", __func__);
5646 pthread_mutex_lock(&adev->lock);
5647 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5648 out->playback_started && out->pcm != NULL) {
5649 pcm_stop(out->pcm);
5650 ret = stop_output_stream(out);
5651 out->playback_started = false;
5652 }
5653 pthread_mutex_unlock(&adev->lock);
5654 return ret;
5655}
5656
5657static int out_start(const struct audio_stream_out* stream)
5658{
5659 struct stream_out *out = (struct stream_out *)stream;
5660 struct audio_device *adev = out->dev;
5661 int ret = -ENOSYS;
5662
5663 ALOGV("%s", __func__);
5664 pthread_mutex_lock(&adev->lock);
5665 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5666 !out->playback_started && out->pcm != NULL) {
5667 ret = start_output_stream(out);
5668 if (ret == 0) {
5669 out->playback_started = true;
5670 }
5671 }
5672 pthread_mutex_unlock(&adev->lock);
5673 return ret;
5674}
5675
5676/*
5677 * Modify config->period_count based on min_size_frames
5678 */
5679static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5680{
5681 int periodCountRequested = (min_size_frames + config->period_size - 1)
5682 / config->period_size;
5683 int periodCount = MMAP_PERIOD_COUNT_MIN;
5684
5685 ALOGV("%s original config.period_size = %d config.period_count = %d",
5686 __func__, config->period_size, config->period_count);
5687
5688 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5689 periodCount *= 2;
5690 }
5691 config->period_count = periodCount;
5692
5693 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5694}
5695
5696static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5697 int32_t min_size_frames,
5698 struct audio_mmap_buffer_info *info)
5699{
5700 struct stream_out *out = (struct stream_out *)stream;
5701 struct audio_device *adev = out->dev;
5702 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005703 unsigned int offset1 = 0;
5704 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005705 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005706 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005707 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005708
Arun Mirpuri5d170872019-03-26 13:21:31 -07005709 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305710 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005711 pthread_mutex_lock(&adev->lock);
5712
Sharad Sanglec6f32552018-05-04 16:15:38 +05305713 if (CARD_STATUS_OFFLINE == out->card_status ||
5714 CARD_STATUS_OFFLINE == adev->card_status) {
5715 ALOGW("out->card_status or adev->card_status offline, try again");
5716 ret = -EIO;
5717 goto exit;
5718 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005719 if (info == NULL || min_size_frames == 0) {
5720 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5721 ret = -EINVAL;
5722 goto exit;
5723 }
5724 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5725 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5726 ret = -ENOSYS;
5727 goto exit;
5728 }
5729 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5730 if (out->pcm_device_id < 0) {
5731 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5732 __func__, out->pcm_device_id, out->usecase);
5733 ret = -EINVAL;
5734 goto exit;
5735 }
5736
5737 adjust_mmap_period_count(&out->config, min_size_frames);
5738
Arun Mirpuri5d170872019-03-26 13:21:31 -07005739 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005740 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5741 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5742 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305743 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305744 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5745 out->card_status = CARD_STATUS_OFFLINE;
5746 adev->card_status = CARD_STATUS_OFFLINE;
5747 ret = -EIO;
5748 goto exit;
5749 }
5750
Haynes Mathew George16081042017-05-31 17:16:49 -07005751 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5752 step = "open";
5753 ret = -ENODEV;
5754 goto exit;
5755 }
5756 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5757 if (ret < 0) {
5758 step = "begin";
5759 goto exit;
5760 }
5761 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005762 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005763 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005764 ret = platform_get_mmap_data_fd(adev->platform,
5765 out->pcm_device_id, 0 /*playback*/,
5766 &info->shared_memory_fd,
5767 &mmap_size);
5768 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005769 // Fall back to non exclusive mode
5770 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5771 } else {
5772 if (mmap_size < buffer_size) {
5773 step = "mmap";
5774 goto exit;
5775 }
5776 // FIXME: indicate exclusive mode support by returning a negative buffer size
5777 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005778 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005779 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005780 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005781
5782 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5783 if (ret < 0) {
5784 step = "commit";
5785 goto exit;
5786 }
5787
5788 out->standby = false;
5789 ret = 0;
5790
Arun Mirpuri5d170872019-03-26 13:21:31 -07005791 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005792 __func__, info->shared_memory_address, info->buffer_size_frames);
5793
5794exit:
5795 if (ret != 0) {
5796 if (out->pcm == NULL) {
5797 ALOGE("%s: %s - %d", __func__, step, ret);
5798 } else {
5799 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5800 pcm_close(out->pcm);
5801 out->pcm = NULL;
5802 }
5803 }
5804 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305805 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005806 return ret;
5807}
5808
5809static int out_get_mmap_position(const struct audio_stream_out *stream,
5810 struct audio_mmap_position *position)
5811{
5812 struct stream_out *out = (struct stream_out *)stream;
5813 ALOGVV("%s", __func__);
5814 if (position == NULL) {
5815 return -EINVAL;
5816 }
5817 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005818 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005819 return -ENOSYS;
5820 }
5821 if (out->pcm == NULL) {
5822 return -ENOSYS;
5823 }
5824
5825 struct timespec ts = { 0, 0 };
5826 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5827 if (ret < 0) {
5828 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5829 return ret;
5830 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005831 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005832 return 0;
5833}
5834
5835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005836/** audio_stream_in implementation **/
5837static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5838{
5839 struct stream_in *in = (struct stream_in *)stream;
5840
5841 return in->config.rate;
5842}
5843
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005844static int in_set_sample_rate(struct audio_stream *stream __unused,
5845 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846{
5847 return -ENOSYS;
5848}
5849
5850static size_t in_get_buffer_size(const struct audio_stream *stream)
5851{
5852 struct stream_in *in = (struct stream_in *)stream;
5853
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005854 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5855 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005856 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5857 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 -07005858 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5859 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305860 else if(audio_extn_cin_attached_usecase(in->usecase))
5861 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005862
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005863 return in->config.period_size * in->af_period_multiplier *
5864 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005865}
5866
5867static uint32_t in_get_channels(const struct audio_stream *stream)
5868{
5869 struct stream_in *in = (struct stream_in *)stream;
5870
5871 return in->channel_mask;
5872}
5873
5874static audio_format_t in_get_format(const struct audio_stream *stream)
5875{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005876 struct stream_in *in = (struct stream_in *)stream;
5877
5878 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879}
5880
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005881static int in_set_format(struct audio_stream *stream __unused,
5882 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005883{
5884 return -ENOSYS;
5885}
5886
5887static int in_standby(struct audio_stream *stream)
5888{
5889 struct stream_in *in = (struct stream_in *)stream;
5890 struct audio_device *adev = in->dev;
5891 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305892 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5893 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005894 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305895
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005896 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005897 if (!in->standby && in->is_st_session) {
5898 ALOGD("%s: sound trigger pcm stop lab", __func__);
5899 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005900 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005901 in->standby = 1;
5902 }
5903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005904 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005905 if (adev->adm_deregister_stream)
5906 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5907
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005908 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005909 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005910 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005911 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005912 voice_extn_compress_voip_close_input_stream(stream);
5913 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005914 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5915 do_stop = in->capture_started;
5916 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005917 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305918 if (audio_extn_cin_attached_usecase(in->usecase))
5919 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005920 }
5921
Arun Mirpuri5d170872019-03-26 13:21:31 -07005922 if (in->pcm) {
5923 ATRACE_BEGIN("pcm_in_close");
5924 pcm_close(in->pcm);
5925 ATRACE_END();
5926 in->pcm = NULL;
5927 }
5928
5929 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005930 adev->enable_voicerx = false;
5931 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005932 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005933 }
Quinn Malef6050362019-01-30 15:55:40 -08005934
5935 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5936 adev->num_va_sessions--;
5937
Eric Laurent150dbfe2013-02-27 14:31:02 -08005938 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005939 }
5940 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005941 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005942 return status;
5943}
5944
Aalique Grahame22e49102018-12-18 14:23:57 -08005945static int in_dump(const struct audio_stream *stream,
5946 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005947{
Aalique Grahame22e49102018-12-18 14:23:57 -08005948 struct stream_in *in = (struct stream_in *)stream;
5949
5950 // We try to get the lock for consistency,
5951 // but it isn't necessary for these variables.
5952 // If we're not in standby, we may be blocked on a read.
5953 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5954 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5955 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5956 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5957
5958 if (locked) {
5959 pthread_mutex_unlock(&in->lock);
5960 }
5961
5962 // dump error info
5963 (void)error_log_dump(
5964 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005966 return 0;
5967}
5968
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305969static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5970{
5971 if (!stream || !parms)
5972 return;
5973
5974 struct stream_in *in = (struct stream_in *)stream;
5975 struct audio_device *adev = in->dev;
5976
5977 card_status_t status;
5978 int card;
5979 if (parse_snd_card_status(parms, &card, &status) < 0)
5980 return;
5981
5982 pthread_mutex_lock(&adev->lock);
5983 bool valid_cb = (card == adev->snd_card);
5984 pthread_mutex_unlock(&adev->lock);
5985
5986 if (!valid_cb)
5987 return;
5988
5989 lock_input_stream(in);
5990 if (in->card_status != status)
5991 in->card_status = status;
5992 pthread_mutex_unlock(&in->lock);
5993
5994 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5995 use_case_table[in->usecase],
5996 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5997
5998 // a better solution would be to report error back to AF and let
5999 // it put the stream to standby
6000 if (status == CARD_STATUS_OFFLINE)
6001 in_standby(&in->stream.common);
6002
6003 return;
6004}
6005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006006static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6007{
6008 struct stream_in *in = (struct stream_in *)stream;
6009 struct audio_device *adev = in->dev;
6010 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006011 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006012 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006013
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306014 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006015 parms = str_parms_create_str(kvpairs);
6016
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306017 if (!parms)
6018 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006019 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006020 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006021
6022 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6023 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006024 val = atoi(value);
6025 /* no audio source uses val == 0 */
6026 if ((in->source != val) && (val != 0)) {
6027 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006028 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6029 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6030 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006031 (in->config.rate == 8000 || in->config.rate == 16000 ||
6032 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006033 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006034 err = voice_extn_compress_voip_open_input_stream(in);
6035 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006036 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006037 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006038 }
6039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040 }
6041 }
6042
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006043 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6044 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006045 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006046 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6047
6048 // Workaround: If routing to an non existing usb device, fail gracefully
6049 // The routing request will otherwise block during 10 second
6050 int card;
6051 if (audio_is_usb_in_device(val) &&
6052 (card = get_alive_usb_card(parms)) >= 0) {
6053
6054 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6055 ret = -ENOSYS;
6056 } else {
6057
6058 in->device = val;
6059 /* If recording is in progress, change the tx device to new device */
6060 if (!in->standby && !in->is_st_session) {
6061 ALOGV("update input routing change");
6062 // inform adm before actual routing to prevent glitches.
6063 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006064 adev->adm_on_routing_change(adev->adm_data,
6065 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006066 ret = select_devices(adev, in->usecase);
6067 }
6068 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006069 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006070 }
6071 }
6072
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306073 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6074 if (err >= 0) {
6075 strlcpy(in->profile, value, sizeof(in->profile));
6076 ALOGV("updating stream profile with value '%s'", in->profile);
6077 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6078 &adev->streams_input_cfg_list,
6079 in->device, in->flags, in->format,
6080 in->sample_rate, in->bit_width,
6081 in->profile, &in->app_type_cfg);
6082 }
6083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006084 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006085 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006086
6087 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306088error:
Eric Laurent994a6932013-07-17 11:51:42 -07006089 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006090 return ret;
6091}
6092
6093static char* in_get_parameters(const struct audio_stream *stream,
6094 const char *keys)
6095{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006096 struct stream_in *in = (struct stream_in *)stream;
6097 struct str_parms *query = str_parms_create_str(keys);
6098 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006099 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006100
6101 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006102 if (reply) {
6103 str_parms_destroy(reply);
6104 }
6105 if (query) {
6106 str_parms_destroy(query);
6107 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006108 ALOGE("in_get_parameters: failed to create query or reply");
6109 return NULL;
6110 }
6111
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006112 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006113
6114 voice_extn_in_get_parameters(in, query, reply);
6115
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006116 stream_get_parameter_channels(query, reply,
6117 &in->supported_channel_masks[0]);
6118 stream_get_parameter_formats(query, reply,
6119 &in->supported_formats[0]);
6120 stream_get_parameter_rates(query, reply,
6121 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006122 str = str_parms_to_str(reply);
6123 str_parms_destroy(query);
6124 str_parms_destroy(reply);
6125
6126 ALOGV("%s: exit: returns - %s", __func__, str);
6127 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006128}
6129
Aalique Grahame22e49102018-12-18 14:23:57 -08006130static int in_set_gain(struct audio_stream_in *stream,
6131 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132{
Aalique Grahame22e49102018-12-18 14:23:57 -08006133 struct stream_in *in = (struct stream_in *)stream;
6134 char mixer_ctl_name[128];
6135 struct mixer_ctl *ctl;
6136 int ctl_value;
6137
6138 ALOGV("%s: gain %f", __func__, gain);
6139
6140 if (stream == NULL)
6141 return -EINVAL;
6142
6143 /* in_set_gain() only used to silence MMAP capture for now */
6144 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6145 return -ENOSYS;
6146
6147 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6148
6149 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6150 if (!ctl) {
6151 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6152 __func__, mixer_ctl_name);
6153 return -ENOSYS;
6154 }
6155
6156 if (gain < RECORD_GAIN_MIN)
6157 gain = RECORD_GAIN_MIN;
6158 else if (gain > RECORD_GAIN_MAX)
6159 gain = RECORD_GAIN_MAX;
6160 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6161
6162 mixer_ctl_set_value(ctl, 0, ctl_value);
6163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006164 return 0;
6165}
6166
6167static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6168 size_t bytes)
6169{
6170 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306171
6172 if (in == NULL) {
6173 ALOGE("%s: stream_in ptr is NULL", __func__);
6174 return -EINVAL;
6175 }
6176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006177 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306178 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306179 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006180
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006181 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306182
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006183 if (in->is_st_session) {
6184 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6185 /* Read from sound trigger HAL */
6186 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006187 if (in->standby) {
6188 adev->num_va_sessions++;
6189 in->standby = 0;
6190 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006191 pthread_mutex_unlock(&in->lock);
6192 return bytes;
6193 }
6194
Haynes Mathew George16081042017-05-31 17:16:49 -07006195 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6196 ret = -ENOSYS;
6197 goto exit;
6198 }
6199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006201 pthread_mutex_lock(&adev->lock);
6202 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6203 ret = voice_extn_compress_voip_start_input_stream(in);
6204 else
6205 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006206 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6207 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006208 pthread_mutex_unlock(&adev->lock);
6209 if (ret != 0) {
6210 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211 }
6212 in->standby = 0;
6213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006215 // what's the duration requested by the client?
6216 long ns = 0;
6217
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306218 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006219 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6220 in->config.rate;
6221
6222 request_in_focus(in, ns);
6223 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006224
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306225 if (audio_extn_cin_attached_usecase(in->usecase)) {
6226 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6227 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306228 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006229 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306230 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006231 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006232 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006233 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006234 } else if (audio_extn_ffv_get_stream() == in) {
6235 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306236 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006237 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306238 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6239 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6240 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6241 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306242 ret = -EINVAL;
6243 goto exit;
6244 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306245 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306246 ret = -errno;
6247 }
6248 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306249 /* bytes read is always set to bytes for non compress usecases */
6250 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251 }
6252
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006253 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255 /*
Quinn Malef6050362019-01-30 15:55:40 -08006256 * Instead of writing zeroes here, we could trust the hardware to always
6257 * provide zeroes when muted. This is also muted with voice recognition
6258 * usecases so that other clients do not have access to voice recognition
6259 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006260 */
Quinn Malef6050362019-01-30 15:55:40 -08006261 if ((ret == 0 && voice_get_mic_mute(adev) &&
6262 !voice_is_in_call_rec_stream(in) &&
6263 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6264 (adev->num_va_sessions &&
6265 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6266 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6267 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268 memset(buffer, 0, bytes);
6269
6270exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006271 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306272 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273 pthread_mutex_unlock(&in->lock);
6274
6275 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306276 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306277 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306278 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306279 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306280 in->standby = true;
6281 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306282 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6283 bytes_read = bytes;
6284 memset(buffer, 0, bytes);
6285 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006286 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006287 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306288 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306289 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306291 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006292}
6293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006294static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295{
6296 return 0;
6297}
6298
Aalique Grahame22e49102018-12-18 14:23:57 -08006299static int in_get_capture_position(const struct audio_stream_in *stream,
6300 int64_t *frames, int64_t *time)
6301{
6302 if (stream == NULL || frames == NULL || time == NULL) {
6303 return -EINVAL;
6304 }
6305 struct stream_in *in = (struct stream_in *)stream;
6306 int ret = -ENOSYS;
6307
6308 lock_input_stream(in);
6309 // note: ST sessions do not close the alsa pcm driver synchronously
6310 // on standby. Therefore, we may return an error even though the
6311 // pcm stream is still opened.
6312 if (in->standby) {
6313 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6314 "%s stream in standby but pcm not NULL for non ST session", __func__);
6315 goto exit;
6316 }
6317 if (in->pcm) {
6318 struct timespec timestamp;
6319 unsigned int avail;
6320 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6321 *frames = in->frames_read + avail;
6322 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6323 ret = 0;
6324 }
6325 }
6326exit:
6327 pthread_mutex_unlock(&in->lock);
6328 return ret;
6329}
6330
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006331static int add_remove_audio_effect(const struct audio_stream *stream,
6332 effect_handle_t effect,
6333 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006334{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006335 struct stream_in *in = (struct stream_in *)stream;
6336 int status = 0;
6337 effect_descriptor_t desc;
6338
6339 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006340 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6341
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006342 if (status != 0)
6343 return status;
6344
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006345 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006346 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006347 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006348 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006349 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006350 in->enable_aec != enable &&
6351 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6352 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006353 if (!enable)
6354 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6355 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6356 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6357 in->dev->enable_voicerx = enable;
6358 struct audio_usecase *usecase;
6359 struct listnode *node;
6360 list_for_each(node, &in->dev->usecase_list) {
6361 usecase = node_to_item(node, struct audio_usecase, list);
6362 if (usecase->type == PCM_PLAYBACK)
6363 select_devices(in->dev, usecase->id);
6364 }
6365 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006366 if (!in->standby) {
6367 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6368 select_devices(in->dev, in->usecase);
6369 }
6370
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006371 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006372 if (in->enable_ns != enable &&
6373 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6374 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006375 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006376 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6377 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006378 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6379 select_devices(in->dev, in->usecase);
6380 } else
6381 select_devices(in->dev, in->usecase);
6382 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006383 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006384 pthread_mutex_unlock(&in->dev->lock);
6385 pthread_mutex_unlock(&in->lock);
6386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006387 return 0;
6388}
6389
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006390static int in_add_audio_effect(const struct audio_stream *stream,
6391 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392{
Eric Laurent994a6932013-07-17 11:51:42 -07006393 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006394 return add_remove_audio_effect(stream, effect, true);
6395}
6396
6397static int in_remove_audio_effect(const struct audio_stream *stream,
6398 effect_handle_t effect)
6399{
Eric Laurent994a6932013-07-17 11:51:42 -07006400 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006401 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402}
6403
Derek Chenf939fb72018-11-13 13:34:41 -08006404streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6405 audio_io_handle_t input)
6406{
6407 struct listnode *node;
6408
6409 list_for_each(node, &dev->active_inputs_list) {
6410 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6411 streams_input_ctxt_t,
6412 list);
6413 if (in_ctxt->input->capture_handle == input) {
6414 return in_ctxt;
6415 }
6416 }
6417 return NULL;
6418}
6419
6420streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6421 audio_io_handle_t output)
6422{
6423 struct listnode *node;
6424
6425 list_for_each(node, &dev->active_outputs_list) {
6426 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6427 streams_output_ctxt_t,
6428 list);
6429 if (out_ctxt->output->handle == output) {
6430 return out_ctxt;
6431 }
6432 }
6433 return NULL;
6434}
6435
Haynes Mathew George16081042017-05-31 17:16:49 -07006436static int in_stop(const struct audio_stream_in* stream)
6437{
6438 struct stream_in *in = (struct stream_in *)stream;
6439 struct audio_device *adev = in->dev;
6440
6441 int ret = -ENOSYS;
6442 ALOGV("%s", __func__);
6443 pthread_mutex_lock(&adev->lock);
6444 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6445 in->capture_started && in->pcm != NULL) {
6446 pcm_stop(in->pcm);
6447 ret = stop_input_stream(in);
6448 in->capture_started = false;
6449 }
6450 pthread_mutex_unlock(&adev->lock);
6451 return ret;
6452}
6453
6454static int in_start(const struct audio_stream_in* stream)
6455{
6456 struct stream_in *in = (struct stream_in *)stream;
6457 struct audio_device *adev = in->dev;
6458 int ret = -ENOSYS;
6459
6460 ALOGV("%s in %p", __func__, in);
6461 pthread_mutex_lock(&adev->lock);
6462 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6463 !in->capture_started && in->pcm != NULL) {
6464 if (!in->capture_started) {
6465 ret = start_input_stream(in);
6466 if (ret == 0) {
6467 in->capture_started = true;
6468 }
6469 }
6470 }
6471 pthread_mutex_unlock(&adev->lock);
6472 return ret;
6473}
6474
6475static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6476 int32_t min_size_frames,
6477 struct audio_mmap_buffer_info *info)
6478{
6479 struct stream_in *in = (struct stream_in *)stream;
6480 struct audio_device *adev = in->dev;
6481 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006482 unsigned int offset1 = 0;
6483 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006484 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006485 uint32_t mmap_size = 0;
6486 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006487
6488 pthread_mutex_lock(&adev->lock);
6489 ALOGV("%s in %p", __func__, in);
6490
Sharad Sanglec6f32552018-05-04 16:15:38 +05306491 if (CARD_STATUS_OFFLINE == in->card_status||
6492 CARD_STATUS_OFFLINE == adev->card_status) {
6493 ALOGW("in->card_status or adev->card_status offline, try again");
6494 ret = -EIO;
6495 goto exit;
6496 }
6497
Haynes Mathew George16081042017-05-31 17:16:49 -07006498 if (info == NULL || min_size_frames == 0) {
6499 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6500 ret = -EINVAL;
6501 goto exit;
6502 }
6503 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6504 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6505 ALOGV("%s in %p", __func__, in);
6506 ret = -ENOSYS;
6507 goto exit;
6508 }
6509 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6510 if (in->pcm_device_id < 0) {
6511 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6512 __func__, in->pcm_device_id, in->usecase);
6513 ret = -EINVAL;
6514 goto exit;
6515 }
6516
6517 adjust_mmap_period_count(&in->config, min_size_frames);
6518
6519 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6520 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6521 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6522 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306523 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306524 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6525 in->card_status = CARD_STATUS_OFFLINE;
6526 adev->card_status = CARD_STATUS_OFFLINE;
6527 ret = -EIO;
6528 goto exit;
6529 }
6530
Haynes Mathew George16081042017-05-31 17:16:49 -07006531 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6532 step = "open";
6533 ret = -ENODEV;
6534 goto exit;
6535 }
6536
6537 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6538 if (ret < 0) {
6539 step = "begin";
6540 goto exit;
6541 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006542
Arun Mirpuri5d170872019-03-26 13:21:31 -07006543 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6544 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6545 info->burst_size_frames = in->config.period_size;
6546 ret = platform_get_mmap_data_fd(adev->platform,
6547 in->pcm_device_id, 1 /*capture*/,
6548 &info->shared_memory_fd,
6549 &mmap_size);
6550 if (ret < 0) {
6551 // Fall back to non exclusive mode
6552 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6553 } else {
6554 if (mmap_size < buffer_size) {
6555 step = "mmap";
6556 goto exit;
6557 }
6558 // FIXME: indicate exclusive mode support by returning a negative buffer size
6559 info->buffer_size_frames *= -1;
6560 }
6561
6562 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006563
6564 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6565 if (ret < 0) {
6566 step = "commit";
6567 goto exit;
6568 }
6569
6570 in->standby = false;
6571 ret = 0;
6572
6573 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6574 __func__, info->shared_memory_address, info->buffer_size_frames);
6575
6576exit:
6577 if (ret != 0) {
6578 if (in->pcm == NULL) {
6579 ALOGE("%s: %s - %d", __func__, step, ret);
6580 } else {
6581 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6582 pcm_close(in->pcm);
6583 in->pcm = NULL;
6584 }
6585 }
6586 pthread_mutex_unlock(&adev->lock);
6587 return ret;
6588}
6589
6590static int in_get_mmap_position(const struct audio_stream_in *stream,
6591 struct audio_mmap_position *position)
6592{
6593 struct stream_in *in = (struct stream_in *)stream;
6594 ALOGVV("%s", __func__);
6595 if (position == NULL) {
6596 return -EINVAL;
6597 }
6598 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6599 return -ENOSYS;
6600 }
6601 if (in->pcm == NULL) {
6602 return -ENOSYS;
6603 }
6604 struct timespec ts = { 0, 0 };
6605 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6606 if (ret < 0) {
6607 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6608 return ret;
6609 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306610 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006611 return 0;
6612}
6613
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306614static int in_get_active_microphones(const struct audio_stream_in *stream,
6615 struct audio_microphone_characteristic_t *mic_array,
6616 size_t *mic_count) {
6617 struct stream_in *in = (struct stream_in *)stream;
6618 struct audio_device *adev = in->dev;
6619 ALOGVV("%s", __func__);
6620
6621 lock_input_stream(in);
6622 pthread_mutex_lock(&adev->lock);
6623 int ret = platform_get_active_microphones(adev->platform,
6624 audio_channel_count_from_in_mask(in->channel_mask),
6625 in->usecase, mic_array, mic_count);
6626 pthread_mutex_unlock(&adev->lock);
6627 pthread_mutex_unlock(&in->lock);
6628
6629 return ret;
6630}
6631
6632static int adev_get_microphones(const struct audio_hw_device *dev,
6633 struct audio_microphone_characteristic_t *mic_array,
6634 size_t *mic_count) {
6635 struct audio_device *adev = (struct audio_device *)dev;
6636 ALOGVV("%s", __func__);
6637
6638 pthread_mutex_lock(&adev->lock);
6639 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6640 pthread_mutex_unlock(&adev->lock);
6641
6642 return ret;
6643}
juyuchendb308c22019-01-21 11:57:17 -07006644
6645static void in_update_sink_metadata(struct audio_stream_in *stream,
6646 const struct sink_metadata *sink_metadata) {
6647
6648 if (stream == NULL
6649 || sink_metadata == NULL
6650 || sink_metadata->tracks == NULL) {
6651 return;
6652 }
6653
6654 int error = 0;
6655 struct stream_in *in = (struct stream_in *)stream;
6656 struct audio_device *adev = in->dev;
6657 audio_devices_t device = AUDIO_DEVICE_NONE;
6658
6659 if (sink_metadata->track_count != 0)
6660 device = sink_metadata->tracks->dest_device;
6661
6662 lock_input_stream(in);
6663 pthread_mutex_lock(&adev->lock);
6664 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6665
6666 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6667 && device != AUDIO_DEVICE_NONE
6668 && adev->voice_tx_output != NULL) {
6669 /* Use the rx device from afe-proxy record to route voice call because
6670 there is no routing if tx device is on primary hal and rx device
6671 is on other hal during voice call. */
6672 adev->voice_tx_output->devices = device;
6673
6674 if (!voice_is_call_state_active(adev)) {
6675 if (adev->mode == AUDIO_MODE_IN_CALL) {
6676 adev->current_call_output = adev->voice_tx_output;
6677 error = voice_start_call(adev);
6678 if (error != 0)
6679 ALOGE("%s: start voice call failed %d", __func__, error);
6680 }
6681 } else {
6682 adev->current_call_output = adev->voice_tx_output;
6683 voice_update_devices_for_all_voice_usecases(adev);
6684 }
6685 }
6686
6687 pthread_mutex_unlock(&adev->lock);
6688 pthread_mutex_unlock(&in->lock);
6689}
6690
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306691int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006692 audio_io_handle_t handle,
6693 audio_devices_t devices,
6694 audio_output_flags_t flags,
6695 struct audio_config *config,
6696 struct audio_stream_out **stream_out,
6697 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698{
6699 struct audio_device *adev = (struct audio_device *)dev;
6700 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306701 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006702 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006703 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306704 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006705 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6706 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6707 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6708 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006709 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006710 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006711 bool force_haptic_path =
6712 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006713
kunleizdff872d2018-08-20 14:40:33 +08006714 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006715 is_usb_dev = false;
6716 devices = AUDIO_DEVICE_OUT_SPEAKER;
6717 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6718 __func__, devices);
6719 }
6720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6724
Mingming Yin3a941d42016-02-17 18:08:05 -08006725 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6726 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306727 devices, flags, &out->stream);
6728
6729
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006730 if (!out) {
6731 return -ENOMEM;
6732 }
6733
Haynes Mathew George204045b2015-02-25 20:32:03 -08006734 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006735 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306736 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006737 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006738 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006740 if (devices == AUDIO_DEVICE_NONE)
6741 devices = AUDIO_DEVICE_OUT_SPEAKER;
6742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006743 out->flags = flags;
6744 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006745 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006746 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006747 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306748 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306749 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6750 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6751 else
6752 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006753 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006754 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006755 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306756 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306757 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306758 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006759 out->hal_output_suspend_supported = 0;
6760 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306761 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306762 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306763 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006764
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306765 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306766 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006767 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6768
Aalique Grahame22e49102018-12-18 14:23:57 -08006769 if (direct_dev &&
6770 (audio_is_linear_pcm(out->format) ||
6771 config->format == AUDIO_FORMAT_DEFAULT) &&
6772 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6773 audio_format_t req_format = config->format;
6774 audio_channel_mask_t req_channel_mask = config->channel_mask;
6775 uint32_t req_sample_rate = config->sample_rate;
6776
6777 pthread_mutex_lock(&adev->lock);
6778 if (is_hdmi) {
6779 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6780 ret = read_hdmi_sink_caps(out);
6781 if (config->sample_rate == 0)
6782 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6783 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6784 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6785 if (config->format == AUDIO_FORMAT_DEFAULT)
6786 config->format = AUDIO_FORMAT_PCM_16_BIT;
6787 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006788 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6789 &config->format,
6790 &out->supported_formats[0],
6791 MAX_SUPPORTED_FORMATS,
6792 &config->channel_mask,
6793 &out->supported_channel_masks[0],
6794 MAX_SUPPORTED_CHANNEL_MASKS,
6795 &config->sample_rate,
6796 &out->supported_sample_rates[0],
6797 MAX_SUPPORTED_SAMPLE_RATES);
6798 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006799 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006800
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006801 pthread_mutex_unlock(&adev->lock);
6802 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006803 if (ret == -ENOSYS) {
6804 /* ignore and go with default */
6805 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006806 }
6807 // For MMAP NO IRQ, allow conversions in ADSP
6808 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6809 goto error_open;
6810 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006811 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006812 goto error_open;
6813 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006814
6815 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6816 config->sample_rate = req_sample_rate;
6817 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6818 config->channel_mask = req_channel_mask;
6819 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6820 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006821 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006822
6823 out->sample_rate = config->sample_rate;
6824 out->channel_mask = config->channel_mask;
6825 out->format = config->format;
6826 if (is_hdmi) {
6827 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6828 out->config = pcm_config_hdmi_multi;
6829 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6830 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6831 out->config = pcm_config_mmap_playback;
6832 out->stream.start = out_start;
6833 out->stream.stop = out_stop;
6834 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6835 out->stream.get_mmap_position = out_get_mmap_position;
6836 } else {
6837 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6838 out->config = pcm_config_hifi;
6839 }
6840
6841 out->config.rate = out->sample_rate;
6842 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6843 if (is_hdmi) {
6844 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6845 audio_bytes_per_sample(out->format));
6846 }
6847 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006848 }
6849
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006850 /* Check for VOIP usecase */
6851 if(out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) {
6852 if (!voice_extn_is_compress_voip_supported()) {
6853 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6854 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006855 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006856 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6857 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006858
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006859 out->config = default_pcm_config_voip_copp;
6860 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6861 out->config.rate = out->sample_rate;
6862 }
6863 } else {
6864 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6865 voice_extn_compress_voip_is_active(out->dev)) &&
6866 (voice_extn_compress_voip_is_config_supported(config))) {
6867 ret = voice_extn_compress_voip_open_output_stream(out);
6868 if (ret != 0) {
6869 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6870 __func__, ret);
6871 goto error_open;
6872 }
6873 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006874 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006875 } else if (audio_is_linear_pcm(out->format) &&
6876 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6877 out->channel_mask = config->channel_mask;
6878 out->sample_rate = config->sample_rate;
6879 out->format = config->format;
6880 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6881 // does this change?
6882 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6883 out->config.rate = config->sample_rate;
6884 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6885 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6886 audio_bytes_per_sample(config->format));
6887 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006888 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306889 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306890 pthread_mutex_lock(&adev->lock);
6891 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6892 pthread_mutex_unlock(&adev->lock);
6893
6894 // reject offload during card offline to allow
6895 // fallback to s/w paths
6896 if (offline) {
6897 ret = -ENODEV;
6898 goto error_open;
6899 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006900
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006901 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6902 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6903 ALOGE("%s: Unsupported Offload information", __func__);
6904 ret = -EINVAL;
6905 goto error_open;
6906 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006907
Atul Khare3fa6e542017-08-09 00:56:17 +05306908 if (config->offload_info.format == 0)
6909 config->offload_info.format = config->format;
6910 if (config->offload_info.sample_rate == 0)
6911 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006912
Mingming Yin90310102013-11-13 16:57:00 -08006913 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306914 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006915 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006916 ret = -EINVAL;
6917 goto error_open;
6918 }
6919
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006920 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6921 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6922 (audio_extn_passthru_is_passthrough_stream(out)) &&
6923 !((config->sample_rate == 48000) ||
6924 (config->sample_rate == 96000) ||
6925 (config->sample_rate == 192000))) {
6926 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6927 __func__, config->sample_rate, config->offload_info.format);
6928 ret = -EINVAL;
6929 goto error_open;
6930 }
6931
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006932 out->compr_config.codec = (struct snd_codec *)
6933 calloc(1, sizeof(struct snd_codec));
6934
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006935 if (!out->compr_config.codec) {
6936 ret = -ENOMEM;
6937 goto error_open;
6938 }
6939
Dhananjay Kumarac341582017-02-23 23:42:25 +05306940 out->stream.pause = out_pause;
6941 out->stream.resume = out_resume;
6942 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306943 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306944 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006945 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306946 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006947 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306948 } else {
6949 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6950 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006951 }
vivek mehta446c3962015-09-14 10:57:35 -07006952
6953 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006954 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6955 config->format == 0 && config->sample_rate == 0 &&
6956 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006957 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006958 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6959 } else {
6960 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6961 ret = -EEXIST;
6962 goto error_open;
6963 }
vivek mehta446c3962015-09-14 10:57:35 -07006964 }
6965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006966 if (config->offload_info.channel_mask)
6967 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006968 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006969 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006970 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006971 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306972 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006973 ret = -EINVAL;
6974 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006975 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006976
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006977 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006978 out->sample_rate = config->offload_info.sample_rate;
6979
Mingming Yin3ee55c62014-08-04 14:23:35 -07006980 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006981
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306982 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306983 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306984 audio_extn_dolby_send_ddp_endp_params(adev);
6985 audio_extn_dolby_set_dmid(adev);
6986 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006988 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006989 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006990 out->compr_config.codec->bit_rate =
6991 config->offload_info.bit_rate;
6992 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306993 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006994 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306995 /* Update bit width only for non passthrough usecases.
6996 * For passthrough usecases, the output will always be opened @16 bit
6997 */
6998 if (!audio_extn_passthru_is_passthrough_stream(out))
6999 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307000
7001 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7002 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7003 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7004
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007005 /*TODO: Do we need to change it for passthrough */
7006 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007007
Manish Dewangana6fc5442015-08-24 20:30:31 +05307008 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7009 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307010 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307011 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307012 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7013 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307014
7015 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7016 AUDIO_FORMAT_PCM) {
7017
7018 /*Based on platform support, configure appropriate alsa format for corresponding
7019 *hal input format.
7020 */
7021 out->compr_config.codec->format = hal_format_to_alsa(
7022 config->offload_info.format);
7023
Ashish Jain83a6cc22016-06-28 14:34:17 +05307024 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307025 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307026 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307027
Dhananjay Kumarac341582017-02-23 23:42:25 +05307028 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307029 *hal input format and alsa format might differ based on platform support.
7030 */
7031 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307032 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307033
7034 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7035
7036 /* Check if alsa session is configured with the same format as HAL input format,
7037 * if not then derive correct fragment size needed to accomodate the
7038 * conversion of HAL input format to alsa format.
7039 */
7040 audio_extn_utils_update_direct_pcm_fragment_size(out);
7041
7042 /*if hal input and output fragment size is different this indicates HAL input format is
7043 *not same as the alsa format
7044 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307045 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307046 /*Allocate a buffer to convert input data to the alsa configured format.
7047 *size of convert buffer is equal to the size required to hold one fragment size
7048 *worth of pcm data, this is because flinger does not write more than fragment_size
7049 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307050 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7051 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307052 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7053 ret = -ENOMEM;
7054 goto error_open;
7055 }
7056 }
7057 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7058 out->compr_config.fragment_size =
7059 audio_extn_passthru_get_buffer_size(&config->offload_info);
7060 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7061 } else {
7062 out->compr_config.fragment_size =
7063 platform_get_compress_offload_buffer_size(&config->offload_info);
7064 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7065 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007066
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307067 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7068 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7069 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007070 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307071 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007072
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307073 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7074 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7075 }
7076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007077 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7078 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007079
Manish Dewangan69426c82017-01-30 17:35:36 +05307080 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7081 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7082 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7083 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7084 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7085 } else {
7086 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7087 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007088
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307089 memset(&out->channel_map_param, 0,
7090 sizeof(struct audio_out_channel_map_param));
7091
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007092 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307093 out->send_next_track_params = false;
7094 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007095 out->offload_state = OFFLOAD_STATE_IDLE;
7096 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007097 out->writeAt.tv_sec = 0;
7098 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007099
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007100 audio_extn_dts_create_state_notifier_node(out->usecase);
7101
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007102 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7103 __func__, config->offload_info.version,
7104 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307105
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307106 /* Check if DSD audio format is supported in codec
7107 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307108 */
7109
7110 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307111 (!platform_check_codec_dsd_support(adev->platform) ||
7112 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307113 ret = -EINVAL;
7114 goto error_open;
7115 }
7116
Ashish Jain5106d362016-05-11 19:23:33 +05307117 /* Disable gapless if any of the following is true
7118 * passthrough playback
7119 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307120 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307121 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307122 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307123 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007124 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307125 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307126 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307127 check_and_set_gapless_mode(adev, false);
7128 } else
7129 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007130
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307131 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007132 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7133 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307134 if (config->format == AUDIO_FORMAT_DSD) {
7135 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7136 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7137 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007138
7139 create_offload_callback_thread(out);
7140
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007141 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007142 switch (config->sample_rate) {
7143 case 0:
7144 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7145 break;
7146 case 8000:
7147 case 16000:
7148 case 48000:
7149 out->sample_rate = config->sample_rate;
7150 break;
7151 default:
7152 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7153 config->sample_rate);
7154 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7155 ret = -EINVAL;
7156 goto error_open;
7157 }
7158 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7159 switch (config->channel_mask) {
7160 case AUDIO_CHANNEL_NONE:
7161 case AUDIO_CHANNEL_OUT_STEREO:
7162 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7163 break;
7164 default:
7165 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7166 config->channel_mask);
7167 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7168 ret = -EINVAL;
7169 goto error_open;
7170 }
7171 switch (config->format) {
7172 case AUDIO_FORMAT_DEFAULT:
7173 case AUDIO_FORMAT_PCM_16_BIT:
7174 out->format = AUDIO_FORMAT_PCM_16_BIT;
7175 break;
7176 default:
7177 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7178 config->format);
7179 config->format = AUDIO_FORMAT_PCM_16_BIT;
7180 ret = -EINVAL;
7181 goto error_open;
7182 }
7183
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307184 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007185 if (ret != 0) {
7186 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007187 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007188 goto error_open;
7189 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007190 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007191 switch (config->sample_rate) {
7192 case 0:
7193 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7194 break;
7195 case 8000:
7196 case 16000:
7197 case 48000:
7198 out->sample_rate = config->sample_rate;
7199 break;
7200 default:
7201 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7202 config->sample_rate);
7203 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7204 ret = -EINVAL;
7205 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007206 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007207 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7208 switch (config->channel_mask) {
7209 case AUDIO_CHANNEL_NONE:
7210 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7211 break;
7212 case AUDIO_CHANNEL_OUT_STEREO:
7213 out->channel_mask = config->channel_mask;
7214 break;
7215 default:
7216 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7217 config->channel_mask);
7218 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7219 ret = -EINVAL;
7220 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007221 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007222 switch (config->format) {
7223 case AUDIO_FORMAT_DEFAULT:
7224 out->format = AUDIO_FORMAT_PCM_16_BIT;
7225 break;
7226 case AUDIO_FORMAT_PCM_16_BIT:
7227 out->format = config->format;
7228 break;
7229 default:
7230 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7231 config->format);
7232 config->format = AUDIO_FORMAT_PCM_16_BIT;
7233 ret = -EINVAL;
7234 break;
7235 }
7236 if (ret != 0)
7237 goto error_open;
7238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007239 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7240 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007241 out->config.rate = out->sample_rate;
7242 out->config.channels =
7243 audio_channel_count_from_out_mask(out->channel_mask);
7244 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007245 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007246 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307247 unsigned int channels = 0;
7248 /*Update config params to default if not set by the caller*/
7249 if (config->sample_rate == 0)
7250 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7251 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7252 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7253 if (config->format == AUDIO_FORMAT_DEFAULT)
7254 config->format = AUDIO_FORMAT_PCM_16_BIT;
7255
7256 channels = audio_channel_count_from_out_mask(out->channel_mask);
7257
Varun Balaraje49253e2017-07-06 19:48:56 +05307258 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7259 out->usecase = get_interactive_usecase(adev);
7260 out->config = pcm_config_low_latency;
7261 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307262 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007263 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7264 out->flags);
7265 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007266 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7267 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7268 out->config = pcm_config_mmap_playback;
7269 out->stream.start = out_start;
7270 out->stream.stop = out_stop;
7271 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7272 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307273 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7274 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007275 out->hal_output_suspend_supported =
7276 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7277 out->dynamic_pm_qos_config_supported =
7278 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7279 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007280 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7281 } else {
7282 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7283 //the mixer path will be a string similar to "low-latency-playback resume"
7284 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7285 strlcat(out->pm_qos_mixer_path,
7286 " resume", MAX_MIXER_PATH_LEN);
7287 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7288 out->pm_qos_mixer_path);
7289 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307290 out->config = pcm_config_low_latency;
7291 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7292 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7293 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307294 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7295 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7296 if (out->config.period_size <= 0) {
7297 ALOGE("Invalid configuration period size is not valid");
7298 ret = -EINVAL;
7299 goto error_open;
7300 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007301 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7302 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7303 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007304 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7305 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7306 out->config = pcm_config_haptics_audio;
7307 if (force_haptic_path)
7308 adev->haptics_config = pcm_config_haptics_audio;
7309 else
7310 adev->haptics_config = pcm_config_haptics;
7311
7312 out->config.channels =
7313 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7314
7315 if (force_haptic_path) {
7316 out->config.channels = 1;
7317 adev->haptics_config.channels = 1;
7318 } else
7319 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307320 } else {
7321 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007322 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7323 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307324 }
7325 out->hal_ip_format = format = out->format;
7326 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7327 out->hal_op_format = pcm_format_to_hal(out->config.format);
7328 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7329 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007330 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307331 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307332 if (out->hal_ip_format != out->hal_op_format) {
7333 uint32_t buffer_size = out->config.period_size *
7334 format_to_bitwidth_table[out->hal_op_format] *
7335 out->config.channels;
7336 out->convert_buffer = calloc(1, buffer_size);
7337 if (out->convert_buffer == NULL){
7338 ALOGE("Allocation failed for convert buffer for size %d",
7339 out->compr_config.fragment_size);
7340 ret = -ENOMEM;
7341 goto error_open;
7342 }
7343 ALOGD("Convert buffer allocated of size %d", buffer_size);
7344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007345 }
7346
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007347 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7348 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307349
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007350 /* TODO remove this hardcoding and check why width is zero*/
7351 if (out->bit_width == 0)
7352 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307353 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007354 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007355 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307356 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307357 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007358 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007359 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7360 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007361 if(adev->primary_output == NULL)
7362 adev->primary_output = out;
7363 else {
7364 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007365 ret = -EEXIST;
7366 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007367 }
7368 }
7369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007370 /* Check if this usecase is already existing */
7371 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007372 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7373 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007374 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007375 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007376 ret = -EEXIST;
7377 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007378 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007380 pthread_mutex_unlock(&adev->lock);
7381
7382 out->stream.common.get_sample_rate = out_get_sample_rate;
7383 out->stream.common.set_sample_rate = out_set_sample_rate;
7384 out->stream.common.get_buffer_size = out_get_buffer_size;
7385 out->stream.common.get_channels = out_get_channels;
7386 out->stream.common.get_format = out_get_format;
7387 out->stream.common.set_format = out_set_format;
7388 out->stream.common.standby = out_standby;
7389 out->stream.common.dump = out_dump;
7390 out->stream.common.set_parameters = out_set_parameters;
7391 out->stream.common.get_parameters = out_get_parameters;
7392 out->stream.common.add_audio_effect = out_add_audio_effect;
7393 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7394 out->stream.get_latency = out_get_latency;
7395 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007396#ifdef NO_AUDIO_OUT
7397 out->stream.write = out_write_for_no_output;
7398#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007399 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007400#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007401 out->stream.get_render_position = out_get_render_position;
7402 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007403 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007404
Haynes Mathew George16081042017-05-31 17:16:49 -07007405 if (out->realtime)
7406 out->af_period_multiplier = af_period_multiplier;
7407 else
7408 out->af_period_multiplier = 1;
7409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007410 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007411 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007412 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007413
7414 config->format = out->stream.common.get_format(&out->stream.common);
7415 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7416 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307417 register_format(out->format, out->supported_formats);
7418 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7419 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007420
Aalique Grahame22e49102018-12-18 14:23:57 -08007421 out->error_log = error_log_create(
7422 ERROR_LOG_ENTRIES,
7423 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7424
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307425 /*
7426 By locking output stream before registering, we allow the callback
7427 to update stream's state only after stream's initial state is set to
7428 adev state.
7429 */
7430 lock_output_stream(out);
7431 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7432 pthread_mutex_lock(&adev->lock);
7433 out->card_status = adev->card_status;
7434 pthread_mutex_unlock(&adev->lock);
7435 pthread_mutex_unlock(&out->lock);
7436
Aalique Grahame22e49102018-12-18 14:23:57 -08007437 stream_app_type_cfg_init(&out->app_type_cfg);
7438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007439 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307440 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007441 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007442
7443 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7444 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7445 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007446 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307447 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007448 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007449 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307450 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007451 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7452 out->usecase, PCM_PLAYBACK);
7453 hdlr_stream_cfg.flags = out->flags;
7454 hdlr_stream_cfg.type = PCM_PLAYBACK;
7455 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7456 &hdlr_stream_cfg);
7457 if (ret) {
7458 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7459 out->adsp_hdlr_stream_handle = NULL;
7460 }
7461 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307462 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007463 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007464 if (ret < 0) {
7465 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7466 out->ip_hdlr_handle = NULL;
7467 }
7468 }
Derek Chenf939fb72018-11-13 13:34:41 -08007469
7470 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7471 calloc(1, sizeof(streams_output_ctxt_t));
7472 if (out_ctxt == NULL) {
7473 ALOGE("%s fail to allocate output ctxt", __func__);
7474 ret = -ENOMEM;
7475 goto error_open;
7476 }
7477 out_ctxt->output = out;
7478
7479 pthread_mutex_lock(&adev->lock);
7480 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7481 pthread_mutex_unlock(&adev->lock);
7482
Eric Laurent994a6932013-07-17 11:51:42 -07007483 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007484 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007485
7486error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307487 if (out->convert_buffer)
7488 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007489 free(out);
7490 *stream_out = NULL;
7491 ALOGD("%s: exit: ret %d", __func__, ret);
7492 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007493}
7494
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307495void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007496 struct audio_stream_out *stream)
7497{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007498 struct stream_out *out = (struct stream_out *)stream;
7499 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007500 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007501
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007502 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307503
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307504 // must deregister from sndmonitor first to prevent races
7505 // between the callback and close_stream
7506 audio_extn_snd_mon_unregister_listener(out);
7507
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007508 /* close adsp hdrl session before standby */
7509 if (out->adsp_hdlr_stream_handle) {
7510 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7511 if (ret)
7512 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7513 out->adsp_hdlr_stream_handle = NULL;
7514 }
7515
Manish Dewangan21a850a2017-08-14 12:03:55 +05307516 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007517 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7518 out->ip_hdlr_handle = NULL;
7519 }
7520
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007521 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307522 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007523 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307524 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307525 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007526 if(ret != 0)
7527 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7528 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007529 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007530 out_standby(&stream->common);
7531
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007532 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007533 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007534 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007535 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007536 if (out->compr_config.codec != NULL)
7537 free(out->compr_config.codec);
7538 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007539
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307540 out->a2dp_compress_mute = false;
7541
Varun Balaraje49253e2017-07-06 19:48:56 +05307542 if (is_interactive_usecase(out->usecase))
7543 free_interactive_usecase(adev, out->usecase);
7544
Ashish Jain83a6cc22016-06-28 14:34:17 +05307545 if (out->convert_buffer != NULL) {
7546 free(out->convert_buffer);
7547 out->convert_buffer = NULL;
7548 }
7549
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007550 if (adev->voice_tx_output == out)
7551 adev->voice_tx_output = NULL;
7552
Aalique Grahame22e49102018-12-18 14:23:57 -08007553 error_log_destroy(out->error_log);
7554 out->error_log = NULL;
7555
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307556 if (adev->primary_output == out)
7557 adev->primary_output = NULL;
7558
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007559 pthread_cond_destroy(&out->cond);
7560 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007561
7562 pthread_mutex_lock(&adev->lock);
7563 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7564 if (out_ctxt != NULL) {
7565 list_remove(&out_ctxt->list);
7566 free(out_ctxt);
7567 } else {
7568 ALOGW("%s, output stream already closed", __func__);
7569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007570 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007571 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007572 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007573}
7574
7575static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7576{
7577 struct audio_device *adev = (struct audio_device *)dev;
7578 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007579 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007580 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007581 int ret;
7582 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007583 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007584
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007585 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007586 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007587
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307588 if (!parms)
7589 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307590
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307591 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7592 if (ret >= 0) {
7593 /* When set to false, HAL should disable EC and NS */
7594 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7595 adev->bt_sco_on = true;
7596 else
7597 adev->bt_sco_on = false;
7598 }
7599
Naresh Tanniru4c630392014-05-12 01:05:52 +05307600 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007601 status = voice_set_parameters(adev, parms);
7602 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007603 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007604
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007605 status = platform_set_parameters(adev->platform, parms);
7606 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007607 goto done;
7608
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007609 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7610 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007611 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007612 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7613 adev->bluetooth_nrec = true;
7614 else
7615 adev->bluetooth_nrec = false;
7616 }
7617
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007618 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7619 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007620 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7621 adev->screen_off = false;
7622 else
7623 adev->screen_off = true;
7624 }
7625
Aalique Grahame22e49102018-12-18 14:23:57 -08007626#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007627 ret = str_parms_get_int(parms, "rotation", &val);
7628 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007629 bool reverse_speakers = false;
7630 switch(val) {
7631 // FIXME: note that the code below assumes that the speakers are in the correct placement
7632 // relative to the user when the device is rotated 90deg from its default rotation. This
7633 // assumption is device-specific, not platform-specific like this code.
7634 case 270:
7635 reverse_speakers = true;
7636 break;
7637 case 0:
7638 case 90:
7639 case 180:
7640 break;
7641 default:
7642 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007643 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007644 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007645 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007646 // check and set swap
7647 // - check if orientation changed and speaker active
7648 // - set rotation and cache the rotation value
7649 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007650 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007651 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007652#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007653
Mingming Yin514a8bc2014-07-29 15:22:21 -07007654 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7655 if (ret >= 0) {
7656 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7657 adev->bt_wb_speech_enabled = true;
7658 else
7659 adev->bt_wb_speech_enabled = false;
7660 }
7661
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007662 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7663 if (ret >= 0) {
7664 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307665 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007666 if (audio_is_output_device(val) &&
7667 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007668 ALOGV("cache new ext disp type and edid");
7669 ret = platform_get_ext_disp_type(adev->platform);
7670 if (ret < 0) {
7671 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307672 } else {
7673 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007674 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307675 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007676 /*
7677 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7678 * Per AudioPolicyManager, USB device is higher priority than WFD.
7679 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7680 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7681 * starting voice call on USB
7682 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007683 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307684 if (ret >= 0)
7685 audio_extn_usb_add_device(device, atoi(value));
7686
Zhou Song6f862822017-11-06 17:27:57 +08007687 if (!audio_extn_usb_is_tunnel_supported()) {
7688 ALOGV("detected USB connect .. disable proxy");
7689 adev->allow_afe_proxy_usage = false;
7690 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007691 }
7692 }
7693
7694 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7695 if (ret >= 0) {
7696 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307697 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007698 /*
7699 * The HDMI / Displayport disconnect handling has been moved to
7700 * audio extension to ensure that its parameters are not
7701 * invalidated prior to updating sysfs of the disconnect event
7702 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7703 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307704 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007705 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307706 if (ret >= 0)
7707 audio_extn_usb_remove_device(device, atoi(value));
7708
Zhou Song6f862822017-11-06 17:27:57 +08007709 if (!audio_extn_usb_is_tunnel_supported()) {
7710 ALOGV("detected USB disconnect .. enable proxy");
7711 adev->allow_afe_proxy_usage = true;
7712 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007713 }
7714 }
7715
Aalique Grahame22e49102018-12-18 14:23:57 -08007716 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007717 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007718
7719 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007720 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307721 struct audio_usecase *usecase;
7722 struct listnode *node;
7723 list_for_each(node, &adev->usecase_list) {
7724 usecase = node_to_item(node, struct audio_usecase, list);
7725 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007726 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307727 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007728
7729 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307730 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007731 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307732 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307733 //force device switch to re configure encoder
7734 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307735 audio_extn_a2dp_set_handoff_mode(false);
7736 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307737 break;
7738 }
7739 }
7740 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007741
7742 //handle vr audio setparam
7743 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7744 value, sizeof(value));
7745 if (ret >= 0) {
7746 ALOGI("Setting vr mode to be %s", value);
7747 if (!strncmp(value, "true", 4)) {
7748 adev->vr_audio_mode_enabled = true;
7749 ALOGI("Setting vr mode to true");
7750 } else if (!strncmp(value, "false", 5)) {
7751 adev->vr_audio_mode_enabled = false;
7752 ALOGI("Setting vr mode to false");
7753 } else {
7754 ALOGI("wrong vr mode set");
7755 }
7756 }
7757
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307758 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007759done:
7760 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007761 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307762error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007763 ALOGV("%s: exit with code(%d)", __func__, status);
7764 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007765}
7766
7767static char* adev_get_parameters(const struct audio_hw_device *dev,
7768 const char *keys)
7769{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307770 ALOGD("%s:%s", __func__, keys);
7771
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007772 struct audio_device *adev = (struct audio_device *)dev;
7773 struct str_parms *reply = str_parms_create();
7774 struct str_parms *query = str_parms_create_str(keys);
7775 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307776 char value[256] = {0};
7777 int ret = 0;
7778
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007779 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007780 if (reply) {
7781 str_parms_destroy(reply);
7782 }
7783 if (query) {
7784 str_parms_destroy(query);
7785 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007786 ALOGE("adev_get_parameters: failed to create query or reply");
7787 return NULL;
7788 }
7789
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007790 //handle vr audio getparam
7791
7792 ret = str_parms_get_str(query,
7793 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7794 value, sizeof(value));
7795
7796 if (ret >= 0) {
7797 bool vr_audio_enabled = false;
7798 pthread_mutex_lock(&adev->lock);
7799 vr_audio_enabled = adev->vr_audio_mode_enabled;
7800 pthread_mutex_unlock(&adev->lock);
7801
7802 ALOGI("getting vr mode to %d", vr_audio_enabled);
7803
7804 if (vr_audio_enabled) {
7805 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7806 "true");
7807 goto exit;
7808 } else {
7809 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7810 "false");
7811 goto exit;
7812 }
7813 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007814
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007815 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007816 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007817 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007818 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007819 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307820 pthread_mutex_unlock(&adev->lock);
7821
Naresh Tannirud7205b62014-06-20 02:54:48 +05307822exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007823 str = str_parms_to_str(reply);
7824 str_parms_destroy(query);
7825 str_parms_destroy(reply);
7826
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307827 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007828 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007829}
7830
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007831static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007832{
7833 return 0;
7834}
7835
7836static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7837{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007838 int ret;
7839 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007840
7841 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7842
Haynes Mathew George5191a852013-09-11 14:19:36 -07007843 pthread_mutex_lock(&adev->lock);
7844 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007845 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007846 pthread_mutex_unlock(&adev->lock);
7847 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007848}
7849
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007850static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7851 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007852{
7853 return -ENOSYS;
7854}
7855
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007856static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7857 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007858{
7859 return -ENOSYS;
7860}
7861
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007862static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7863 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007864{
7865 return -ENOSYS;
7866}
7867
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007868static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7869 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007870{
7871 return -ENOSYS;
7872}
7873
7874static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7875{
7876 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007877 struct listnode *node;
7878 struct audio_usecase *usecase = NULL;
7879 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08007880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007881 pthread_mutex_lock(&adev->lock);
7882 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007883 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007884 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007885 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007886 list_for_each(node, &adev->usecase_list) {
7887 usecase = node_to_item(node, struct audio_usecase, list);
7888 if (usecase->type == VOICE_CALL)
7889 break;
7890 }
7891 if (usecase &&
7892 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7893 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7894 true);
7895 if (ret != 0) {
7896 /* default service interval was successfully updated,
7897 reopen USB backend with new service interval */
7898 check_usecases_codec_backend(adev,
7899 usecase,
7900 usecase->out_snd_device);
7901 }
7902 }
7903
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007904 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007905 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007906 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08007907 // restore device for other active usecases after stop call
7908 list_for_each(node, &adev->usecase_list) {
7909 usecase = node_to_item(node, struct audio_usecase, list);
7910 select_devices(adev, usecase->id);
7911 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007912 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007913 }
7914 pthread_mutex_unlock(&adev->lock);
7915 return 0;
7916}
7917
7918static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7919{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007920 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007921 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007922
7923 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007924 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007925 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007926
Derek Chend2530072014-11-24 12:39:14 -08007927 if (adev->ext_hw_plugin)
7928 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007929
7930 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007931 pthread_mutex_unlock(&adev->lock);
7932
7933 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007934}
7935
7936static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7937{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007938 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007939 return 0;
7940}
7941
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007942static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007943 const struct audio_config *config)
7944{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007945 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007946
Aalique Grahame22e49102018-12-18 14:23:57 -08007947 /* Don't know if USB HIFI in this context so use true to be conservative */
7948 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7949 true /*is_usb_hifi */) != 0)
7950 return 0;
7951
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007952 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7953 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007954}
7955
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007956static bool adev_input_allow_hifi_record(struct audio_device *adev,
7957 audio_devices_t devices,
7958 audio_input_flags_t flags,
7959 audio_source_t source) {
7960 const bool allowed = true;
7961
7962 if (!audio_is_usb_in_device(devices))
7963 return !allowed;
7964
7965 switch (flags) {
7966 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007967 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007968 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7969 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007970 default:
7971 return !allowed;
7972 }
7973
7974 switch (source) {
7975 case AUDIO_SOURCE_DEFAULT:
7976 case AUDIO_SOURCE_MIC:
7977 case AUDIO_SOURCE_UNPROCESSED:
7978 break;
7979 default:
7980 return !allowed;
7981 }
7982
7983 switch (adev->mode) {
7984 case 0:
7985 break;
7986 default:
7987 return !allowed;
7988 }
7989
7990 return allowed;
7991}
7992
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007993static int adev_update_voice_comm_input_stream(struct stream_in *in,
7994 struct audio_config *config)
7995{
7996 bool valid_rate = (config->sample_rate == 8000 ||
7997 config->sample_rate == 16000 ||
7998 config->sample_rate == 32000 ||
7999 config->sample_rate == 48000);
8000 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8001
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008002 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008003 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008004 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8005 in->config = default_pcm_config_voip_copp;
8006 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8007 DEFAULT_VOIP_BUF_DURATION_MS,
8008 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008009 } else {
8010 ALOGW("%s No valid input in voip, use defaults"
8011 "sample rate %u, channel mask 0x%X",
8012 __func__, config->sample_rate, in->channel_mask);
8013 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008014 in->config.rate = config->sample_rate;
8015 in->sample_rate = config->sample_rate;
8016 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008017 //XXX needed for voice_extn_compress_voip_open_input_stream
8018 in->config.rate = config->sample_rate;
8019 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8020 voice_extn_compress_voip_is_active(in->dev)) &&
8021 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8022 valid_rate && valid_ch) {
8023 voice_extn_compress_voip_open_input_stream(in);
8024 // update rate entries to match config from AF
8025 in->config.rate = config->sample_rate;
8026 in->sample_rate = config->sample_rate;
8027 } else {
8028 ALOGW("%s compress voip not active, use defaults", __func__);
8029 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008030 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008031 return 0;
8032}
8033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008034static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008035 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008036 audio_devices_t devices,
8037 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008038 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308039 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008040 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008041 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008042{
8043 struct audio_device *adev = (struct audio_device *)dev;
8044 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008045 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008046 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008047 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308048 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008049 bool is_usb_dev = audio_is_usb_in_device(devices);
8050 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8051 devices,
8052 flags,
8053 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308054
kunleizdff872d2018-08-20 14:40:33 +08008055 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008056 is_usb_dev = false;
8057 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8058 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8059 __func__, devices);
8060 }
8061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008062 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008063
8064 if (!(is_usb_dev && may_use_hifi_record)) {
8065 if (config->sample_rate == 0)
8066 config->sample_rate = 48000;
8067 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8068 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8069 if (config->format == AUDIO_FORMAT_DEFAULT)
8070 config->format = AUDIO_FORMAT_PCM_16_BIT;
8071
8072 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8073
Aalique Grahame22e49102018-12-18 14:23:57 -08008074 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8075 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008076 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308077 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008078
8079 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008080
8081 if (!in) {
8082 ALOGE("failed to allocate input stream");
8083 return -ENOMEM;
8084 }
8085
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308086 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308087 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8088 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008089 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008090 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008092 in->stream.common.get_sample_rate = in_get_sample_rate;
8093 in->stream.common.set_sample_rate = in_set_sample_rate;
8094 in->stream.common.get_buffer_size = in_get_buffer_size;
8095 in->stream.common.get_channels = in_get_channels;
8096 in->stream.common.get_format = in_get_format;
8097 in->stream.common.set_format = in_set_format;
8098 in->stream.common.standby = in_standby;
8099 in->stream.common.dump = in_dump;
8100 in->stream.common.set_parameters = in_set_parameters;
8101 in->stream.common.get_parameters = in_get_parameters;
8102 in->stream.common.add_audio_effect = in_add_audio_effect;
8103 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8104 in->stream.set_gain = in_set_gain;
8105 in->stream.read = in_read;
8106 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008107 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308108 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008109 in->stream.set_microphone_direction = in_set_microphone_direction;
8110 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008111 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008112
8113 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008114 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008115 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008116 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008117 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008118 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008119 in->bit_width = 16;
8120 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008121 in->direction = MIC_DIRECTION_UNSPECIFIED;
8122 in->zoom = 0;
Haynes Mathew George46740472017-10-27 18:40:12 -07008123
Aalique Grahame22e49102018-12-18 14:23:57 -08008124 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
8125 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8126 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8127 /* Force channel config requested to mono if incall
8128 record is being requested for only uplink/downlink */
8129 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8130 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8131 ret = -EINVAL;
8132 goto err_open;
8133 }
8134 }
8135
Haynes Mathew George46740472017-10-27 18:40:12 -07008136 /* Update config params with the requested sample rate and channels */
8137 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
8138 (adev->mode != AUDIO_MODE_IN_CALL)) {
8139 ret = -EINVAL;
8140 goto err_open;
8141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008142
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008143 if (is_usb_dev && may_use_hifi_record) {
8144 /* HiFi record selects an appropriate format, channel, rate combo
8145 depending on sink capabilities*/
8146 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8147 &config->format,
8148 &in->supported_formats[0],
8149 MAX_SUPPORTED_FORMATS,
8150 &config->channel_mask,
8151 &in->supported_channel_masks[0],
8152 MAX_SUPPORTED_CHANNEL_MASKS,
8153 &config->sample_rate,
8154 &in->supported_sample_rates[0],
8155 MAX_SUPPORTED_SAMPLE_RATES);
8156 if (ret != 0) {
8157 ret = -EINVAL;
8158 goto err_open;
8159 }
8160 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008161 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308162 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308163 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8164 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8165 in->config.format = PCM_FORMAT_S32_LE;
8166 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308167 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8168 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8169 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8170 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8171 bool ret_error = false;
8172 in->bit_width = 24;
8173 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8174 from HAL is 24_packed and 8_24
8175 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8176 24_packed return error indicating supported format is 24_packed
8177 *> In case of any other source requesting 24 bit or float return error
8178 indicating format supported is 16 bit only.
8179
8180 on error flinger will retry with supported format passed
8181 */
8182 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8183 (source != AUDIO_SOURCE_CAMCORDER)) {
8184 config->format = AUDIO_FORMAT_PCM_16_BIT;
8185 if (config->sample_rate > 48000)
8186 config->sample_rate = 48000;
8187 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008188 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8189 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308190 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8191 ret_error = true;
8192 }
8193
8194 if (ret_error) {
8195 ret = -EINVAL;
8196 goto err_open;
8197 }
8198 }
8199
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008200 in->channel_mask = config->channel_mask;
8201 in->format = config->format;
8202
8203 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308204
8205 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8206 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8207 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8208 else {
8209 ret = -EINVAL;
8210 goto err_open;
8211 }
8212 }
8213
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008214 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8215 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8216 is_low_latency = true;
8217#if LOW_LATENCY_CAPTURE_USE_CASE
8218 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8219#endif
8220 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008221 if (!in->realtime) {
8222 in->config = pcm_config_audio_capture;
8223 frame_size = audio_stream_in_frame_size(&in->stream);
8224 buffer_size = get_input_buffer_size(config->sample_rate,
8225 config->format,
8226 channel_count,
8227 is_low_latency);
8228 in->config.period_size = buffer_size / frame_size;
8229 in->config.rate = config->sample_rate;
8230 in->af_period_multiplier = 1;
8231 } else {
8232 // period size is left untouched for rt mode playback
8233 in->config = pcm_config_audio_capture_rt;
8234 in->af_period_multiplier = af_period_multiplier;
8235 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008236 }
8237
8238 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8239 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8240 in->realtime = 0;
8241 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8242 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008243 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08008244 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008245 in->stream.start = in_start;
8246 in->stream.stop = in_stop;
8247 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8248 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008249 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008250 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8251 } else if (in->realtime) {
8252 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008253 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008254 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008255 in->sample_rate = in->config.rate;
8256 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008257 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008258 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8259 in->config = pcm_config_audio_capture;
8260 frame_size = audio_stream_in_frame_size(&in->stream);
8261 buffer_size = get_input_buffer_size(config->sample_rate,
8262 config->format,
8263 channel_count,
8264 false /*is_low_latency*/);
8265 in->config.period_size = buffer_size / frame_size;
8266 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008267 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008268 switch (config->format) {
8269 case AUDIO_FORMAT_PCM_32_BIT:
8270 in->bit_width = 32;
8271 break;
8272 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8273 case AUDIO_FORMAT_PCM_8_24_BIT:
8274 in->bit_width = 24;
8275 break;
8276 default:
8277 in->bit_width = 16;
8278 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008279 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008280 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008281 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308282 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008283 if (config->sample_rate == 0)
8284 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8285 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8286 config->sample_rate != 8000) {
8287 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8288 ret = -EINVAL;
8289 goto err_open;
8290 }
8291 if (config->format == AUDIO_FORMAT_DEFAULT)
8292 config->format = AUDIO_FORMAT_PCM_16_BIT;
8293 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8294 config->format = AUDIO_FORMAT_PCM_16_BIT;
8295 ret = -EINVAL;
8296 goto err_open;
8297 }
8298
8299 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8300 in->config = pcm_config_afe_proxy_record;
8301 in->config.channels = channel_count;
8302 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308303 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008304 in->af_period_multiplier = 1;
8305 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8306 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8307 (config->sample_rate == 8000 ||
8308 config->sample_rate == 16000 ||
8309 config->sample_rate == 32000 ||
8310 config->sample_rate == 48000) &&
8311 channel_count == 1) {
8312 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8313 in->config = pcm_config_audio_capture;
8314 frame_size = audio_stream_in_frame_size(&in->stream);
8315 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8316 config->sample_rate,
8317 config->format,
8318 channel_count, false /*is_low_latency*/);
8319 in->config.period_size = buffer_size / frame_size;
8320 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8321 in->config.rate = config->sample_rate;
8322 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008323 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308324 int ret_val;
8325 pthread_mutex_lock(&adev->lock);
8326 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8327 in, config, &channel_mask_updated);
8328 pthread_mutex_unlock(&adev->lock);
8329
8330 if (!ret_val) {
8331 if (channel_mask_updated == true) {
8332 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8333 __func__, config->channel_mask);
8334 ret = -EINVAL;
8335 goto err_open;
8336 }
8337 ALOGD("%s: created multi-channel session succesfully",__func__);
8338 } else if (audio_extn_compr_cap_enabled() &&
8339 audio_extn_compr_cap_format_supported(config->format) &&
8340 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8341 audio_extn_compr_cap_init(in);
8342 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05308343 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05308344 ret = audio_extn_cin_configure_input_stream(in);
8345 if (ret)
8346 goto err_open;
8347 } else {
8348 in->config = pcm_config_audio_capture;
8349 in->config.rate = config->sample_rate;
8350 in->config.format = pcm_format_from_audio_format(config->format);
8351 in->config.channels = channel_count;
8352 in->sample_rate = config->sample_rate;
8353 in->format = config->format;
8354 frame_size = audio_stream_in_frame_size(&in->stream);
8355 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008356 config->format,
8357 channel_count,
8358 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008359 /* prevent division-by-zero */
8360 if (frame_size == 0) {
8361 ALOGE("%s: Error frame_size==0", __func__);
8362 ret = -EINVAL;
8363 goto err_open;
8364 }
8365
Revathi Uddarajud2634032017-12-07 14:42:34 +05308366 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008367 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008368
Revathi Uddarajud2634032017-12-07 14:42:34 +05308369 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8370 /* optionally use VOIP usecase depending on config(s) */
8371 ret = adev_update_voice_comm_input_stream(in, config);
8372 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008373
Revathi Uddarajud2634032017-12-07 14:42:34 +05308374 if (ret) {
8375 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8376 goto err_open;
8377 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008378 }
kunleiz28c73e72019-03-27 17:24:04 +08008379#ifdef CONCURRENT_CAPTURE_ENABLED
8380 /* Acquire lock to avoid two concurrent use cases initialized to
8381 same pcm record use case */
8382
8383 pthread_mutex_lock(&adev->lock);
8384 if (in->usecase == USECASE_AUDIO_RECORD) {
8385 if (!(adev->pcm_record_uc_state)) {
8386 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8387 adev->pcm_record_uc_state = 1;
8388 } else {
8389 /* Assign compress record use case for second record */
8390 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8391 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8392 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8393 }
8394 }
8395 pthread_mutex_unlock(&adev->lock);
8396#endif
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008397 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308398 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8399 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008400 devices, flags, in->format,
8401 in->sample_rate, in->bit_width,
8402 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308403 register_format(in->format, in->supported_formats);
8404 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8405 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308406
Aalique Grahame22e49102018-12-18 14:23:57 -08008407 in->error_log = error_log_create(
8408 ERROR_LOG_ENTRIES,
8409 1000000000 /* aggregate consecutive identical errors within one second */);
8410
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008411 /* This stream could be for sound trigger lab,
8412 get sound trigger pcm if present */
8413 audio_extn_sound_trigger_check_and_get_session(in);
8414
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308415 lock_input_stream(in);
8416 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8417 pthread_mutex_lock(&adev->lock);
8418 in->card_status = adev->card_status;
8419 pthread_mutex_unlock(&adev->lock);
8420 pthread_mutex_unlock(&in->lock);
8421
Aalique Grahame22e49102018-12-18 14:23:57 -08008422 stream_app_type_cfg_init(&in->app_type_cfg);
8423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008424 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008425
8426 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8427 calloc(1, sizeof(streams_input_ctxt_t));
8428 if (in_ctxt == NULL) {
8429 ALOGE("%s fail to allocate input ctxt", __func__);
8430 ret = -ENOMEM;
8431 goto err_open;
8432 }
8433 in_ctxt->input = in;
8434
8435 pthread_mutex_lock(&adev->lock);
8436 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8437 pthread_mutex_unlock(&adev->lock);
8438
Eric Laurent994a6932013-07-17 11:51:42 -07008439 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008440 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441
8442err_open:
8443 free(in);
8444 *stream_in = NULL;
8445 return ret;
8446}
8447
8448static void adev_close_input_stream(struct audio_hw_device *dev,
8449 struct audio_stream_in *stream)
8450{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008451 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008452 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008453 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308454
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308455 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008456
kunleiz70e57612018-12-28 17:50:23 +08008457 /* must deregister from sndmonitor first to prevent races
8458 * between the callback and close_stream
8459 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308460 audio_extn_snd_mon_unregister_listener(stream);
8461
kunleiz70e57612018-12-28 17:50:23 +08008462 /* Disable echo reference if there are no active input, hfp call
8463 * and sound trigger while closing input stream
8464 */
8465 if (!adev->active_input &&
8466 !audio_extn_hfp_is_active(adev) &&
8467 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008468 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008469 else
8470 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308471
Pallavid7c7a272018-01-16 11:22:55 +05308472 if (in == NULL) {
8473 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8474 return;
8475 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008476 error_log_destroy(in->error_log);
8477 in->error_log = NULL;
8478
Pallavid7c7a272018-01-16 11:22:55 +05308479
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008480 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308481 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008482 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308483 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008484 if (ret != 0)
8485 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8486 __func__, ret);
8487 } else
8488 in_standby(&stream->common);
8489
Revathi Uddarajud2634032017-12-07 14:42:34 +05308490 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308491 if (in->usecase == USECASE_AUDIO_RECORD) {
8492 adev->pcm_record_uc_state = 0;
8493 }
8494
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008495 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008496 audio_extn_ssr_deinit();
8497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498
Garmond Leunge2433c32017-09-28 21:51:22 -07008499 if (audio_extn_ffv_get_stream() == in) {
8500 audio_extn_ffv_stream_deinit();
8501 }
8502
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308503 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008504 audio_extn_compr_cap_format_supported(in->config.format))
8505 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308506
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308507 if (audio_extn_cin_attached_usecase(in->usecase))
8508 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008509
Mingming Yinfd7607b2016-01-22 12:48:44 -08008510 if (in->is_st_session) {
8511 ALOGV("%s: sound trigger pcm stop lab", __func__);
8512 audio_extn_sound_trigger_stop_lab(in);
8513 }
Derek Chenf939fb72018-11-13 13:34:41 -08008514 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8515 if (in_ctxt != NULL) {
8516 list_remove(&in_ctxt->list);
8517 free(in_ctxt);
8518 } else {
8519 ALOGW("%s, input stream already closed", __func__);
8520 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008521 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308522 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008523 return;
8524}
8525
Aalique Grahame22e49102018-12-18 14:23:57 -08008526/* verifies input and output devices and their capabilities.
8527 *
8528 * This verification is required when enabling extended bit-depth or
8529 * sampling rates, as not all qcom products support it.
8530 *
8531 * Suitable for calling only on initialization such as adev_open().
8532 * It fills the audio_device use_case_table[] array.
8533 *
8534 * Has a side-effect that it needs to configure audio routing / devices
8535 * in order to power up the devices and read the device parameters.
8536 * It does not acquire any hw device lock. Should restore the devices
8537 * back to "normal state" upon completion.
8538 */
8539static int adev_verify_devices(struct audio_device *adev)
8540{
8541 /* enumeration is a bit difficult because one really wants to pull
8542 * the use_case, device id, etc from the hidden pcm_device_table[].
8543 * In this case there are the following use cases and device ids.
8544 *
8545 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8546 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8547 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8548 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8549 * [USECASE_AUDIO_RECORD] = {0, 0},
8550 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8551 * [USECASE_VOICE_CALL] = {2, 2},
8552 *
8553 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8554 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8555 */
8556
8557 /* should be the usecases enabled in adev_open_input_stream() */
8558 static const int test_in_usecases[] = {
8559 USECASE_AUDIO_RECORD,
8560 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8561 };
8562 /* should be the usecases enabled in adev_open_output_stream()*/
8563 static const int test_out_usecases[] = {
8564 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8565 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8566 };
8567 static const usecase_type_t usecase_type_by_dir[] = {
8568 PCM_PLAYBACK,
8569 PCM_CAPTURE,
8570 };
8571 static const unsigned flags_by_dir[] = {
8572 PCM_OUT,
8573 PCM_IN,
8574 };
8575
8576 size_t i;
8577 unsigned dir;
8578 const unsigned card_id = adev->snd_card;
8579
8580 for (dir = 0; dir < 2; ++dir) {
8581 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8582 const unsigned flags_dir = flags_by_dir[dir];
8583 const size_t testsize =
8584 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8585 const int *testcases =
8586 dir ? test_in_usecases : test_out_usecases;
8587 const audio_devices_t audio_device =
8588 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8589
8590 for (i = 0; i < testsize; ++i) {
8591 const audio_usecase_t audio_usecase = testcases[i];
8592 int device_id;
8593 struct pcm_params **pparams;
8594 struct stream_out out;
8595 struct stream_in in;
8596 struct audio_usecase uc_info;
8597 int retval;
8598
8599 pparams = &adev->use_case_table[audio_usecase];
8600 pcm_params_free(*pparams); /* can accept null input */
8601 *pparams = NULL;
8602
8603 /* find the device ID for the use case (signed, for error) */
8604 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8605 if (device_id < 0)
8606 continue;
8607
8608 /* prepare structures for device probing */
8609 memset(&uc_info, 0, sizeof(uc_info));
8610 uc_info.id = audio_usecase;
8611 uc_info.type = usecase_type;
8612 if (dir) {
8613 adev->active_input = &in;
8614 memset(&in, 0, sizeof(in));
8615 in.device = audio_device;
8616 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8617 uc_info.stream.in = &in;
8618 } else {
8619 adev->active_input = NULL;
8620 }
8621 memset(&out, 0, sizeof(out));
8622 out.devices = audio_device; /* only field needed in select_devices */
8623 uc_info.stream.out = &out;
8624 uc_info.devices = audio_device;
8625 uc_info.in_snd_device = SND_DEVICE_NONE;
8626 uc_info.out_snd_device = SND_DEVICE_NONE;
8627 list_add_tail(&adev->usecase_list, &uc_info.list);
8628
8629 /* select device - similar to start_(in/out)put_stream() */
8630 retval = select_devices(adev, audio_usecase);
8631 if (retval >= 0) {
8632 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8633#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008634 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008635 if (*pparams) {
8636 ALOGV("%s: (%s) card %d device %d", __func__,
8637 dir ? "input" : "output", card_id, device_id);
8638 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8639 } else {
8640 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8641 }
8642#endif
8643 }
8644
8645 /* deselect device - similar to stop_(in/out)put_stream() */
8646 /* 1. Get and set stream specific mixer controls */
8647 retval = disable_audio_route(adev, &uc_info);
8648 /* 2. Disable the rx device */
8649 retval = disable_snd_device(adev,
8650 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8651 list_remove(&uc_info.list);
8652 }
8653 }
8654 adev->active_input = NULL; /* restore adev state */
8655 return 0;
8656}
8657
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308658int adev_create_audio_patch(struct audio_hw_device *dev,
8659 unsigned int num_sources,
8660 const struct audio_port_config *sources,
8661 unsigned int num_sinks,
8662 const struct audio_port_config *sinks,
8663 audio_patch_handle_t *handle)
8664{
Derek Chenf939fb72018-11-13 13:34:41 -08008665 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308666
Derek Chenf939fb72018-11-13 13:34:41 -08008667 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8668 num_sources,
8669 sources,
8670 num_sinks,
8671 sinks,
8672 handle);
8673 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8674 num_sources,
8675 sources,
8676 num_sinks,
8677 sinks,
8678 handle);
8679 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308680}
8681
8682int adev_release_audio_patch(struct audio_hw_device *dev,
8683 audio_patch_handle_t handle)
8684{
Derek Chenf939fb72018-11-13 13:34:41 -08008685 int ret;
8686
8687 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8688 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8689 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308690}
8691
8692int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8693{
8694 return audio_extn_hw_loopback_get_audio_port(dev, config);
8695}
8696
8697int adev_set_audio_port_config(struct audio_hw_device *dev,
8698 const struct audio_port_config *config)
8699{
8700 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8701}
8702
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008703static int adev_dump(const audio_hw_device_t *device __unused,
8704 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008705{
8706 return 0;
8707}
8708
8709static int adev_close(hw_device_t *device)
8710{
Aalique Grahame22e49102018-12-18 14:23:57 -08008711 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008712 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008713
8714 if (!adev)
8715 return 0;
8716
8717 pthread_mutex_lock(&adev_init_lock);
8718
8719 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308720 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008721 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008722 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008723 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008724 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308725 audio_extn_utils_release_streams_cfg_lists(
8726 &adev->streams_output_cfg_list,
8727 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308728 if (audio_extn_qaf_is_enabled())
8729 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008730 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008731 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008732 free(adev->snd_dev_ref_cnt);
8733 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008734 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8735 pcm_params_free(adev->use_case_table[i]);
8736 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008737 if (adev->adm_deinit)
8738 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308739 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008740 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308741 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308742 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008743 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308744 if (adev->device_cfg_params) {
8745 free(adev->device_cfg_params);
8746 adev->device_cfg_params = NULL;
8747 }
Derek Chend2530072014-11-24 12:39:14 -08008748 if(adev->ext_hw_plugin)
8749 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008750 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008751 free(device);
8752 adev = NULL;
8753 }
8754 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308755 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008756 return 0;
8757}
8758
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008759/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8760 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8761 * just that it _might_ work.
8762 */
8763static int period_size_is_plausible_for_low_latency(int period_size)
8764{
8765 switch (period_size) {
8766 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008767 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008768 case 240:
8769 case 320:
8770 case 480:
8771 return 1;
8772 default:
8773 return 0;
8774 }
8775}
8776
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308777static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8778{
8779 bool is_snd_card_status = false;
8780 bool is_ext_device_status = false;
8781 char value[32];
8782 int card = -1;
8783 card_status_t status;
8784
8785 if (cookie != adev || !parms)
8786 return;
8787
8788 if (!parse_snd_card_status(parms, &card, &status)) {
8789 is_snd_card_status = true;
8790 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8791 is_ext_device_status = true;
8792 } else {
8793 // not a valid event
8794 return;
8795 }
8796
8797 pthread_mutex_lock(&adev->lock);
8798 if (card == adev->snd_card || is_ext_device_status) {
8799 if (is_snd_card_status && adev->card_status != status) {
8800 adev->card_status = status;
8801 platform_snd_card_update(adev->platform, status);
8802 audio_extn_fm_set_parameters(adev, parms);
8803 } else if (is_ext_device_status) {
8804 platform_set_parameters(adev->platform, parms);
8805 }
8806 }
8807 pthread_mutex_unlock(&adev->lock);
8808 return;
8809}
8810
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308811/* out and adev lock held */
8812static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8813{
8814 struct audio_usecase *uc_info;
8815 float left_p;
8816 float right_p;
8817 audio_devices_t devices;
8818
8819 uc_info = get_usecase_from_list(adev, out->usecase);
8820 if (uc_info == NULL) {
8821 ALOGE("%s: Could not find the usecase (%d) in the list",
8822 __func__, out->usecase);
8823 return -EINVAL;
8824 }
8825
8826 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8827 out->usecase, use_case_table[out->usecase]);
8828
8829 if (restore) {
8830 // restore A2DP device for active usecases and unmute if required
8831 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8832 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8833 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8834 select_devices(adev, uc_info->id);
8835 pthread_mutex_lock(&out->compr_mute_lock);
8836 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8837 (out->a2dp_compress_mute)) {
8838 out->a2dp_compress_mute = false;
8839 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8840 }
8841 pthread_mutex_unlock(&out->compr_mute_lock);
8842 }
8843 } else {
8844 // mute compress stream if suspended
8845 pthread_mutex_lock(&out->compr_mute_lock);
8846 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8847 (!out->a2dp_compress_mute)) {
8848 if (!out->standby) {
8849 ALOGD("%s: selecting speaker and muting stream", __func__);
8850 devices = out->devices;
8851 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8852 left_p = out->volume_l;
8853 right_p = out->volume_r;
8854 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8855 compress_pause(out->compr);
8856 out_set_compr_volume(&out->stream, (float)0, (float)0);
8857 out->a2dp_compress_mute = true;
8858 select_devices(adev, out->usecase);
8859 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8860 compress_resume(out->compr);
8861 out->devices = devices;
8862 out->volume_l = left_p;
8863 out->volume_r = right_p;
8864 }
8865 }
8866 pthread_mutex_unlock(&out->compr_mute_lock);
8867 }
8868 ALOGV("%s: exit", __func__);
8869 return 0;
8870}
8871
8872int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8873{
8874 int ret = 0;
8875
8876 lock_output_stream(out);
8877 pthread_mutex_lock(&adev->lock);
8878
8879 ret = check_a2dp_restore_l(adev, out, restore);
8880
8881 pthread_mutex_unlock(&adev->lock);
8882 pthread_mutex_unlock(&out->lock);
8883 return ret;
8884}
8885
Haynes Mathew George01156f92018-04-13 15:29:54 -07008886void adev_on_battery_status_changed(bool charging)
8887{
8888 pthread_mutex_lock(&adev->lock);
8889 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8890 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008891 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008892 pthread_mutex_unlock(&adev->lock);
8893}
8894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008895static int adev_open(const hw_module_t *module, const char *name,
8896 hw_device_t **device)
8897{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308898 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008899 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308900 char mixer_ctl_name[128] = {0};
8901 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308902
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008903 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008904 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8905
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008906 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008907 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008908 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008909 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008910 ALOGD("%s: returning existing instance of adev", __func__);
8911 ALOGD("%s: exit", __func__);
8912 pthread_mutex_unlock(&adev_init_lock);
8913 return 0;
8914 }
8915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008916 adev = calloc(1, sizeof(struct audio_device));
8917
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008918 if (!adev) {
8919 pthread_mutex_unlock(&adev_init_lock);
8920 return -ENOMEM;
8921 }
8922
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008923 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8924
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008925 // register audio ext hidl at the earliest
8926 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308927#ifdef DYNAMIC_LOG_ENABLED
8928 register_for_dynamic_logging("hal");
8929#endif
8930
Derek Chenf939fb72018-11-13 13:34:41 -08008931 /* default audio HAL major version */
8932 uint32_t maj_version = 2;
8933 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8934 maj_version = atoi(value);
8935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008936 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008937 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008938 adev->device.common.module = (struct hw_module_t *)module;
8939 adev->device.common.close = adev_close;
8940
8941 adev->device.init_check = adev_init_check;
8942 adev->device.set_voice_volume = adev_set_voice_volume;
8943 adev->device.set_master_volume = adev_set_master_volume;
8944 adev->device.get_master_volume = adev_get_master_volume;
8945 adev->device.set_master_mute = adev_set_master_mute;
8946 adev->device.get_master_mute = adev_get_master_mute;
8947 adev->device.set_mode = adev_set_mode;
8948 adev->device.set_mic_mute = adev_set_mic_mute;
8949 adev->device.get_mic_mute = adev_get_mic_mute;
8950 adev->device.set_parameters = adev_set_parameters;
8951 adev->device.get_parameters = adev_get_parameters;
8952 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8953 adev->device.open_output_stream = adev_open_output_stream;
8954 adev->device.close_output_stream = adev_close_output_stream;
8955 adev->device.open_input_stream = adev_open_input_stream;
8956 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308957 adev->device.create_audio_patch = adev_create_audio_patch;
8958 adev->device.release_audio_patch = adev_release_audio_patch;
8959 adev->device.get_audio_port = adev_get_audio_port;
8960 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008961 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308962 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008963
8964 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008965 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008966 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008967 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008968 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008970 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008971 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308972 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008973 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008974 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008975 /* Init audio feature manager */
8976 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008977 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008978 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08008979 list_init(&adev->active_inputs_list);
8980 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008981 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008982 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308983 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308984 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308985 adev->perf_lock_opts[0] = 0x101;
8986 adev->perf_lock_opts[1] = 0x20E;
8987 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008988 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07008989 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308990 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008993 adev->platform = platform_init(adev);
8994 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008995 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008996 free(adev->snd_dev_ref_cnt);
8997 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008998 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008999 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9000 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009001 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009002 return -EINVAL;
9003 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009004
Aalique Grahame22e49102018-12-18 14:23:57 -08009005 adev->extspk = audio_extn_extspk_init(adev);
9006
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309007 if (audio_extn_qaf_is_enabled()) {
9008 ret = audio_extn_qaf_init(adev);
9009 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009010 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309011 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009012 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309013 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9014 *device = NULL;
9015 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309016 return ret;
9017 }
9018
9019 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9020 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9021 }
9022
Derek Chenae7b0342019-02-08 15:17:04 -08009023 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009024 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9025
Eric Laurentc4aef752013-09-12 17:45:53 -07009026 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9027 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9028 if (adev->visualizer_lib == NULL) {
9029 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9030 } else {
9031 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9032 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009033 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009034 "visualizer_hal_start_output");
9035 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009036 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009037 "visualizer_hal_stop_output");
9038 }
9039 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309040 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009041 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009042 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009043 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309044 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009045 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009046
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009047 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9048 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9049 if (adev->offload_effects_lib == NULL) {
9050 ALOGE("%s: DLOPEN failed for %s", __func__,
9051 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9052 } else {
9053 ALOGV("%s: DLOPEN successful for %s", __func__,
9054 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9055 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309056 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009057 "offload_effects_bundle_hal_start_output");
9058 adev->offload_effects_stop_output =
9059 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9060 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009061 adev->offload_effects_set_hpx_state =
9062 (int (*)(bool))dlsym(adev->offload_effects_lib,
9063 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309064 adev->offload_effects_get_parameters =
9065 (void (*)(struct str_parms *, struct str_parms *))
9066 dlsym(adev->offload_effects_lib,
9067 "offload_effects_bundle_get_parameters");
9068 adev->offload_effects_set_parameters =
9069 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9070 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009071 }
9072 }
9073
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009074 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9075 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9076 if (adev->adm_lib == NULL) {
9077 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9078 } else {
9079 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9080 adev->adm_init = (adm_init_t)
9081 dlsym(adev->adm_lib, "adm_init");
9082 adev->adm_deinit = (adm_deinit_t)
9083 dlsym(adev->adm_lib, "adm_deinit");
9084 adev->adm_register_input_stream = (adm_register_input_stream_t)
9085 dlsym(adev->adm_lib, "adm_register_input_stream");
9086 adev->adm_register_output_stream = (adm_register_output_stream_t)
9087 dlsym(adev->adm_lib, "adm_register_output_stream");
9088 adev->adm_deregister_stream = (adm_deregister_stream_t)
9089 dlsym(adev->adm_lib, "adm_deregister_stream");
9090 adev->adm_request_focus = (adm_request_focus_t)
9091 dlsym(adev->adm_lib, "adm_request_focus");
9092 adev->adm_abandon_focus = (adm_abandon_focus_t)
9093 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009094 adev->adm_set_config = (adm_set_config_t)
9095 dlsym(adev->adm_lib, "adm_set_config");
9096 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9097 dlsym(adev->adm_lib, "adm_request_focus_v2");
9098 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9099 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9100 adev->adm_on_routing_change = (adm_on_routing_change_t)
9101 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009102 }
9103 }
9104
Aalique Grahame22e49102018-12-18 14:23:57 -08009105 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009106 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009107 //initialize this to false for now,
9108 //this will be set to true through set param
9109 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009110
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009111 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009113
9114 if (k_enable_extended_precision)
9115 adev_verify_devices(adev);
9116
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009117 adev->dsp_bit_width_enforce_mode =
9118 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009119
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309120 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9121 &adev->streams_output_cfg_list,
9122 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009123
Kiran Kandi910e1862013-10-29 13:29:42 -07009124 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009125
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009126 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009127 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9128 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009129 trial = atoi(value);
9130 if (period_size_is_plausible_for_low_latency(trial)) {
9131 pcm_config_low_latency.period_size = trial;
9132 pcm_config_low_latency.start_threshold = trial / 4;
9133 pcm_config_low_latency.avail_min = trial / 4;
9134 configured_low_latency_capture_period_size = trial;
9135 }
9136 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009137 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9138 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009139 trial = atoi(value);
9140 if (period_size_is_plausible_for_low_latency(trial)) {
9141 configured_low_latency_capture_period_size = trial;
9142 }
9143 }
9144
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009145 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9146
Aalique Grahame22e49102018-12-18 14:23:57 -08009147 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9148 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009149 af_period_multiplier = atoi(value);
9150 if (af_period_multiplier < 0)
9151 af_period_multiplier = 2;
9152 else if (af_period_multiplier > 4)
9153 af_period_multiplier = 4;
9154
9155 ALOGV("new period_multiplier = %d", af_period_multiplier);
9156 }
9157
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009158 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009159
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009160 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009161 pthread_mutex_unlock(&adev_init_lock);
9162
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009163 if (adev->adm_init)
9164 adev->adm_data = adev->adm_init();
9165
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309166 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309167 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009168 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309169
9170 audio_extn_snd_mon_init();
9171 pthread_mutex_lock(&adev->lock);
9172 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9173 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009174 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9175 /*
9176 * if the battery state callback happens before charging can be queried,
9177 * it will be guarded with the adev->lock held in the cb function and so
9178 * the callback value will reflect the latest state
9179 */
9180 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309181 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009182 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009183 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009184 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309185 /* Allocate memory for Device config params */
9186 adev->device_cfg_params = (struct audio_device_config_param*)
9187 calloc(platform_get_max_codec_backend(),
9188 sizeof(struct audio_device_config_param));
9189 if (adev->device_cfg_params == NULL)
9190 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309191
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309192 /*
9193 * Check if new PSPD matrix mixer control is supported. If not
9194 * supported, then set flag so that old mixer ctrl is sent while
9195 * sending pspd coefficients on older kernel version. Query mixer
9196 * control for default pcm id and channel value one.
9197 */
9198 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9199 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9200
9201 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9202 if (!ctl) {
9203 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9204 __func__, mixer_ctl_name);
9205 adev->use_old_pspd_mix_ctrl = true;
9206 }
9207
Eric Laurent994a6932013-07-17 11:51:42 -07009208 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009209 return 0;
9210}
9211
9212static struct hw_module_methods_t hal_module_methods = {
9213 .open = adev_open,
9214};
9215
9216struct audio_module HAL_MODULE_INFO_SYM = {
9217 .common = {
9218 .tag = HARDWARE_MODULE_TAG,
9219 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9220 .hal_api_version = HARDWARE_HAL_API_VERSION,
9221 .id = AUDIO_HARDWARE_MODULE_ID,
9222 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009223 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009224 .methods = &hal_module_methods,
9225 },
9226};