blob: b0aff8ebfa11dfd54b1a675556ce9c103810c9cb [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053076#include "ip_hdlr_intf.h"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080077#include "audio_feature_manager.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096
Aalique Grahame22e49102018-12-18 14:23:57 -080097#define RECORD_GAIN_MIN 0.0f
98#define RECORD_GAIN_MAX 1.0f
99#define RECORD_VOLUME_CTL_MAX 0x2000
100
101/* treat as unsigned Q1.13 */
102#define APP_TYPE_GAIN_DEFAULT 0x2000
103
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700104#define PROXY_OPEN_RETRY_COUNT 100
105#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800106
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800107#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
108 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
109 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
110#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800112
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700113#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700114#define DEFAULT_VOIP_BUF_DURATION_MS 20
115#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
116#define DEFAULT_VOIP_SAMP_RATE 48000
117
118#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
119
120struct pcm_config default_pcm_config_voip_copp = {
121 .channels = 1,
122 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
123 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
124 .period_count = 2,
125 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800126 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700128};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700130#define MIN_CHANNEL_COUNT 1
131#define DEFAULT_CHANNEL_COUNT 2
132#define MAX_HIFI_CHANNEL_COUNT 8
133
Aalique Grahame22e49102018-12-18 14:23:57 -0800134#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
135#define MAX_CHANNEL_COUNT 1
136#else
137#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
138#define XSTR(x) STR(x)
139#define STR(x) #x
140#endif
141
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700142static unsigned int configured_low_latency_capture_period_size =
143 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
144
Haynes Mathew George16081042017-05-31 17:16:49 -0700145#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
146#define MMAP_PERIOD_COUNT_MIN 32
147#define MMAP_PERIOD_COUNT_MAX 512
148#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
149
Aalique Grahame22e49102018-12-18 14:23:57 -0800150/* This constant enables extended precision handling.
151 * TODO The flag is off until more testing is done.
152 */
153static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700154extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800155
Eric Laurentb23d5282013-05-14 15:27:20 -0700156struct pcm_config pcm_config_deep_buffer = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
160 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
163 .stop_threshold = INT_MAX,
164 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165};
166
167struct pcm_config pcm_config_low_latency = {
168 .channels = 2,
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
170 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
171 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
172 .format = PCM_FORMAT_S16_LE,
173 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
174 .stop_threshold = INT_MAX,
175 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176};
177
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800178struct pcm_config pcm_config_haptics_audio = {
179 .channels = 1,
180 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
181 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
182 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185 .stop_threshold = INT_MAX,
186 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187};
188
189struct pcm_config pcm_config_haptics = {
190 .channels = 1,
191 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
192 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
193 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
198};
199
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700200static int af_period_multiplier = 4;
201struct pcm_config pcm_config_rt = {
202 .channels = 2,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = ULL_PERIOD_SIZE, //1 ms
205 .period_count = 512, //=> buffer size is 512ms
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
208 .stop_threshold = INT_MAX,
209 .silence_threshold = 0,
210 .silence_size = 0,
211 .avail_min = ULL_PERIOD_SIZE, //1 ms
212};
213
Eric Laurentb23d5282013-05-14 15:27:20 -0700214struct pcm_config pcm_config_hdmi_multi = {
215 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
216 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
217 .period_size = HDMI_MULTI_PERIOD_SIZE,
218 .period_count = HDMI_MULTI_PERIOD_COUNT,
219 .format = PCM_FORMAT_S16_LE,
220 .start_threshold = 0,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_playback = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = MMAP_PERIOD_SIZE*8,
232 .stop_threshold = INT32_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700238struct pcm_config pcm_config_hifi = {
239 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
240 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
241 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
242 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
243 .format = PCM_FORMAT_S24_3LE,
244 .start_threshold = 0,
245 .stop_threshold = INT_MAX,
246 .avail_min = 0,
247};
248
Eric Laurentb23d5282013-05-14 15:27:20 -0700249struct pcm_config pcm_config_audio_capture = {
250 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700251 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
252 .format = PCM_FORMAT_S16_LE,
253};
254
Haynes Mathew George16081042017-05-31 17:16:49 -0700255struct pcm_config pcm_config_mmap_capture = {
256 .channels = 2,
257 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
258 .period_size = MMAP_PERIOD_SIZE,
259 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
260 .format = PCM_FORMAT_S16_LE,
261 .start_threshold = 0,
262 .stop_threshold = INT_MAX,
263 .silence_threshold = 0,
264 .silence_size = 0,
265 .avail_min = MMAP_PERIOD_SIZE, //1 ms
266};
267
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700268#define AFE_PROXY_CHANNEL_COUNT 2
269#define AFE_PROXY_SAMPLING_RATE 48000
270
271#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
272#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
273
274struct pcm_config pcm_config_afe_proxy_playback = {
275 .channels = AFE_PROXY_CHANNEL_COUNT,
276 .rate = AFE_PROXY_SAMPLING_RATE,
277 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
278 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
279 .format = PCM_FORMAT_S16_LE,
280 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .stop_threshold = INT_MAX,
282 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283};
284
285#define AFE_PROXY_RECORD_PERIOD_SIZE 768
286#define AFE_PROXY_RECORD_PERIOD_COUNT 4
287
Aalique Grahame22e49102018-12-18 14:23:57 -0800288struct pcm_config pcm_config_audio_capture_rt = {
289 .channels = 2,
290 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
291 .period_size = ULL_PERIOD_SIZE,
292 .period_count = 512,
293 .format = PCM_FORMAT_S16_LE,
294 .start_threshold = 0,
295 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
296 .silence_threshold = 0,
297 .silence_size = 0,
298 .avail_min = ULL_PERIOD_SIZE, //1 ms
299};
300
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700301struct pcm_config pcm_config_afe_proxy_record = {
302 .channels = AFE_PROXY_CHANNEL_COUNT,
303 .rate = AFE_PROXY_SAMPLING_RATE,
304 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
305 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
306 .format = PCM_FORMAT_S16_LE,
307 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .stop_threshold = INT_MAX,
309 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
310};
311
Ashish Jainf1eaa582016-05-23 20:54:24 +0530312#define AUDIO_MAX_PCM_FORMATS 7
313
314const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
315 [AUDIO_FORMAT_DEFAULT] = 0,
316 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
317 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
318 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
319 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
321 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
322};
323
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800324const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700325 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
326 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800327 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700328 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
329 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700330 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700331 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
333 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700340 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
341 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700342 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800343 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700344
Eric Laurentb23d5282013-05-14 15:27:20 -0700345 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700346 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530347 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
348 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
349 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530350 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
351 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700352 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700353 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700354 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700355 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800357 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800358 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700359 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700360
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700361 [USECASE_VOICE2_CALL] = "voice2-call",
362 [USECASE_VOLTE_CALL] = "volte-call",
363 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800364 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800365 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
366 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800367 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700368 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
369 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
370 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800371 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
372 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
373 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
374
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700375 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
376 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700377 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
378 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700379
380 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
381 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530382 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700383
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530384 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530385 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
388 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
389 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530390 /* For Interactive Audio Streams */
391 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700399
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800400 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
401
402 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700403};
404
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700405static const audio_usecase_t offload_usecases[] = {
406 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700407 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
408 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700415};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800416
Varun Balaraje49253e2017-07-06 19:48:56 +0530417static const audio_usecase_t interactive_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
426};
427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428#define STRING_TO_ENUM(string) { #string, string }
429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430struct string_to_enum {
431 const char *name;
432 uint32_t value;
433};
434
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700444 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
445 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
446 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
447 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455};
456
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457static const struct string_to_enum formats_name_to_enum_table[] = {
458 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
459 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
460 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700461 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
462 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
463 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700464 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800465 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
466 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800468};
469
470//list of all supported sample rates by HDMI specification.
471static const int out_hdmi_sample_rates[] = {
472 32000, 44100, 48000, 88200, 96000, 176400, 192000,
473};
474
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700475static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(32000),
477 STRING_TO_ENUM(44100),
478 STRING_TO_ENUM(48000),
479 STRING_TO_ENUM(88200),
480 STRING_TO_ENUM(96000),
481 STRING_TO_ENUM(176400),
482 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700483};
484
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700485static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700486static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700487static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700488//cache last MBDRC cal step level
489static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700490
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530491static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
492static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700493static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800494static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530495static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530496
Vatsal Buchac09ae062018-11-14 13:25:08 +0530497#ifdef AUDIO_FEATURE_ENABLED_GCOV
498extern void __gcov_flush();
499static void enable_gcov()
500{
501 __gcov_flush();
502}
503#else
504static void enable_gcov()
505{
506}
507#endif
508
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700509static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
510 int flags __unused)
511{
512 int dir = 0;
513 switch (uc_id) {
514 case USECASE_AUDIO_RECORD_LOW_LATENCY:
515 dir = 1;
516 case USECASE_AUDIO_PLAYBACK_ULL:
517 break;
518 default:
519 return false;
520 }
521
522 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
523 PCM_PLAYBACK : PCM_CAPTURE);
524 if (adev->adm_is_noirq_avail)
525 return adev->adm_is_noirq_avail(adev->adm_data,
526 adev->snd_card, dev_id, dir);
527 return false;
528}
529
530static void register_out_stream(struct stream_out *out)
531{
532 struct audio_device *adev = out->dev;
533 if (is_offload_usecase(out->usecase) ||
534 !adev->adm_register_output_stream)
535 return;
536
537 // register stream first for backward compatibility
538 adev->adm_register_output_stream(adev->adm_data,
539 out->handle,
540 out->flags);
541
542 if (!adev->adm_set_config)
543 return;
544
545 if (out->realtime)
546 adev->adm_set_config(adev->adm_data,
547 out->handle,
548 out->pcm, &out->config);
549}
550
551static void register_in_stream(struct stream_in *in)
552{
553 struct audio_device *adev = in->dev;
554 if (!adev->adm_register_input_stream)
555 return;
556
557 adev->adm_register_input_stream(adev->adm_data,
558 in->capture_handle,
559 in->flags);
560
561 if (!adev->adm_set_config)
562 return;
563
564 if (in->realtime)
565 adev->adm_set_config(adev->adm_data,
566 in->capture_handle,
567 in->pcm,
568 &in->config);
569}
570
571static void request_out_focus(struct stream_out *out, long ns)
572{
573 struct audio_device *adev = out->dev;
574
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700575 if (adev->adm_request_focus_v2)
576 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
577 else if (adev->adm_request_focus)
578 adev->adm_request_focus(adev->adm_data, out->handle);
579}
580
581static void request_in_focus(struct stream_in *in, long ns)
582{
583 struct audio_device *adev = in->dev;
584
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700585 if (adev->adm_request_focus_v2)
586 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
587 else if (adev->adm_request_focus)
588 adev->adm_request_focus(adev->adm_data, in->capture_handle);
589}
590
591static void release_out_focus(struct stream_out *out)
592{
593 struct audio_device *adev = out->dev;
594
595 if (adev->adm_abandon_focus)
596 adev->adm_abandon_focus(adev->adm_data, out->handle);
597}
598
599static void release_in_focus(struct stream_in *in)
600{
601 struct audio_device *adev = in->dev;
602 if (adev->adm_abandon_focus)
603 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
604}
605
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530606static int parse_snd_card_status(struct str_parms *parms, int *card,
607 card_status_t *status)
608{
609 char value[32]={0};
610 char state[32]={0};
611
612 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
613 if (ret < 0)
614 return -1;
615
616 // sscanf should be okay as value is of max length 32.
617 // same as sizeof state.
618 if (sscanf(value, "%d,%s", card, state) < 2)
619 return -1;
620
621 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
622 CARD_STATUS_OFFLINE;
623 return 0;
624}
625
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700626static inline void adjust_frames_for_device_delay(struct stream_out *out,
627 uint32_t *dsp_frames) {
628 // Adjustment accounts for A2dp encoder latency with offload usecases
629 // Note: Encoder latency is returned in ms.
630 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
631 unsigned long offset =
632 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
633 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
634 }
635}
636
vivek mehtaa76401a2015-04-24 14:12:15 -0700637__attribute__ ((visibility ("default")))
638bool audio_hw_send_gain_dep_calibration(int level) {
639 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700640 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700641
642 pthread_mutex_lock(&adev_init_lock);
643
644 if (adev != NULL && adev->platform != NULL) {
645 pthread_mutex_lock(&adev->lock);
646 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700647
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530648 // cache level info for any of the use case which
649 // was not started.
650 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700651
vivek mehtaa76401a2015-04-24 14:12:15 -0700652 pthread_mutex_unlock(&adev->lock);
653 } else {
654 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
655 }
656
657 pthread_mutex_unlock(&adev_init_lock);
658
659 return ret_val;
660}
661
Ashish Jain5106d362016-05-11 19:23:33 +0530662static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
663{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800664 bool gapless_enabled = false;
665 const char *mixer_ctl_name = "Compress Gapless Playback";
666 struct mixer_ctl *ctl;
667
668 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700669 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530670
671 /*Disable gapless if its AV playback*/
672 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800673
674 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
675 if (!ctl) {
676 ALOGE("%s: Could not get ctl for mixer cmd - %s",
677 __func__, mixer_ctl_name);
678 return -EINVAL;
679 }
680
681 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
682 ALOGE("%s: Could not set gapless mode %d",
683 __func__, gapless_enabled);
684 return -EINVAL;
685 }
686 return 0;
687}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700688
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700689__attribute__ ((visibility ("default")))
690int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
691 int table_size) {
692 int ret_val = 0;
693 ALOGV("%s: enter ... ", __func__);
694
695 pthread_mutex_lock(&adev_init_lock);
696 if (adev == NULL) {
697 ALOGW("%s: adev is NULL .... ", __func__);
698 goto done;
699 }
700
701 pthread_mutex_lock(&adev->lock);
702 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
703 pthread_mutex_unlock(&adev->lock);
704done:
705 pthread_mutex_unlock(&adev_init_lock);
706 ALOGV("%s: exit ... ", __func__);
707 return ret_val;
708}
709
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800710bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800711{
712 bool ret = false;
713 ALOGV("%s: enter ...", __func__);
714
715 pthread_mutex_lock(&adev_init_lock);
716
717 if (adev != NULL && adev->platform != NULL) {
718 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800719 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800720 pthread_mutex_unlock(&adev->lock);
721 }
722
723 pthread_mutex_unlock(&adev_init_lock);
724
725 ALOGV("%s: exit with ret %d", __func__, ret);
726 return ret;
727}
Aalique Grahame22e49102018-12-18 14:23:57 -0800728
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700729static bool is_supported_format(audio_format_t format)
730{
Eric Laurent86e17132013-09-12 17:49:30 -0700731 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530732 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530733 format == AUDIO_FORMAT_AAC_LC ||
734 format == AUDIO_FORMAT_AAC_HE_V1 ||
735 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530736 format == AUDIO_FORMAT_AAC_ADTS_LC ||
737 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
738 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530739 format == AUDIO_FORMAT_AAC_LATM_LC ||
740 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
741 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530742 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
743 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530744 format == AUDIO_FORMAT_PCM_FLOAT ||
745 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700746 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530747 format == AUDIO_FORMAT_AC3 ||
748 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700749 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530750 format == AUDIO_FORMAT_DTS ||
751 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800752 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530753 format == AUDIO_FORMAT_ALAC ||
754 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530755 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530756 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800757 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530758 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700759 format == AUDIO_FORMAT_APTX ||
760 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800761 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700762
763 return false;
764}
765
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700766static inline bool is_mmap_usecase(audio_usecase_t uc_id)
767{
768 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
769 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
770}
771
Avinash Vaish71a8b972014-07-24 15:36:33 +0530772static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
773 struct audio_usecase *uc_info)
774{
775 struct listnode *node;
776 struct audio_usecase *usecase;
777
778 if (uc_info == NULL)
779 return -EINVAL;
780
781 /* Re-route all voice usecases on the shared backend other than the
782 specified usecase to new snd devices */
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800785 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530786 enable_audio_route(adev, usecase);
787 }
788 return 0;
789}
790
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530791static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530792{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530793 ALOGV("%s", __func__);
794 audio_route_apply_and_update_path(adev->audio_route,
795 "asrc-mode");
796 adev->asrc_mode_enabled = true;
797}
798
799static void disable_asrc_mode(struct audio_device *adev)
800{
801 ALOGV("%s", __func__);
802 audio_route_reset_and_update_path(adev->audio_route,
803 "asrc-mode");
804 adev->asrc_mode_enabled = false;
805}
806
807/*
808 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
809 * 44.1 or Native DSD backends are enabled for any of current use case.
810 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
811 * - Disable current mix path use case(Headphone backend) and re-enable it with
812 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
813 * e.g. Naitve DSD or Headphone 44.1 -> + 48
814 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530815static void check_and_set_asrc_mode(struct audio_device *adev,
816 struct audio_usecase *uc_info,
817 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530818{
819 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530820 int i, num_new_devices = 0;
821 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
822 /*
823 *Split snd device for new combo use case
824 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
825 */
826 if (platform_split_snd_device(adev->platform,
827 snd_device,
828 &num_new_devices,
829 split_new_snd_devices) == 0) {
830 for (i = 0; i < num_new_devices; i++)
831 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
832 } else {
833 int new_backend_idx = platform_get_backend_index(snd_device);
834 if (((new_backend_idx == HEADPHONE_BACKEND) ||
835 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
836 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
837 !adev->asrc_mode_enabled) {
838 struct listnode *node = NULL;
839 struct audio_usecase *uc = NULL;
840 struct stream_out *curr_out = NULL;
841 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
842 int i, num_devices, ret = 0;
843 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530844
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530845 list_for_each(node, &adev->usecase_list) {
846 uc = node_to_item(node, struct audio_usecase, list);
847 curr_out = (struct stream_out*) uc->stream.out;
848 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
849 /*
850 *Split snd device for existing combo use case
851 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
852 */
853 ret = platform_split_snd_device(adev->platform,
854 uc->out_snd_device,
855 &num_devices,
856 split_snd_devices);
857 if (ret < 0 || num_devices == 0) {
858 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
859 split_snd_devices[0] = uc->out_snd_device;
860 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800861 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530862 for (i = 0; i < num_devices; i++) {
863 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
864 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
865 if((new_backend_idx == HEADPHONE_BACKEND) &&
866 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
867 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
868 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
869 __func__);
870 enable_asrc_mode(adev);
871 break;
872 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
873 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
874 (usecase_backend_idx == HEADPHONE_BACKEND)) {
875 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
876 __func__);
877 disable_audio_route(adev, uc);
878 disable_snd_device(adev, uc->out_snd_device);
879 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
880 if (new_backend_idx == DSD_NATIVE_BACKEND)
881 audio_route_apply_and_update_path(adev->audio_route,
882 "hph-true-highquality-mode");
883 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
884 (curr_out->bit_width >= 24))
885 audio_route_apply_and_update_path(adev->audio_route,
886 "hph-highquality-mode");
887 enable_asrc_mode(adev);
888 enable_snd_device(adev, uc->out_snd_device);
889 enable_audio_route(adev, uc);
890 break;
891 }
892 }
893 // reset split devices count
894 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800895 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530896 if (adev->asrc_mode_enabled)
897 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530898 }
899 }
900 }
901}
902
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700903static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
904 struct audio_effect_config effect_config,
905 unsigned int param_value)
906{
907 char mixer_ctl_name[] = "Audio Effect";
908 struct mixer_ctl *ctl;
909 long set_values[6];
910 struct stream_in *in = adev->active_input;
911
912 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
913 if (!ctl) {
914 ALOGE("%s: Could not get mixer ctl - %s",
915 __func__, mixer_ctl_name);
916 return -EINVAL;
917 }
918
919 set_values[0] = 1; //0:Rx 1:Tx
920 set_values[1] = in->app_type_cfg.app_type;
921 set_values[2] = (long)effect_config.module_id;
922 set_values[3] = (long)effect_config.instance_id;
923 set_values[4] = (long)effect_config.param_id;
924 set_values[5] = param_value;
925
926 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
927
928 return 0;
929
930}
931
932static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
933 int effect_type, unsigned int *param_value)
934{
935 int ret = 0;
936 struct audio_effect_config other_effect_config;
937 struct audio_usecase *usecase = NULL;
938 struct stream_in *in = adev->active_input;
939
940 usecase = get_usecase_from_list(adev, in->usecase);
941 if (!usecase)
942 return -EINVAL;
943
944 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
945 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
946 if (ret < 0) {
947 ALOGE("%s Failed to get effect params %d", __func__, ret);
948 return ret;
949 }
950
951 if (module_id == other_effect_config.module_id) {
952 //Same module id for AEC/NS. Values need to be combined
953 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
954 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
955 *param_value |= other_effect_config.param_value;
956 }
957 }
958
959 return ret;
960}
961
962static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800963{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700964 struct audio_effect_config effect_config;
965 struct audio_usecase *usecase = NULL;
966 int ret = 0;
967 unsigned int param_value = 0;
968 struct stream_in *in = adev->active_input;
969
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800970 if(!voice_extn_is_dynamic_ecns_enabled())
971 return ENOSYS;
972
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700973 if (!in) {
974 ALOGE("%s: Invalid input stream", __func__);
975 return -EINVAL;
976 }
977
978 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
979
980 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800981 if (usecase == NULL) {
982 ALOGE("%s: Could not find the usecase (%d) in the list",
983 __func__, in->usecase);
984 return -EINVAL;
985 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700986
987 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
988 if (ret < 0) {
989 ALOGE("%s Failed to get module id %d", __func__, ret);
990 return ret;
991 }
992 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
993 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
994
995 if(enable)
996 param_value = effect_config.param_value;
997
998 /*Special handling for AEC & NS effects Param values need to be
999 updated if module ids are same*/
1000
1001 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1002 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1003 if (ret < 0)
1004 return ret;
1005 }
1006
1007 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1008
1009 return ret;
1010}
1011
1012static void check_and_enable_effect(struct audio_device *adev)
1013{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001014 if(!voice_extn_is_dynamic_ecns_enabled())
1015 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001016
1017 if (adev->active_input->enable_aec) {
1018 enable_disable_effect(adev, EFFECT_AEC, true);
1019 }
1020
1021 if (adev->active_input->enable_ns &&
1022 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1023 enable_disable_effect(adev, EFFECT_NS, true);
1024 }
1025}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001026
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001027int pcm_ioctl(struct pcm *pcm, int request, ...)
1028{
1029 va_list ap;
1030 void * arg;
1031 int pcm_fd = *(int*)pcm;
1032
1033 va_start(ap, request);
1034 arg = va_arg(ap, void *);
1035 va_end(ap);
1036
1037 return ioctl(pcm_fd, request, arg);
1038}
1039
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001040int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001041 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001044 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301045 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301046 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001047
1048 if (usecase == NULL)
1049 return -EINVAL;
1050
1051 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1052
Surendar Karka93cd25a2018-08-28 14:21:37 +05301053 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001055 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001057
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001058#ifdef DS1_DOLBY_DAP_ENABLED
1059 audio_extn_dolby_set_dmid(adev);
1060 audio_extn_dolby_set_endpoint(adev);
1061#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001062 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001063 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301064 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001065 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301066 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301067 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1068 out = usecase->stream.out;
1069 if (out && out->compr)
1070 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1071 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301072 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301073
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001074 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001075 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001076 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301077 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1078 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1079 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1080 if (parms) {
1081 audio_extn_fm_set_parameters(adev, parms);
1082 str_parms_destroy(parms);
1083 }
1084 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 ALOGV("%s: exit", __func__);
1086 return 0;
1087}
1088
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001089int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001090 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001093 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001094
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301095 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001096 return -EINVAL;
1097
1098 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301099 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 snd_device = usecase->in_snd_device;
1101 else
1102 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001103 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001104 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001105 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001106 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001107 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301108 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301109 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 ALOGV("%s: exit", __func__);
1111 return 0;
1112}
1113
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001114int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001115 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301117 int i, num_devices = 0;
1118 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001119 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1120
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001121 if (snd_device < SND_DEVICE_MIN ||
1122 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001123 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001124 return -EINVAL;
1125 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126
1127 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001128
1129 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1130 ALOGE("%s: Invalid sound device returned", __func__);
1131 return -EINVAL;
1132 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001134 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001135 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 return 0;
1137 }
1138
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301139
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001140 if (audio_extn_spkr_prot_is_enabled())
1141 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001142
Aalique Grahame22e49102018-12-18 14:23:57 -08001143 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1144
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001145 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1146 audio_extn_spkr_prot_is_enabled()) {
1147 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001148 adev->snd_dev_ref_cnt[snd_device]--;
1149 return -EINVAL;
1150 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001151 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001152 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001153 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001154 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001155 return -EINVAL;
1156 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001157 } else if (platform_split_snd_device(adev->platform,
1158 snd_device,
1159 &num_devices,
1160 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301161 for (i = 0; i < num_devices; i++) {
1162 enable_snd_device(adev, new_snd_devices[i]);
1163 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001164 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001165 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001166 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301167
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301168
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301169 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1170 (audio_extn_a2dp_start_playback() < 0)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02001171 ALOGE(" fail to configure A2dp Source control path ");
1172 return -EINVAL;
1173 }
1174
1175 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1176 (audio_extn_a2dp_start_capture() < 0)) {
1177 ALOGE(" fail to configure A2dp Sink control path ");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301178 return -EINVAL;
1179 }
1180
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001181 /* due to the possibility of calibration overwrite between listen
1182 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001183 audio_extn_sound_trigger_update_device_status(snd_device,
1184 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301185 audio_extn_listen_update_device_status(snd_device,
1186 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001187 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001188 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001189 audio_extn_sound_trigger_update_device_status(snd_device,
1190 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301191 audio_extn_listen_update_device_status(snd_device,
1192 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001193 return -EINVAL;
1194 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001195 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001196 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301197
1198 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1199 !adev->native_playback_enabled &&
1200 audio_is_true_native_stream_active(adev)) {
1201 ALOGD("%s: %d: napb: enabling native mode in hardware",
1202 __func__, __LINE__);
1203 audio_route_apply_and_update_path(adev->audio_route,
1204 "true-native-mode");
1205 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301206 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301207 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1208 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001209 (audio_extn_ffv_get_stream() == adev->active_input)) {
1210 ALOGD("%s: init ec ref loopback", __func__);
1211 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1212 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214 return 0;
1215}
1216
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001217int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001218 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301220 int i, num_devices = 0;
1221 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001222 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1223
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001224 if (snd_device < SND_DEVICE_MIN ||
1225 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001226 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001227 return -EINVAL;
1228 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001229 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1230 ALOGE("%s: device ref cnt is already 0", __func__);
1231 return -EINVAL;
1232 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001233
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001235
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001236 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1237 ALOGE("%s: Invalid sound device returned", __func__);
1238 return -EINVAL;
1239 }
1240
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001241 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001242 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301243
Aalique Grahame22e49102018-12-18 14:23:57 -08001244 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1245
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001246 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1247 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001248 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001249
1250 // when speaker device is disabled, reset swap.
1251 // will be renabled on usecase start
1252 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001253 } else if (platform_split_snd_device(adev->platform,
1254 snd_device,
1255 &num_devices,
1256 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301257 for (i = 0; i < num_devices; i++) {
1258 disable_snd_device(adev, new_snd_devices[i]);
1259 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001260 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001261 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001262 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001263 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001264
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301265 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1266 audio_extn_a2dp_stop_playback();
1267
Florian Pfister1a84f312018-07-19 14:38:18 +02001268 if (SND_DEVICE_IN_BT_A2DP == snd_device)
1269 audio_extn_a2dp_stop_capture();
1270
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001271 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301272 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301273 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1274 adev->native_playback_enabled) {
1275 ALOGD("%s: %d: napb: disabling native mode in hardware",
1276 __func__, __LINE__);
1277 audio_route_reset_and_update_path(adev->audio_route,
1278 "true-native-mode");
1279 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301280 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1281 adev->asrc_mode_enabled) {
1282 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301283 disable_asrc_mode(adev);
1284 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301285 }
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301286 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1287 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001288 (audio_extn_ffv_get_stream() == adev->active_input)) {
1289 ALOGD("%s: deinit ec ref loopback", __func__);
1290 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1291 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001292 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001293 audio_extn_sound_trigger_update_device_status(snd_device,
1294 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301295 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001296 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001299 return 0;
1300}
1301
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001302/*
1303 legend:
1304 uc - existing usecase
1305 new_uc - new usecase
1306 d1, d11, d2 - SND_DEVICE enums
1307 a1, a2 - corresponding ANDROID device enums
1308 B1, B2 - backend strings
1309
1310case 1
1311 uc->dev d1 (a1) B1
1312 new_uc->dev d1 (a1), d2 (a2) B1, B2
1313
1314 resolution: disable and enable uc->dev on d1
1315
1316case 2
1317 uc->dev d1 (a1) B1
1318 new_uc->dev d11 (a1) B1
1319
1320 resolution: need to switch uc since d1 and d11 are related
1321 (e.g. speaker and voice-speaker)
1322 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1323
1324case 3
1325 uc->dev d1 (a1) B1
1326 new_uc->dev d2 (a2) B2
1327
1328 resolution: no need to switch uc
1329
1330case 4
1331 uc->dev d1 (a1) B1
1332 new_uc->dev d2 (a2) B1
1333
1334 resolution: disable enable uc-dev on d2 since backends match
1335 we cannot enable two streams on two different devices if they
1336 share the same backend. e.g. if offload is on speaker device using
1337 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1338 using the same backend, offload must also be switched to voice-handset.
1339
1340case 5
1341 uc->dev d1 (a1) B1
1342 new_uc->dev d1 (a1), d2 (a2) B1
1343
1344 resolution: disable enable uc-dev on d2 since backends match
1345 we cannot enable two streams on two different devices if they
1346 share the same backend.
1347
1348case 6
1349 uc->dev d1 (a1) B1
1350 new_uc->dev d2 (a1) B2
1351
1352 resolution: no need to switch
1353
1354case 7
1355 uc->dev d1 (a1), d2 (a2) B1, B2
1356 new_uc->dev d1 (a1) B1
1357
1358 resolution: no need to switch
1359
Zhou Song4ba65882018-07-09 14:48:07 +08001360case 8
1361 uc->dev d1 (a1) B1
1362 new_uc->dev d11 (a1), d2 (a2) B1, B2
1363 resolution: compared to case 1, for this case, d1 and d11 are related
1364 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001365*/
1366static snd_device_t derive_playback_snd_device(void * platform,
1367 struct audio_usecase *uc,
1368 struct audio_usecase *new_uc,
1369 snd_device_t new_snd_device)
1370{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301371 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001372
1373 snd_device_t d1 = uc->out_snd_device;
1374 snd_device_t d2 = new_snd_device;
1375
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301376 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301377 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301378 a1 = uc->stream.inout->out_config.devices;
1379 a2 = new_uc->stream.inout->out_config.devices;
1380 break;
1381 default :
1382 a1 = uc->stream.out->devices;
1383 a2 = new_uc->stream.out->devices;
1384 break;
1385 }
1386
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001387 // Treat as a special case when a1 and a2 are not disjoint
1388 if ((a1 != a2) && (a1 & a2)) {
1389 snd_device_t d3[2];
1390 int num_devices = 0;
1391 int ret = platform_split_snd_device(platform,
1392 popcount(a1) > 1 ? d1 : d2,
1393 &num_devices,
1394 d3);
1395 if (ret < 0) {
1396 if (ret != -ENOSYS) {
1397 ALOGW("%s failed to split snd_device %d",
1398 __func__,
1399 popcount(a1) > 1 ? d1 : d2);
1400 }
1401 goto end;
1402 }
1403
1404 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1405 // But if it does happen, we need to give priority to d2 if
1406 // the combo devices active on the existing usecase share a backend.
1407 // This is because we cannot have a usecase active on a combo device
1408 // and a new usecase requests one device in this combo pair.
1409 if (platform_check_backends_match(d3[0], d3[1])) {
1410 return d2; // case 5
1411 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001412 // check if d1 is related to any of d3's
1413 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001414 return d1; // case 1
1415 else
1416 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001417 }
1418 } else {
1419 if (platform_check_backends_match(d1, d2)) {
1420 return d2; // case 2, 4
1421 } else {
1422 return d1; // case 6, 3
1423 }
1424 }
1425
1426end:
1427 return d2; // return whatever was calculated before.
1428}
1429
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001430static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301431 struct audio_usecase *uc_info,
1432 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001433{
1434 struct listnode *node;
1435 struct audio_usecase *usecase;
1436 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301437 snd_device_t uc_derive_snd_device;
1438 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001440 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301441 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442 /*
1443 * This function is to make sure that all the usecases that are active on
1444 * the hardware codec backend are always routed to any one device that is
1445 * handled by the hardware codec.
1446 * For example, if low-latency and deep-buffer usecases are currently active
1447 * on speaker and out_set_parameters(headset) is received on low-latency
1448 * output, then we have to make sure deep-buffer is also switched to headset,
1449 * because of the limitation that both the devices cannot be enabled
1450 * at the same time as they share the same backend.
1451 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001452 /*
1453 * This call is to check if we need to force routing for a particular stream
1454 * If there is a backend configuration change for the device when a
1455 * new stream starts, then ADM needs to be closed and re-opened with the new
1456 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001457 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001458 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001459 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1460 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301461 /* For a2dp device reconfigure all active sessions
1462 * with new AFE encoder format based on a2dp state
1463 */
1464 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1465 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1466 audio_extn_a2dp_is_force_device_switch()) {
1467 force_routing = true;
1468 force_restart_session = true;
1469 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301470 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1471
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001473 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001474 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1476 switch_device[i] = false;
1477
1478 list_for_each(node, &adev->usecase_list) {
1479 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001480
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301481 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1482 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301483 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301484 platform_get_snd_device_name(usecase->out_snd_device),
1485 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301486 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1487 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1488 usecase, uc_info, snd_device);
1489 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1490 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1491 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1492 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001493 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301494 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1495 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1496 ((force_restart_session) ||
1497 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301498 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1499 __func__, use_case_table[usecase->id],
1500 platform_get_snd_device_name(usecase->out_snd_device));
1501 disable_audio_route(adev, usecase);
1502 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301503 /* Enable existing usecase on derived playback device */
1504 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301505 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301506 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 }
1508 }
1509
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301510 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1511 num_uc_to_switch);
1512
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001514 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301516 /* Make sure the previous devices to be disabled first and then enable the
1517 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 list_for_each(node, &adev->usecase_list) {
1519 usecase = node_to_item(node, struct audio_usecase, list);
1520 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001521 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001522 }
1523 }
1524
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001525 list_for_each(node, &adev->usecase_list) {
1526 usecase = node_to_item(node, struct audio_usecase, list);
1527 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301528 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001529 }
1530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 /* Re-route all the usecases on the shared backend other than the
1533 specified usecase to new snd devices */
1534 list_for_each(node, &adev->usecase_list) {
1535 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301536 /* Update the out_snd_device only before enabling the audio route */
1537 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301538 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301539 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301540 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301541 use_case_table[usecase->id],
1542 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001543 /* Update voc calibration before enabling VoIP route */
1544 if (usecase->type == VOIP_CALL)
1545 status = platform_switch_voice_call_device_post(adev->platform,
1546 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001547 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301548 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001549 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1550 out_set_voip_volume(&usecase->stream.out->stream,
1551 usecase->stream.out->volume_l,
1552 usecase->stream.out->volume_r);
1553 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301554 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 }
1556 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 }
1558}
1559
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301560static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001561 struct audio_usecase *uc_info,
1562 snd_device_t snd_device)
1563{
1564 struct listnode *node;
1565 struct audio_usecase *usecase;
1566 bool switch_device[AUDIO_USECASE_MAX];
1567 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301568 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001569 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001570
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301571 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1572 snd_device);
1573 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301574
1575 /*
1576 * Make sure out devices is checked against out codec backend device and
1577 * also in devices against in codec backend. Checking out device against in
1578 * codec backend or vice versa causes issues.
1579 */
1580 if (uc_info->type == PCM_CAPTURE)
1581 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001582 /*
1583 * This function is to make sure that all the active capture usecases
1584 * are always routed to the same input sound device.
1585 * For example, if audio-record and voice-call usecases are currently
1586 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1587 * is received for voice call then we have to make sure that audio-record
1588 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1589 * because of the limitation that two devices cannot be enabled
1590 * at the same time if they share the same backend.
1591 */
1592 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1593 switch_device[i] = false;
1594
1595 list_for_each(node, &adev->usecase_list) {
1596 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301597 /*
1598 * TODO: Enhance below condition to handle BT sco/USB multi recording
1599 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001600 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001601 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301602 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301603 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301604 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301605 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001606 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001607 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1608 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001609 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001610 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001611 switch_device[usecase->id] = true;
1612 num_uc_to_switch++;
1613 }
1614 }
1615
1616 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001617 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001618
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301619 /* Make sure the previous devices to be disabled first and then enable the
1620 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001621 list_for_each(node, &adev->usecase_list) {
1622 usecase = node_to_item(node, struct audio_usecase, list);
1623 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001624 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001625 }
1626 }
1627
1628 list_for_each(node, &adev->usecase_list) {
1629 usecase = node_to_item(node, struct audio_usecase, list);
1630 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001631 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001632 }
1633 }
1634
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001635 /* Re-route all the usecases on the shared backend other than the
1636 specified usecase to new snd devices */
1637 list_for_each(node, &adev->usecase_list) {
1638 usecase = node_to_item(node, struct audio_usecase, list);
1639 /* Update the in_snd_device only before enabling the audio route */
1640 if (switch_device[usecase->id] ) {
1641 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001642 if (usecase->type != VOICE_CALL) {
1643 /* Update voc calibration before enabling VoIP route */
1644 if (usecase->type == VOIP_CALL)
1645 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001646 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001647 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301648 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001649 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001650 }
1651 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001652 }
1653}
1654
Mingming Yin3a941d42016-02-17 18:08:05 -08001655static void reset_hdmi_sink_caps(struct stream_out *out) {
1656 int i = 0;
1657
1658 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1659 out->supported_channel_masks[i] = 0;
1660 }
1661 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1662 out->supported_formats[i] = 0;
1663 }
1664 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1665 out->supported_sample_rates[i] = 0;
1666 }
1667}
1668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001670static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671{
Mingming Yin3a941d42016-02-17 18:08:05 -08001672 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001673 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
Mingming Yin3a941d42016-02-17 18:08:05 -08001675 reset_hdmi_sink_caps(out);
1676
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001677 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001678 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001679 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001680 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001681 }
1682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001685 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001686 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001687 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1688 case 6:
1689 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1690 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1691 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1692 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1693 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1694 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 break;
1696 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001697 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001698 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 break;
1700 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001701
1702 // check channel format caps
1703 i = 0;
1704 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1705 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1706 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1707 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1708 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1709 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1710 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1711 }
1712
Ben Romberger1aaaf862017-04-06 17:49:46 -07001713 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1714 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1715 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1716 }
1717
Mingming Yin3a941d42016-02-17 18:08:05 -08001718 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1719 ALOGV(":%s HDMI supports DTS format", __func__);
1720 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1721 }
1722
1723 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1724 ALOGV(":%s HDMI supports DTS HD format", __func__);
1725 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1726 }
1727
Naresh Tanniru928f0862017-04-07 16:44:23 -07001728 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1729 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1730 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1731 }
1732
Mingming Yin3a941d42016-02-17 18:08:05 -08001733
1734 // check sample rate caps
1735 i = 0;
1736 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1737 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1738 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1739 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1740 }
1741 }
1742
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001743 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744}
1745
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001746static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1747 uint32_t *supported_sample_rates __unused,
1748 uint32_t max_rates __unused)
1749{
1750 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1751 supported_sample_rates,
1752 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301753 ssize_t i = 0;
1754
1755 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001756 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1757 supported_sample_rates[i]);
1758 }
1759 return count;
1760}
1761
1762static inline int read_usb_sup_channel_masks(bool is_playback,
1763 audio_channel_mask_t *supported_channel_masks,
1764 uint32_t max_masks)
1765{
1766 int channels = audio_extn_usb_get_max_channels(is_playback);
1767 int channel_count;
1768 uint32_t num_masks = 0;
1769 if (channels > MAX_HIFI_CHANNEL_COUNT)
1770 channels = MAX_HIFI_CHANNEL_COUNT;
1771
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301772 channel_count = DEFAULT_CHANNEL_COUNT;
1773
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001774 if (is_playback) {
1775 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001776 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301777 // above 2 but we want indexed masks here.
1778 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001779 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001780 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1781 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301782 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001783 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301784
1785 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1786 (num_masks < max_masks)); channel_count--) {
1787 supported_channel_masks[num_masks++] =
1788 audio_channel_mask_for_index_assignment_from_count(channel_count);
1789 }
1790
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001791 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1792 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1793 return num_masks;
1794}
1795
1796static inline int read_usb_sup_formats(bool is_playback __unused,
1797 audio_format_t *supported_formats,
1798 uint32_t max_formats __unused)
1799{
1800 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1801 switch (bitwidth) {
1802 case 24:
1803 // XXX : usb.c returns 24 for s24 and s24_le?
1804 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1805 break;
1806 case 32:
1807 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1808 break;
1809 case 16:
1810 default :
1811 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1812 break;
1813 }
1814 ALOGV("%s: %s supported format %d", __func__,
1815 is_playback ? "P" : "C", bitwidth);
1816 return 1;
1817}
1818
1819static inline int read_usb_sup_params_and_compare(bool is_playback,
1820 audio_format_t *format,
1821 audio_format_t *supported_formats,
1822 uint32_t max_formats,
1823 audio_channel_mask_t *mask,
1824 audio_channel_mask_t *supported_channel_masks,
1825 uint32_t max_masks,
1826 uint32_t *rate,
1827 uint32_t *supported_sample_rates,
1828 uint32_t max_rates) {
1829 int ret = 0;
1830 int num_formats;
1831 int num_masks;
1832 int num_rates;
1833 int i;
1834
1835 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1836 max_formats);
1837 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1838 max_masks);
1839
1840 num_rates = read_usb_sup_sample_rates(is_playback,
1841 supported_sample_rates, max_rates);
1842
1843#define LUT(table, len, what, dflt) \
1844 for (i=0; i<len && (table[i] != what); i++); \
1845 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1846
1847 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1848 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1849 LUT(supported_sample_rates, num_rates, *rate, 0);
1850
1851#undef LUT
1852 return ret < 0 ? -EINVAL : 0; // HACK TBD
1853}
1854
Alexy Josephb1379942016-01-29 15:49:38 -08001855audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001856 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001857{
1858 struct audio_usecase *usecase;
1859 struct listnode *node;
1860
1861 list_for_each(node, &adev->usecase_list) {
1862 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001863 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001864 ALOGV("%s: usecase id %d", __func__, usecase->id);
1865 return usecase->id;
1866 }
1867 }
1868 return USECASE_INVALID;
1869}
1870
Alexy Josephb1379942016-01-29 15:49:38 -08001871struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001872 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873{
1874 struct audio_usecase *usecase;
1875 struct listnode *node;
1876
1877 list_for_each(node, &adev->usecase_list) {
1878 usecase = node_to_item(node, struct audio_usecase, list);
1879 if (usecase->id == uc_id)
1880 return usecase;
1881 }
1882 return NULL;
1883}
1884
Dhananjay Kumard4833242016-10-06 22:09:12 +05301885struct stream_in *get_next_active_input(const struct audio_device *adev)
1886{
1887 struct audio_usecase *usecase;
1888 struct listnode *node;
1889
1890 list_for_each_reverse(node, &adev->usecase_list) {
1891 usecase = node_to_item(node, struct audio_usecase, list);
1892 if (usecase->type == PCM_CAPTURE)
1893 return usecase->stream.in;
1894 }
1895 return NULL;
1896}
1897
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301898/*
1899 * is a true native playback active
1900 */
1901bool audio_is_true_native_stream_active(struct audio_device *adev)
1902{
1903 bool active = false;
1904 int i = 0;
1905 struct listnode *node;
1906
1907 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1908 ALOGV("%s:napb: not in true mode or non hdphones device",
1909 __func__);
1910 active = false;
1911 goto exit;
1912 }
1913
1914 list_for_each(node, &adev->usecase_list) {
1915 struct audio_usecase *uc;
1916 uc = node_to_item(node, struct audio_usecase, list);
1917 struct stream_out *curr_out =
1918 (struct stream_out*) uc->stream.out;
1919
1920 if (curr_out && PCM_PLAYBACK == uc->type) {
1921 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1922 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1923 uc->id, curr_out->sample_rate,
1924 curr_out->bit_width,
1925 platform_get_snd_device_name(uc->out_snd_device));
1926
1927 if (is_offload_usecase(uc->id) &&
1928 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1929 active = true;
1930 ALOGD("%s:napb:native stream detected", __func__);
1931 }
1932 }
1933 }
1934exit:
1935 return active;
1936}
1937
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001938uint32_t adev_get_dsp_bit_width_enforce_mode()
1939{
1940 if (adev == NULL) {
1941 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1942 return 0;
1943 }
1944 return adev->dsp_bit_width_enforce_mode;
1945}
1946
1947static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1948{
1949 char value[PROPERTY_VALUE_MAX];
1950 int trial;
1951 uint32_t dsp_bit_width_enforce_mode = 0;
1952
1953 if (!mixer) {
1954 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1955 __func__);
1956 return 0;
1957 }
1958
1959 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1960 value, NULL) > 0) {
1961 trial = atoi(value);
1962 switch (trial) {
1963 case 16:
1964 dsp_bit_width_enforce_mode = 16;
1965 break;
1966 case 24:
1967 dsp_bit_width_enforce_mode = 24;
1968 break;
1969 case 32:
1970 dsp_bit_width_enforce_mode = 32;
1971 break;
1972 default:
1973 dsp_bit_width_enforce_mode = 0;
1974 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1975 break;
1976 }
1977 }
1978
1979 return dsp_bit_width_enforce_mode;
1980}
1981
1982static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1983 uint32_t enforce_mode,
1984 bool enable)
1985{
1986 struct mixer_ctl *ctl = NULL;
1987 const char *mixer_ctl_name = "ASM Bit Width";
1988 uint32_t asm_bit_width_mode = 0;
1989
1990 if (enforce_mode == 0) {
1991 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1992 return;
1993 }
1994
1995 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1996 if (!ctl) {
1997 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1998 __func__, mixer_ctl_name);
1999 return;
2000 }
2001
2002 if (enable)
2003 asm_bit_width_mode = enforce_mode;
2004 else
2005 asm_bit_width_mode = 0;
2006
2007 ALOGV("%s DSP bit width feature status is %d width=%d",
2008 __func__, enable, asm_bit_width_mode);
2009 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2010 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2011 asm_bit_width_mode);
2012
2013 return;
2014}
2015
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302016/*
2017 * if native DSD playback active
2018 */
2019bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2020{
2021 bool active = false;
2022 struct listnode *node = NULL;
2023 struct audio_usecase *uc = NULL;
2024 struct stream_out *curr_out = NULL;
2025
2026 list_for_each(node, &adev->usecase_list) {
2027 uc = node_to_item(node, struct audio_usecase, list);
2028 curr_out = (struct stream_out*) uc->stream.out;
2029
2030 if (curr_out && PCM_PLAYBACK == uc->type &&
2031 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2032 active = true;
2033 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302034 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302035 }
2036 }
2037 return active;
2038}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302039
2040static bool force_device_switch(struct audio_usecase *usecase)
2041{
2042 bool ret = false;
2043 bool is_it_true_mode = false;
2044
Zhou Song30f2c3e2018-02-08 14:02:15 +08002045 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302046 usecase->type == TRANSCODE_LOOPBACK_RX ||
2047 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002048 return false;
2049 }
2050
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002051 if(usecase->stream.out == NULL) {
2052 ALOGE("%s: stream.out is NULL", __func__);
2053 return false;
2054 }
2055
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302056 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002057 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2058 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2059 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302060 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2061 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2062 (!is_it_true_mode && adev->native_playback_enabled)){
2063 ret = true;
2064 ALOGD("napb: time to toggle native mode");
2065 }
2066 }
2067
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302068 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302069 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2070 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002071 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302072 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302073 ALOGD("Force a2dp device switch to update new encoder config");
2074 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002075 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302076
Florian Pfister1a84f312018-07-19 14:38:18 +02002077 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302078 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2079 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002080 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302081 return ret;
2082}
2083
Aalique Grahame22e49102018-12-18 14:23:57 -08002084static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2085{
2086 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2087}
2088
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302089bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2090{
2091 bool ret=false;
2092 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2093 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2094 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2095 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2096 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2097 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2098 ret = true;
2099
2100 return ret;
2101}
2102
2103bool is_a2dp_device(snd_device_t out_snd_device)
2104{
2105 bool ret=false;
2106 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2107 ret = true;
2108
2109 return ret;
2110}
2111
2112bool is_bt_soc_on(struct audio_device *adev)
2113{
2114 struct mixer_ctl *ctl;
2115 char *mixer_ctl_name = "BT SOC status";
2116 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2117 bool bt_soc_status = true;
2118 if (!ctl) {
2119 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2120 __func__, mixer_ctl_name);
2121 /*This is to ensure we dont break targets which dont have the kernel change*/
2122 return true;
2123 }
2124 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2125 ALOGD("BT SOC status: %d",bt_soc_status);
2126 return bt_soc_status;
2127}
2128
2129int out_standby_l(struct audio_stream *stream);
2130
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002131int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002133 snd_device_t out_snd_device = SND_DEVICE_NONE;
2134 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002135 struct audio_usecase *usecase = NULL;
2136 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002137 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002138 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302139 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002140 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302143 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2144
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002145 usecase = get_usecase_from_list(adev, uc_id);
2146 if (usecase == NULL) {
2147 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2148 return -EINVAL;
2149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002151 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002152 (usecase->type == VOIP_CALL) ||
2153 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302154 if(usecase->stream.out == NULL) {
2155 ALOGE("%s: stream.out is NULL", __func__);
2156 return -EINVAL;
2157 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002158 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002159 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002160 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002161 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302162 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302163 if (usecase->stream.inout == NULL) {
2164 ALOGE("%s: stream.inout is NULL", __func__);
2165 return -EINVAL;
2166 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302167 stream_out.devices = usecase->stream.inout->out_config.devices;
2168 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2169 stream_out.format = usecase->stream.inout->out_config.format;
2170 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2171 out_snd_device = platform_get_output_snd_device(adev->platform,
2172 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302173 usecase->devices = out_snd_device;
2174 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2175 if (usecase->stream.inout == NULL) {
2176 ALOGE("%s: stream.inout is NULL", __func__);
2177 return -EINVAL;
2178 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302179 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302180 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 } else {
2182 /*
2183 * If the voice call is active, use the sound devices of voice call usecase
2184 * so that it would not result any device switch. All the usecases will
2185 * be switched to new device when select_devices() is called for voice call
2186 * usecase. This is to avoid switching devices for voice call when
2187 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002188 * choose voice call device only if the use case device is
2189 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002190 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002191 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002192 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002193 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002194 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2195 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302196 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2197 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002198 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002199 in_snd_device = vc_usecase->in_snd_device;
2200 out_snd_device = vc_usecase->out_snd_device;
2201 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002202 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002203 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002204 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002205 if ((voip_usecase != NULL) &&
2206 (usecase->type == PCM_PLAYBACK) &&
2207 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002208 out_snd_device_backend_match = platform_check_backends_match(
2209 voip_usecase->out_snd_device,
2210 platform_get_output_snd_device(
2211 adev->platform,
2212 usecase->stream.out));
2213 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002214 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002215 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2216 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002217 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002218 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002219 in_snd_device = voip_usecase->in_snd_device;
2220 out_snd_device = voip_usecase->out_snd_device;
2221 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002222 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002223 hfp_ucid = audio_extn_hfp_get_usecase();
2224 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002225 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002226 in_snd_device = hfp_usecase->in_snd_device;
2227 out_snd_device = hfp_usecase->out_snd_device;
2228 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002229 }
2230 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302231 if (usecase->stream.out == NULL) {
2232 ALOGE("%s: stream.out is NULL", __func__);
2233 return -EINVAL;
2234 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235 usecase->devices = usecase->stream.out->devices;
2236 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002237 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002238 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002239 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002240 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002241 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002242 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2243
2244 if ((usecase->stream.out != NULL &&
2245 voip_usecase != NULL &&
2246 usecase->stream.out->usecase == voip_usecase->id) &&
2247 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002248 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2249 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002250 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002251 select_devices(adev, adev->active_input->usecase);
2252 }
2253 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002254 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302255 if (usecase->stream.in == NULL) {
2256 ALOGE("%s: stream.in is NULL", __func__);
2257 return -EINVAL;
2258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 usecase->devices = usecase->stream.in->device;
2260 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002261 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002262 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002263 if (adev->active_input &&
2264 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302265 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002266 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2267 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2268 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2269 out_device = voip_usecase->stream.out->devices;
2270 else if (adev->primary_output && !adev->primary_output->standby)
2271 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002272 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002273 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2274 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002275 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002276 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002277 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002278 }
2279 }
2280
2281 if (out_snd_device == usecase->out_snd_device &&
2282 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302283
2284 if (!force_device_switch(usecase))
2285 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 }
2287
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302288 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002289 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302290 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2291 return 0;
2292 }
2293
Aalique Grahame22e49102018-12-18 14:23:57 -08002294 if (out_snd_device != SND_DEVICE_NONE &&
2295 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2296 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2297 __func__,
2298 use_case_table[uc_id],
2299 adev->last_logged_snd_device[uc_id][0],
2300 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2301 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2302 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2303 -1,
2304 out_snd_device,
2305 platform_get_snd_device_name(out_snd_device),
2306 platform_get_snd_device_acdb_id(out_snd_device));
2307 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2308 }
2309 if (in_snd_device != SND_DEVICE_NONE &&
2310 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2311 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2312 __func__,
2313 use_case_table[uc_id],
2314 adev->last_logged_snd_device[uc_id][1],
2315 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2316 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2317 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2318 -1,
2319 in_snd_device,
2320 platform_get_snd_device_name(in_snd_device),
2321 platform_get_snd_device_acdb_id(in_snd_device));
2322 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2323 }
2324
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326 /*
2327 * Limitation: While in call, to do a device switch we need to disable
2328 * and enable both RX and TX devices though one of them is same as current
2329 * device.
2330 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002331 if ((usecase->type == VOICE_CALL) &&
2332 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2333 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002334 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002335 }
2336
2337 if (((usecase->type == VOICE_CALL) ||
2338 (usecase->type == VOIP_CALL)) &&
2339 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2340 /* Disable sidetone only if voice/voip call already exists */
2341 if (voice_is_call_state_active(adev) ||
2342 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002343 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002344
2345 /* Disable aanc only if voice call exists */
2346 if (voice_is_call_state_active(adev))
2347 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002348 }
2349
Aalique Grahame22e49102018-12-18 14:23:57 -08002350 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2351 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002352 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302353 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002354 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2355 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2356 else
2357 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302358 }
2359
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002360 /* Disable current sound devices */
2361 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002362 disable_audio_route(adev, usecase);
2363 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 }
2365
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002366 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002367 disable_audio_route(adev, usecase);
2368 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369 }
2370
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002371 /* Applicable only on the targets that has external modem.
2372 * New device information should be sent to modem before enabling
2373 * the devices to reduce in-call device switch time.
2374 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002375 if ((usecase->type == VOICE_CALL) &&
2376 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2377 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002378 status = platform_switch_voice_call_enable_device_config(adev->platform,
2379 out_snd_device,
2380 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002381 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002382
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002383 /* Enable new sound devices */
2384 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002385 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302386 if (platform_check_codec_asrc_support(adev->platform))
2387 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002388 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 }
2390
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002391 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302392 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002393 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002394 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002395
Avinash Vaish71a8b972014-07-24 15:36:33 +05302396 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002397 status = platform_switch_voice_call_device_post(adev->platform,
2398 out_snd_device,
2399 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302400 enable_audio_route_for_voice_usecases(adev, usecase);
2401 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002402
sangwoo170731f2013-06-08 15:36:36 +09002403 usecase->in_snd_device = in_snd_device;
2404 usecase->out_snd_device = out_snd_device;
2405
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302406 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2407 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302408 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002409 if ((24 == usecase->stream.out->bit_width) &&
2410 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2411 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2412 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2413 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2414 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2415 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2416 /*
2417 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2418 * configured device sample rate, if not update the COPP rate to be equal to the
2419 * device sample rate, else open COPP at stream sample rate
2420 */
2421 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2422 usecase->stream.out->sample_rate,
2423 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302424 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2425 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002426 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2427 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2428 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2429 }
2430
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002431 /* Notify device change info to effect clients registered */
2432 audio_extn_gef_notify_device_config(
2433 usecase->stream.out->devices,
2434 usecase->stream.out->channel_mask,
2435 usecase->stream.out->app_type_cfg.sample_rate,
2436 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302437 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002438 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002439
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002440 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002441
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002442 /* If input stream is already running then effect needs to be
2443 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002444 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2445 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002446 check_and_enable_effect(adev);
2447
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002448 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002449 /* Enable aanc only if voice call exists */
2450 if (voice_is_call_state_active(adev))
2451 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2452
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002453 /* Enable sidetone only if other voice/voip call already exists */
2454 if (voice_is_call_state_active(adev) ||
2455 voice_extn_compress_voip_is_started(adev))
2456 voice_set_sidetone(adev, out_snd_device, true);
2457 }
2458
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002459 /* Applicable only on the targets that has external modem.
2460 * Enable device command should be sent to modem only after
2461 * enabling voice call mixer controls
2462 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002463 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002464 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2465 out_snd_device,
2466 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467
2468 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2469
2470 if (usecase->type == VOIP_CALL) {
2471 if (adev->active_input != NULL &&
2472 !adev->active_input->standby) {
2473 if (is_bt_soc_on(adev) == false){
2474 ALOGD("BT SCO MIC disconnected while in connection");
2475 if (adev->active_input->pcm != NULL)
2476 pcm_stop(adev->active_input->pcm);
2477 }
2478 }
2479 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2480 && usecase->stream.out->started) {
2481 if (is_bt_soc_on(adev) == false) {
2482 ALOGD("BT SCO/A2DP disconnected while in connection");
2483 out_standby_l(&usecase->stream.out->stream.common);
2484 }
2485 }
2486 } else if ((usecase->stream.out != NULL) &&
2487 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302488 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2489 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302490 usecase->stream.out->started) {
2491 if (is_bt_soc_on(adev) == false) {
2492 ALOGD("BT SCO/A2dp disconnected while in connection");
2493 out_standby_l(&usecase->stream.out->stream.common);
2494 }
2495 }
2496 }
2497
Aalique Grahame22e49102018-12-18 14:23:57 -08002498 if (usecase == voip_usecase) {
2499 struct stream_out *voip_out = voip_usecase->stream.out;
2500 audio_extn_utils_send_app_type_gain(adev,
2501 voip_out->app_type_cfg.app_type,
2502 &voip_out->app_type_cfg.gain[0]);
2503 }
2504
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302505 ALOGD("%s: done",__func__);
2506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 return status;
2508}
2509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510static int stop_input_stream(struct stream_in *in)
2511{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302512 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302514
2515 if (in == NULL) {
2516 ALOGE("%s: stream_in ptr is NULL", __func__);
2517 return -EINVAL;
2518 }
2519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 struct audio_device *adev = in->dev;
2521
Eric Laurent994a6932013-07-17 11:51:42 -07002522 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002523 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 uc_info = get_usecase_from_list(adev, in->usecase);
2525 if (uc_info == NULL) {
2526 ALOGE("%s: Could not find the usecase (%d) in the list",
2527 __func__, in->usecase);
2528 return -EINVAL;
2529 }
2530
Derek Chenea197282019-01-07 17:35:01 -08002531 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2532 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002533
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002534 /* Close in-call recording streams */
2535 voice_check_and_stop_incall_rec_usecase(adev, in);
2536
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002538 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002539
2540 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002541 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002543 list_remove(&uc_info->list);
2544 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002546 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302547 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002548 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 return ret;
2550}
2551
2552int start_input_stream(struct stream_in *in)
2553{
2554 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002555 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302557
2558 if (in == NULL) {
2559 ALOGE("%s: stream_in ptr is NULL", __func__);
2560 return -EINVAL;
2561 }
2562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002564 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002565 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
Mingming Yin2664a5b2015-09-03 10:53:11 -07002567 if (get_usecase_from_list(adev, usecase) == NULL)
2568 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302569 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2570 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002571
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302572 if (CARD_STATUS_OFFLINE == in->card_status||
2573 CARD_STATUS_OFFLINE == adev->card_status) {
2574 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302575 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302576 goto error_config;
2577 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302578
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302579 if (audio_is_bluetooth_sco_device(in->device)) {
2580 if (!adev->bt_sco_on) {
2581 ALOGE("%s: SCO profile is not ready, return error", __func__);
2582 ret = -EIO;
2583 goto error_config;
2584 }
2585 }
2586
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002587 /* Check if source matches incall recording usecase criteria */
2588 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2589 if (ret)
2590 goto error_config;
2591 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002592 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2593
2594 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2595 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2596 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002597 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002598 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002599
Eric Laurentb23d5282013-05-14 15:27:20 -07002600 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 if (in->pcm_device_id < 0) {
2602 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2603 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002604 ret = -EINVAL;
2605 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002607
2608 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002610
2611 if (!uc_info) {
2612 ret = -ENOMEM;
2613 goto error_config;
2614 }
2615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 uc_info->id = in->usecase;
2617 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002618 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002619 uc_info->devices = in->device;
2620 uc_info->in_snd_device = SND_DEVICE_NONE;
2621 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002623 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302624 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2625 adev->perf_lock_opts,
2626 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002627 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
Derek Chenea197282019-01-07 17:35:01 -08002629 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2630 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002631
Haynes Mathew George16081042017-05-31 17:16:49 -07002632 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302633 ret = audio_extn_cin_start_input_stream(in);
2634 if (ret)
2635 goto error_open;
2636 else
2637 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002638 }
2639
Haynes Mathew George16081042017-05-31 17:16:49 -07002640 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002641 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002642 ALOGE("%s: pcm stream not ready", __func__);
2643 goto error_open;
2644 }
2645 ret = pcm_start(in->pcm);
2646 if (ret < 0) {
2647 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2648 goto error_open;
2649 }
2650 } else {
2651 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2652 unsigned int pcm_open_retry_count = 0;
2653
2654 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2655 flags |= PCM_MMAP | PCM_NOIRQ;
2656 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2657 } else if (in->realtime) {
2658 flags |= PCM_MMAP | PCM_NOIRQ;
2659 }
2660
Garmond Leunge2433c32017-09-28 21:51:22 -07002661 if (audio_extn_ffv_get_stream() == in) {
2662 ALOGD("%s: ffv stream, update pcm config", __func__);
2663 audio_extn_ffv_update_pcm_config(&config);
2664 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002665 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2666 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2667
2668 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002669 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002670 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002671 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002672 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302673 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302674 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2675 adev->card_status = CARD_STATUS_OFFLINE;
2676 in->card_status = CARD_STATUS_OFFLINE;
2677 ret = -EIO;
2678 goto error_open;
2679 }
2680
Haynes Mathew George16081042017-05-31 17:16:49 -07002681 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2682 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2683 if (in->pcm != NULL) {
2684 pcm_close(in->pcm);
2685 in->pcm = NULL;
2686 }
2687 if (pcm_open_retry_count-- == 0) {
2688 ret = -EIO;
2689 goto error_open;
2690 }
2691 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2692 continue;
2693 }
2694 break;
2695 }
2696
2697 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002698 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002699 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002700 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002701 if (ret < 0) {
2702 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2703 pcm_close(in->pcm);
2704 in->pcm = NULL;
2705 goto error_open;
2706 }
2707 register_in_stream(in);
2708 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002709 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002710 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002711 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002712 if (ret < 0) {
2713 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002714 pcm_close(in->pcm);
2715 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002716 goto error_open;
2717 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002718 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002719 }
2720
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002721 check_and_enable_effect(adev);
2722
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302723done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302724 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002725 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302726 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002727 return ret;
2728
2729error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302730 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002732error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302733 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302734 /*
2735 * sleep 50ms to allow sufficient time for kernel
2736 * drivers to recover incases like SSR.
2737 */
2738 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002739 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302740 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002741 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742}
2743
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002744void lock_input_stream(struct stream_in *in)
2745{
2746 pthread_mutex_lock(&in->pre_lock);
2747 pthread_mutex_lock(&in->lock);
2748 pthread_mutex_unlock(&in->pre_lock);
2749}
2750
2751void lock_output_stream(struct stream_out *out)
2752{
2753 pthread_mutex_lock(&out->pre_lock);
2754 pthread_mutex_lock(&out->lock);
2755 pthread_mutex_unlock(&out->pre_lock);
2756}
2757
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758/* must be called with out->lock locked */
2759static int send_offload_cmd_l(struct stream_out* out, int command)
2760{
2761 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2762
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002763 if (!cmd) {
2764 ALOGE("failed to allocate mem for command 0x%x", command);
2765 return -ENOMEM;
2766 }
2767
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002768 ALOGVV("%s %d", __func__, command);
2769
2770 cmd->cmd = command;
2771 list_add_tail(&out->offload_cmd_list, &cmd->node);
2772 pthread_cond_signal(&out->offload_cond);
2773 return 0;
2774}
2775
2776/* must be called iwth out->lock locked */
2777static void stop_compressed_output_l(struct stream_out *out)
2778{
2779 out->offload_state = OFFLOAD_STATE_IDLE;
2780 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002781 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002782 if (out->compr != NULL) {
2783 compress_stop(out->compr);
2784 while (out->offload_thread_blocked) {
2785 pthread_cond_wait(&out->cond, &out->lock);
2786 }
2787 }
2788}
2789
Varun Balaraje49253e2017-07-06 19:48:56 +05302790bool is_interactive_usecase(audio_usecase_t uc_id)
2791{
2792 unsigned int i;
2793 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2794 if (uc_id == interactive_usecases[i])
2795 return true;
2796 }
2797 return false;
2798}
2799
2800static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2801{
2802 audio_usecase_t ret_uc = USECASE_INVALID;
2803 unsigned int intract_uc_index;
2804 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2805
2806 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2807 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2808 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2809 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2810 ret_uc = interactive_usecases[intract_uc_index];
2811 break;
2812 }
2813 }
2814
2815 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2816 return ret_uc;
2817}
2818
2819static void free_interactive_usecase(struct audio_device *adev,
2820 audio_usecase_t uc_id)
2821{
2822 unsigned int interact_uc_index;
2823 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2824
2825 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2826 if (interactive_usecases[interact_uc_index] == uc_id) {
2827 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2828 break;
2829 }
2830 }
2831 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2832}
2833
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002834bool is_offload_usecase(audio_usecase_t uc_id)
2835{
2836 unsigned int i;
2837 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2838 if (uc_id == offload_usecases[i])
2839 return true;
2840 }
2841 return false;
2842}
2843
Dhananjay Kumarac341582017-02-23 23:42:25 +05302844static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002845{
vivek mehta446c3962015-09-14 10:57:35 -07002846 audio_usecase_t ret_uc = USECASE_INVALID;
2847 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002848 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002849 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302850 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002851 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2852 else
2853 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002854
vivek mehta446c3962015-09-14 10:57:35 -07002855 pthread_mutex_lock(&adev->lock);
2856 if (get_usecase_from_list(adev, ret_uc) != NULL)
2857 ret_uc = USECASE_INVALID;
2858 pthread_mutex_unlock(&adev->lock);
2859
2860 return ret_uc;
2861 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002862
2863 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002864 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2865 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2866 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2867 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002868 break;
2869 }
2870 }
vivek mehta446c3962015-09-14 10:57:35 -07002871
2872 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2873 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002874}
2875
2876static void free_offload_usecase(struct audio_device *adev,
2877 audio_usecase_t uc_id)
2878{
vivek mehta446c3962015-09-14 10:57:35 -07002879 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002880 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002881
2882 if (!adev->multi_offload_enable)
2883 return;
2884
2885 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2886 if (offload_usecases[offload_uc_index] == uc_id) {
2887 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002888 break;
2889 }
2890 }
2891 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2892}
2893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894static void *offload_thread_loop(void *context)
2895{
2896 struct stream_out *out = (struct stream_out *) context;
2897 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002898 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002901 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2903
2904 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002905 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 for (;;) {
2907 struct offload_cmd *cmd = NULL;
2908 stream_callback_event_t event;
2909 bool send_callback = false;
2910
2911 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2912 __func__, list_empty(&out->offload_cmd_list),
2913 out->offload_state);
2914 if (list_empty(&out->offload_cmd_list)) {
2915 ALOGV("%s SLEEPING", __func__);
2916 pthread_cond_wait(&out->offload_cond, &out->lock);
2917 ALOGV("%s RUNNING", __func__);
2918 continue;
2919 }
2920
2921 item = list_head(&out->offload_cmd_list);
2922 cmd = node_to_item(item, struct offload_cmd, node);
2923 list_remove(item);
2924
2925 ALOGVV("%s STATE %d CMD %d out->compr %p",
2926 __func__, out->offload_state, cmd->cmd, out->compr);
2927
2928 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2929 free(cmd);
2930 break;
2931 }
2932
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002933 // allow OFFLOAD_CMD_ERROR reporting during standby
2934 // this is needed to handle failures during compress_open
2935 // Note however that on a pause timeout, the stream is closed
2936 // and no offload usecase will be active. Therefore this
2937 // special case is needed for compress_open failures alone
2938 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2939 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002941 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942 pthread_cond_signal(&out->cond);
2943 continue;
2944 }
2945 out->offload_thread_blocked = true;
2946 pthread_mutex_unlock(&out->lock);
2947 send_callback = false;
2948 switch(cmd->cmd) {
2949 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002950 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002952 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 send_callback = true;
2954 event = STREAM_CBK_EVENT_WRITE_READY;
2955 break;
2956 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002957 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302958 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002959 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302960 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002961 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302962 if (ret < 0)
2963 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302964 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302965 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002966 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002967 else
2968 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002969 if (-ENETRESET != ret && !(-EINTR == ret &&
2970 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302971 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302972 pthread_mutex_lock(&out->lock);
2973 out->send_new_metadata = 1;
2974 out->send_next_track_params = true;
2975 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302976 event = STREAM_CBK_EVENT_DRAIN_READY;
2977 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2978 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302979 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980 break;
2981 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002982 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002983 ret = compress_drain(out->compr);
2984 ALOGD("copl(%p):out of compress_drain", out);
2985 // EINTR check avoids drain interruption due to SSR
2986 if (-ENETRESET != ret && !(-EINTR == ret &&
2987 CARD_STATUS_OFFLINE == out->card_status)) {
2988 send_callback = true;
2989 event = STREAM_CBK_EVENT_DRAIN_READY;
2990 } else
2991 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302993 case OFFLOAD_CMD_ERROR:
2994 ALOGD("copl(%p): sending error callback to AF", out);
2995 send_callback = true;
2996 event = STREAM_CBK_EVENT_ERROR;
2997 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 default:
2999 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3000 break;
3001 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003002 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 out->offload_thread_blocked = false;
3004 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003005 if (send_callback && out->client_callback) {
3006 ALOGVV("%s: sending client_callback event %d", __func__, event);
3007 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003008 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003009 free(cmd);
3010 }
3011
3012 pthread_cond_signal(&out->cond);
3013 while (!list_empty(&out->offload_cmd_list)) {
3014 item = list_head(&out->offload_cmd_list);
3015 list_remove(item);
3016 free(node_to_item(item, struct offload_cmd, node));
3017 }
3018 pthread_mutex_unlock(&out->lock);
3019
3020 return NULL;
3021}
3022
3023static int create_offload_callback_thread(struct stream_out *out)
3024{
3025 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3026 list_init(&out->offload_cmd_list);
3027 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3028 offload_thread_loop, out);
3029 return 0;
3030}
3031
3032static int destroy_offload_callback_thread(struct stream_out *out)
3033{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003034 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003035 stop_compressed_output_l(out);
3036 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3037
3038 pthread_mutex_unlock(&out->lock);
3039 pthread_join(out->offload_thread, (void **) NULL);
3040 pthread_cond_destroy(&out->offload_cond);
3041
3042 return 0;
3043}
3044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045static int stop_output_stream(struct stream_out *out)
3046{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303047 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 struct audio_usecase *uc_info;
3049 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003050 bool has_voip_usecase =
3051 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052
Eric Laurent994a6932013-07-17 11:51:42 -07003053 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003054 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 uc_info = get_usecase_from_list(adev, out->usecase);
3056 if (uc_info == NULL) {
3057 ALOGE("%s: Could not find the usecase (%d) in the list",
3058 __func__, out->usecase);
3059 return -EINVAL;
3060 }
3061
Derek Chenea197282019-01-07 17:35:01 -08003062 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3063 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003064
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003065 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303066 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003067 if (adev->visualizer_stop_output != NULL)
3068 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003069
3070 audio_extn_dts_remove_state_notifier_node(out->usecase);
3071
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003072 if (adev->offload_effects_stop_output != NULL)
3073 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3074 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003075
Arun Mirpurief53ce52018-09-11 18:00:09 -07003076 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3077 voice_set_device_mute_flag(adev, false);
3078
Eric Laurent150dbfe2013-02-27 14:31:02 -08003079 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003080 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003081
3082 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003083 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084
Aalique Grahame22e49102018-12-18 14:23:57 -08003085 audio_extn_extspk_update(adev->extspk);
3086
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003087 if (is_offload_usecase(out->usecase)) {
3088 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3089 adev->dsp_bit_width_enforce_mode,
3090 false);
3091 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003092 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3093 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3094 false);
3095
3096 if (ret != 0)
3097 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3098 /* default service interval was successfully updated,
3099 reopen USB backend with new service interval */
3100 ret = 0;
3101 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003102
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003103 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303104 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003105 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303106 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003107 ALOGV("Disable passthrough , reset mixer to pcm");
3108 /* NO_PASSTHROUGH */
3109 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003110 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003111 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3112 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003113
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303114 /* Must be called after removing the usecase from list */
3115 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303116 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303117
Manish Dewangan21a850a2017-08-14 12:03:55 +05303118 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003119 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3120 if (ret < 0)
3121 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3122 }
3123
Aalique Grahame22e49102018-12-18 14:23:57 -08003124 if (has_voip_usecase ||
3125 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3126 struct listnode *node;
3127 struct audio_usecase *usecase;
3128 list_for_each(node, &adev->usecase_list) {
3129 usecase = node_to_item(node, struct audio_usecase, list);
3130 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3131 continue;
3132
3133 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3134 __func__, usecase->id, use_case_table[usecase->id],
3135 out->usecase, use_case_table[out->usecase]);
3136 select_devices(adev, usecase->id);
3137 }
3138 }
3139
Garmond Leung5fd0b552018-04-17 11:56:12 -07003140 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003141 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 return ret;
3143}
3144
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003145struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3146 unsigned int flags, unsigned int pcm_open_retry_count,
3147 struct pcm_config *config)
3148{
3149 struct pcm* pcm = NULL;
3150
3151 while (1) {
3152 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3153 if (pcm == NULL || !pcm_is_ready(pcm)) {
3154 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3155 if (pcm != NULL) {
3156 pcm_close(pcm);
3157 pcm = NULL;
3158 }
3159 if (pcm_open_retry_count-- == 0)
3160 return NULL;
3161
3162 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3163 continue;
3164 }
3165 break;
3166 }
3167
3168 if (pcm_is_ready(pcm)) {
3169 int ret = pcm_prepare(pcm);
3170 if (ret < 0) {
3171 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3172 pcm_close(pcm);
3173 pcm = NULL;
3174 }
3175 }
3176
3177 return pcm;
3178}
3179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180int start_output_stream(struct stream_out *out)
3181{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 struct audio_usecase *uc_info;
3184 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003185 char mixer_ctl_name[128];
3186 struct mixer_ctl *ctl = NULL;
3187 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303188 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003189 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190
Haynes Mathew George380745d2017-10-04 15:27:45 -07003191 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003192 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3193 ret = -EINVAL;
3194 goto error_config;
3195 }
3196
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003197 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303198 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003199 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303200
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303201 if (CARD_STATUS_OFFLINE == out->card_status ||
3202 CARD_STATUS_OFFLINE == adev->card_status) {
3203 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303204 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303205 goto error_config;
3206 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303207
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303208 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003209 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003210 if (out->devices &
3211 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303212 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303213 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303214 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3215 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3216 ret = -EAGAIN;
3217 goto error_config;
3218 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303219 }
3220 }
3221 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303222 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3223 if (!adev->bt_sco_on) {
3224 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3225 //combo usecase just by pass a2dp
3226 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3227 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3228 } else {
3229 ALOGE("%s: SCO profile is not ready, return error", __func__);
3230 ret = -EAGAIN;
3231 goto error_config;
3232 }
3233 }
3234 }
3235
Eric Laurentb23d5282013-05-14 15:27:20 -07003236 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 if (out->pcm_device_id < 0) {
3238 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3239 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003240 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003241 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 }
3243
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003244 if (is_haptic_usecase) {
3245 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3246 if (adev->haptic_pcm_device_id < 0) {
3247 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3248 __func__, adev->haptic_pcm_device_id, out->usecase);
3249 ret = -EINVAL;
3250 goto error_config;
3251 }
3252 }
3253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003255
3256 if (!uc_info) {
3257 ret = -ENOMEM;
3258 goto error_config;
3259 }
3260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 uc_info->id = out->usecase;
3262 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003263 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003264 uc_info->devices = out->devices;
3265 uc_info->in_snd_device = SND_DEVICE_NONE;
3266 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003267
3268 /* This must be called before adding this usecase to the list */
3269 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3270 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3271 /* USB backend is not reopened immediately.
3272 This is eventually done as part of select_devices */
3273 }
3274
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003275 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303277 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3278 adev->perf_lock_opts,
3279 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303280
3281 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303282 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303283 if (audio_extn_passthru_is_enabled() &&
3284 audio_extn_passthru_is_passthrough_stream(out)) {
3285 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303286 }
3287 }
3288
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303289 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003290 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303291 if (!a2dp_combo) {
3292 check_a2dp_restore_l(adev, out, false);
3293 } else {
3294 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003295 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3296 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3297 else
3298 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303299 select_devices(adev, out->usecase);
3300 out->devices = dev;
3301 }
3302 } else {
3303 select_devices(adev, out->usecase);
3304 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003305
Arun Mirpurief53ce52018-09-11 18:00:09 -07003306 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3307 voice_set_device_mute_flag(adev, true);
3308
Derek Chenea197282019-01-07 17:35:01 -08003309 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3310 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003311
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003312 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3313 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003314
3315 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003316 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003317 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3318 ALOGE("%s: pcm stream not ready", __func__);
3319 goto error_open;
3320 }
3321 ret = pcm_start(out->pcm);
3322 if (ret < 0) {
3323 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3324 goto error_open;
3325 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003326 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003327 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003328 unsigned int flags = PCM_OUT;
3329 unsigned int pcm_open_retry_count = 0;
3330 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3331 flags |= PCM_MMAP | PCM_NOIRQ;
3332 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003333 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003334 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003335 } else
3336 flags |= PCM_MONOTONIC;
3337
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003338 if ((adev->vr_audio_mode_enabled) &&
3339 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3340 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3341 "PCM_Dev %d Topology", out->pcm_device_id);
3342 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3343 if (!ctl) {
3344 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3345 __func__, mixer_ctl_name);
3346 } else {
3347 //if success use ULLPP
3348 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3349 __func__, mixer_ctl_name, out->pcm_device_id);
3350 //There is a still a possibility that some sessions
3351 // that request for FAST|RAW when 3D audio is active
3352 //can go through ULLPP. Ideally we expects apps to
3353 //listen to audio focus and stop concurrent playback
3354 //Also, we will look for mode flag (voice_in_communication)
3355 //before enabling the realtime flag.
3356 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3357 }
3358 }
3359
Surendar Karka91fa3682018-07-02 18:12:12 +05303360 if (out->realtime)
3361 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3362 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3363
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003364 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3365 flags, pcm_open_retry_count,
3366 &(out->config));
3367 if (out->pcm == NULL) {
3368 ret = -EIO;
3369 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003370 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003371
3372 if (is_haptic_usecase) {
3373 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3374 adev->haptic_pcm_device_id,
3375 flags, pcm_open_retry_count,
3376 &(adev->haptics_config));
3377 // failure to open haptics pcm shouldnt stop audio,
3378 // so do not close audio pcm in case of error
3379 }
3380
Surendar Karka91fa3682018-07-02 18:12:12 +05303381 if (!out->realtime)
3382 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303383 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003384
Zhou Song2b8f28f2017-09-11 10:51:38 +08003385 // apply volume for voip playback after path is set up
3386 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3387 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303388 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3389 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303390 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3391 out->apply_volume = false;
3392 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003393 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003394 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303395 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003396 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3397 adev->dsp_bit_width_enforce_mode,
3398 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003400 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003401 out->compr = compress_open(adev->snd_card,
3402 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003403 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003404 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303405 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303406 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3407 adev->card_status = CARD_STATUS_OFFLINE;
3408 out->card_status = CARD_STATUS_OFFLINE;
3409 ret = -EIO;
3410 goto error_open;
3411 }
3412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003414 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 compress_close(out->compr);
3416 out->compr = NULL;
3417 ret = -EIO;
3418 goto error_open;
3419 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303420 /* compress_open sends params of the track, so reset the flag here */
3421 out->is_compr_metadata_avail = false;
3422
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003423 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003425
Fred Oh3f43e742015-03-04 18:42:34 -08003426 /* Since small bufs uses blocking writes, a write will be blocked
3427 for the default max poll time (20s) in the event of an SSR.
3428 Reduce the poll time to observe and deal with SSR faster.
3429 */
Ashish Jain5106d362016-05-11 19:23:33 +05303430 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003431 compress_set_max_poll_wait(out->compr, 1000);
3432 }
3433
Manish Dewangan69426c82017-01-30 17:35:36 +05303434 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303435 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303436
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003437 audio_extn_dts_create_state_notifier_node(out->usecase);
3438 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3439 popcount(out->channel_mask),
3440 out->playback_started);
3441
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003442#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303443 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003444 audio_extn_dolby_send_ddp_endp_params(adev);
3445#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303446 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3447 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003448 if (adev->visualizer_start_output != NULL)
3449 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3450 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303451 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003452 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003453 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003455
3456 if (ret == 0) {
3457 register_out_stream(out);
3458 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003459 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3460 ALOGE("%s: pcm stream not ready", __func__);
3461 goto error_open;
3462 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003463 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003464 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003465 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003466 if (ret < 0)
3467 goto error_open;
3468 }
3469 }
3470
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303471 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003472 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003473
Manish Dewangan21a850a2017-08-14 12:03:55 +05303474 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003475 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003476 if (ret < 0)
3477 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3478 }
3479
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003480 // consider a scenario where on pause lower layers are tear down.
3481 // so on resume, swap mixer control need to be sent only when
3482 // backend is active, hence rather than sending from enable device
3483 // sending it from start of streamtream
3484
3485 platform_set_swap_channels(adev, true);
3486
Haynes Mathew George380745d2017-10-04 15:27:45 -07003487 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303488 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003489 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003491 if (adev->haptic_pcm) {
3492 pcm_close(adev->haptic_pcm);
3493 adev->haptic_pcm = NULL;
3494 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303495 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003497error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303498 /*
3499 * sleep 50ms to allow sufficient time for kernel
3500 * drivers to recover incases like SSR.
3501 */
3502 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003503 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303504 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003505 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506}
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508static int check_input_parameters(uint32_t sample_rate,
3509 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003510 int channel_count,
3511 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003513 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303515 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3516 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3517 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003518 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003519 !audio_extn_compr_cap_format_supported(format) &&
3520 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003521 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003522
Aalique Grahame22e49102018-12-18 14:23:57 -08003523 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3524 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3525 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3526 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3527 return -EINVAL;
3528 }
3529
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003530 switch (channel_count) {
3531 case 1:
3532 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303533 case 3:
3534 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003535 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003536 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003537 break;
3538 default:
3539 ret = -EINVAL;
3540 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541
3542 switch (sample_rate) {
3543 case 8000:
3544 case 11025:
3545 case 12000:
3546 case 16000:
3547 case 22050:
3548 case 24000:
3549 case 32000:
3550 case 44100:
3551 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003552 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303553 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003554 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303555 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 break;
3557 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003558 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 }
3560
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003561 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562}
3563
Naresh Tanniru04f71882018-06-26 17:46:22 +05303564
3565/** Add a value in a list if not already present.
3566 * @return true if value was successfully inserted or already present,
3567 * false if the list is full and does not contain the value.
3568 */
3569static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3570 for (size_t i = 0; i < list_length; i++) {
3571 if (list[i] == value) return true; // value is already present
3572 if (list[i] == 0) { // no values in this slot
3573 list[i] = value;
3574 return true; // value inserted
3575 }
3576 }
3577 return false; // could not insert value
3578}
3579
3580/** Add channel_mask in supported_channel_masks if not already present.
3581 * @return true if channel_mask was successfully inserted or already present,
3582 * false if supported_channel_masks is full and does not contain channel_mask.
3583 */
3584static void register_channel_mask(audio_channel_mask_t channel_mask,
3585 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3586 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3587 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3588}
3589
3590/** Add format in supported_formats if not already present.
3591 * @return true if format was successfully inserted or already present,
3592 * false if supported_formats is full and does not contain format.
3593 */
3594static void register_format(audio_format_t format,
3595 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3596 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3597 "%s: stream can not declare supporting its format %x", __func__, format);
3598}
3599/** Add sample_rate in supported_sample_rates if not already present.
3600 * @return true if sample_rate was successfully inserted or already present,
3601 * false if supported_sample_rates is full and does not contain sample_rate.
3602 */
3603static void register_sample_rate(uint32_t sample_rate,
3604 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3605 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3606 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3607}
3608
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003609static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3610{
3611 uint32_t high = num1, low = num2, temp = 0;
3612
3613 if (!num1 || !num2)
3614 return 0;
3615
3616 if (num1 < num2) {
3617 high = num2;
3618 low = num1;
3619 }
3620
3621 while (low != 0) {
3622 temp = low;
3623 low = high % low;
3624 high = temp;
3625 }
3626 return (num1 * num2)/high;
3627}
3628
3629static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3630{
3631 uint32_t remainder = 0;
3632
3633 if (!multiplier)
3634 return num;
3635
3636 remainder = num % multiplier;
3637 if (remainder)
3638 num += (multiplier - remainder);
3639
3640 return num;
3641}
3642
Aalique Grahame22e49102018-12-18 14:23:57 -08003643static size_t get_stream_buffer_size(size_t duration_ms,
3644 uint32_t sample_rate,
3645 audio_format_t format,
3646 int channel_count,
3647 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648{
3649 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003650 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651
Aalique Grahame22e49102018-12-18 14:23:57 -08003652 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003653 if (is_low_latency)
3654 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303655
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003656 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003657 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658
Ralf Herzbd08d632018-09-28 15:50:49 +02003659 /* make sure the size is multiple of 32 bytes and additionally multiple of
3660 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003661 * At 48 kHz mono 16-bit PCM:
3662 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3663 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003664 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003665 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003666 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003667
3668 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669}
3670
Aalique Grahame22e49102018-12-18 14:23:57 -08003671static size_t get_input_buffer_size(uint32_t sample_rate,
3672 audio_format_t format,
3673 int channel_count,
3674 bool is_low_latency)
3675{
3676 /* Don't know if USB HIFI in this context so use true to be conservative */
3677 if (check_input_parameters(sample_rate, format, channel_count,
3678 true /*is_usb_hifi */) != 0)
3679 return 0;
3680
3681 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3682 sample_rate,
3683 format,
3684 channel_count,
3685 is_low_latency);
3686}
3687
Ashish Jain058165c2016-09-28 23:18:48 +05303688static size_t get_output_period_size(uint32_t sample_rate,
3689 audio_format_t format,
3690 int channel_count,
3691 int duration /*in millisecs*/)
3692{
3693 size_t size = 0;
3694 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3695
3696 if ((duration == 0) || (sample_rate == 0) ||
3697 (bytes_per_sample == 0) || (channel_count == 0)) {
3698 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3699 bytes_per_sample, channel_count);
3700 return -EINVAL;
3701 }
3702
3703 size = (sample_rate *
3704 duration *
3705 bytes_per_sample *
3706 channel_count) / 1000;
3707 /*
3708 * To have same PCM samples for all channels, the buffer size requires to
3709 * be multiple of (number of channels * bytes per sample)
3710 * For writes to succeed, the buffer must be written at address which is multiple of 32
3711 */
3712 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3713
3714 return (size/(channel_count * bytes_per_sample));
3715}
3716
Zhou Song48453a02018-01-10 17:50:59 +08003717static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303718{
3719 uint64_t actual_frames_rendered = 0;
3720 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3721
3722 /* This adjustment accounts for buffering after app processor.
3723 * It is based on estimated DSP latency per use case, rather than exact.
3724 */
3725 int64_t platform_latency = platform_render_latency(out->usecase) *
3726 out->sample_rate / 1000000LL;
3727
Zhou Song48453a02018-01-10 17:50:59 +08003728 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303729 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3730 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3731 * hence only estimate.
3732 */
3733 int64_t signed_frames = out->written - kernel_buffer_size;
3734
3735 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3736
Zhou Song48453a02018-01-10 17:50:59 +08003737 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303738 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003739 if (timestamp != NULL )
3740 *timestamp = out->writeAt;
3741 } else if (timestamp != NULL) {
3742 clock_gettime(CLOCK_MONOTONIC, timestamp);
3743 }
3744 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303745
3746 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3747 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3748 (long long int)out->written, (int)kernel_buffer_size,
3749 audio_bytes_per_sample(out->compr_config.codec->format),
3750 popcount(out->channel_mask));
3751
3752 return actual_frames_rendered;
3753}
3754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3756{
3757 struct stream_out *out = (struct stream_out *)stream;
3758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003759 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760}
3761
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003762static int out_set_sample_rate(struct audio_stream *stream __unused,
3763 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764{
3765 return -ENOSYS;
3766}
3767
3768static size_t out_get_buffer_size(const struct audio_stream *stream)
3769{
3770 struct stream_out *out = (struct stream_out *)stream;
3771
Varun Balaraje49253e2017-07-06 19:48:56 +05303772 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303773 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303774 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303775 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3776 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3777 else
3778 return out->compr_config.fragment_size;
3779 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003780 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003781 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3782 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 +05303783 else if (is_offload_usecase(out->usecase) &&
3784 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303785 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003786
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003787 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003788 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789}
3790
3791static uint32_t out_get_channels(const struct audio_stream *stream)
3792{
3793 struct stream_out *out = (struct stream_out *)stream;
3794
3795 return out->channel_mask;
3796}
3797
3798static audio_format_t out_get_format(const struct audio_stream *stream)
3799{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 struct stream_out *out = (struct stream_out *)stream;
3801
3802 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803}
3804
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003805static int out_set_format(struct audio_stream *stream __unused,
3806 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807{
3808 return -ENOSYS;
3809}
3810
3811static int out_standby(struct audio_stream *stream)
3812{
3813 struct stream_out *out = (struct stream_out *)stream;
3814 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003815 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003816
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303817 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3818 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003820 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003822 if (adev->adm_deregister_stream)
3823 adev->adm_deregister_stream(adev->adm_data, out->handle);
3824
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003825 if (is_offload_usecase(out->usecase))
3826 stop_compressed_output_l(out);
3827
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003828 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003830 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3831 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303832 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003833 pthread_mutex_unlock(&adev->lock);
3834 pthread_mutex_unlock(&out->lock);
3835 ALOGD("VOIP output entered standby");
3836 return 0;
3837 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003838 if (out->pcm) {
3839 pcm_close(out->pcm);
3840 out->pcm = NULL;
3841 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003842 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3843 do_stop = out->playback_started;
3844 out->playback_started = false;
3845 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003846 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003847 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303848 out->send_next_track_params = false;
3849 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003850 out->gapless_mdata.encoder_delay = 0;
3851 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003852 if (out->compr != NULL) {
3853 compress_close(out->compr);
3854 out->compr = NULL;
3855 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003856 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003857 if (do_stop) {
3858 stop_output_stream(out);
3859 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003860 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 }
3862 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303863 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 return 0;
3865}
3866
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303867static int out_on_error(struct audio_stream *stream)
3868{
3869 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003870 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303871
3872 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003873 // always send CMD_ERROR for offload streams, this
3874 // is needed e.g. when SSR happens within compress_open
3875 // since the stream is active, offload_callback_thread is also active.
3876 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3877 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003878 }
3879 pthread_mutex_unlock(&out->lock);
3880
3881 status = out_standby(&out->stream.common);
3882
3883 lock_output_stream(out);
3884 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003885 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303886 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303887
3888 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3889 ALOGD("Setting previous card status if offline");
3890 out->prev_card_status_offline = true;
3891 }
3892
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303893 pthread_mutex_unlock(&out->lock);
3894
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003895 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303896}
3897
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303898/*
3899 *standby implementation without locks, assumes that the callee already
3900 *has taken adev and out lock.
3901 */
3902int out_standby_l(struct audio_stream *stream)
3903{
3904 struct stream_out *out = (struct stream_out *)stream;
3905 struct audio_device *adev = out->dev;
3906
3907 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3908 stream, out->usecase, use_case_table[out->usecase]);
3909
3910 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003911 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303912 if (adev->adm_deregister_stream)
3913 adev->adm_deregister_stream(adev->adm_data, out->handle);
3914
3915 if (is_offload_usecase(out->usecase))
3916 stop_compressed_output_l(out);
3917
3918 out->standby = true;
3919 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3920 voice_extn_compress_voip_close_output_stream(stream);
3921 out->started = 0;
3922 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003923 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303924 return 0;
3925 } else if (!is_offload_usecase(out->usecase)) {
3926 if (out->pcm) {
3927 pcm_close(out->pcm);
3928 out->pcm = NULL;
3929 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003930 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3931 if (adev->haptic_pcm) {
3932 pcm_close(adev->haptic_pcm);
3933 adev->haptic_pcm = NULL;
3934 }
3935
3936 if (adev->haptic_buffer != NULL) {
3937 free(adev->haptic_buffer);
3938 adev->haptic_buffer = NULL;
3939 adev->haptic_buffer_size = 0;
3940 }
3941 adev->haptic_pcm_device_id = 0;
3942 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303943 } else {
3944 ALOGD("copl(%p):standby", out);
3945 out->send_next_track_params = false;
3946 out->is_compr_metadata_avail = false;
3947 out->gapless_mdata.encoder_delay = 0;
3948 out->gapless_mdata.encoder_padding = 0;
3949 if (out->compr != NULL) {
3950 compress_close(out->compr);
3951 out->compr = NULL;
3952 }
3953 }
3954 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003955 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303956 }
3957 ALOGD("%s: exit", __func__);
3958 return 0;
3959}
3960
Aalique Grahame22e49102018-12-18 14:23:57 -08003961static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962{
Aalique Grahame22e49102018-12-18 14:23:57 -08003963 struct stream_out *out = (struct stream_out *)stream;
3964
3965 // We try to get the lock for consistency,
3966 // but it isn't necessary for these variables.
3967 // If we're not in standby, we may be blocked on a write.
3968 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
3969 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
3970 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
3971
3972 if (locked) {
3973 pthread_mutex_unlock(&out->lock);
3974 }
3975
3976 // dump error info
3977 (void)error_log_dump(
3978 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
3979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980 return 0;
3981}
3982
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003983static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3984{
3985 int ret = 0;
3986 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003987
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003988 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003989 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003990 return -EINVAL;
3991 }
3992
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303993 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003994
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003995 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3996 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303997 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003998 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003999 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4000 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304001 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004002 }
4003
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004004 ALOGV("%s new encoder delay %u and padding %u", __func__,
4005 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4006
4007 return 0;
4008}
4009
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004010static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4011{
4012 return out == adev->primary_output || out == adev->voice_tx_output;
4013}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004014
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304015// note: this call is safe only if the stream_cb is
4016// removed first in close_output_stream (as is done now).
4017static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4018{
4019 if (!stream || !parms)
4020 return;
4021
4022 struct stream_out *out = (struct stream_out *)stream;
4023 struct audio_device *adev = out->dev;
4024
4025 card_status_t status;
4026 int card;
4027 if (parse_snd_card_status(parms, &card, &status) < 0)
4028 return;
4029
4030 pthread_mutex_lock(&adev->lock);
4031 bool valid_cb = (card == adev->snd_card);
4032 pthread_mutex_unlock(&adev->lock);
4033
4034 if (!valid_cb)
4035 return;
4036
4037 lock_output_stream(out);
4038 if (out->card_status != status)
4039 out->card_status = status;
4040 pthread_mutex_unlock(&out->lock);
4041
4042 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4043 use_case_table[out->usecase],
4044 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4045
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304046 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304047 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304048 if (voice_is_call_state_active(adev) &&
4049 out == adev->primary_output) {
4050 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4051 pthread_mutex_lock(&adev->lock);
4052 voice_stop_call(adev);
4053 adev->mode = AUDIO_MODE_NORMAL;
4054 pthread_mutex_unlock(&adev->lock);
4055 }
4056 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304057 return;
4058}
4059
Kevin Rocardfce19002017-08-07 19:21:36 -07004060static int get_alive_usb_card(struct str_parms* parms) {
4061 int card;
4062 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4063 !audio_extn_usb_alive(card)) {
4064 return card;
4065 }
4066 return -ENODEV;
4067}
4068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4070{
4071 struct stream_out *out = (struct stream_out *)stream;
4072 struct audio_device *adev = out->dev;
4073 struct str_parms *parms;
4074 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004075 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304076 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004077 bool reconfig = false;
4078 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079
sangwoobc677242013-08-08 16:53:43 +09004080 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004081 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304083 if (!parms)
4084 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004085 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4086 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004088 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004089 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004091 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004092 * When HDMI cable is unplugged the music playback is paused and
4093 * the policy manager sends routing=0. But the audioflinger continues
4094 * to write data until standby time (3sec). As the HDMI core is
4095 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004096 * Avoid this by routing audio to speaker until standby.
4097 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004098 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4099 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304100 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004101 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4102 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004103 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304104 /*
4105 * When A2DP is disconnected the
4106 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004107 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304108 * (3sec). As BT is turned off, the write gets blocked.
4109 * Avoid this by routing audio to speaker until standby.
4110 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004111 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004112 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004113 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304114 val = AUDIO_DEVICE_OUT_SPEAKER;
4115 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304116 /*
4117 * When USB headset is disconnected the music platback paused
4118 * and the policy manager send routing=0. But if the USB is connected
4119 * back before the standby time, AFE is not closed and opened
4120 * when USB is connected back. So routing to speker will guarantee
4121 * AFE reconfiguration and AFE will be opend once USB is connected again
4122 */
4123 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4124 (val == AUDIO_DEVICE_NONE) &&
4125 !audio_extn_usb_connected(parms)) {
4126 val = AUDIO_DEVICE_OUT_SPEAKER;
4127 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304128 /* To avoid a2dp to sco overlapping / BT device improper state
4129 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304130 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304131 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004132 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004133 if (val &
4134 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304135 //combo usecase just by pass a2dp
4136 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304137 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304138 } else {
4139 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4140 /* update device to a2dp and don't route as BT returned error
4141 * However it is still possible a2dp routing called because
4142 * of current active device disconnection (like wired headset)
4143 */
4144 out->devices = val;
4145 pthread_mutex_unlock(&out->lock);
4146 pthread_mutex_unlock(&adev->lock);
4147 goto error;
4148 }
4149 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304150 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004151
4152 audio_devices_t new_dev = val;
4153
4154 // Workaround: If routing to an non existing usb device, fail gracefully
4155 // The routing request will otherwise block during 10 second
4156 int card;
4157 if (audio_is_usb_out_device(new_dev) &&
4158 (card = get_alive_usb_card(parms)) >= 0) {
4159
4160 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4161 pthread_mutex_unlock(&adev->lock);
4162 pthread_mutex_unlock(&out->lock);
4163 ret = -ENOSYS;
4164 goto routing_fail;
4165 }
4166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004167 /*
4168 * select_devices() call below switches all the usecases on the same
4169 * backend to the new device. Refer to check_usecases_codec_backend() in
4170 * the select_devices(). But how do we undo this?
4171 *
4172 * For example, music playback is active on headset (deep-buffer usecase)
4173 * and if we go to ringtones and select a ringtone, low-latency usecase
4174 * will be started on headset+speaker. As we can't enable headset+speaker
4175 * and headset devices at the same time, select_devices() switches the music
4176 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4177 * So when the ringtone playback is completed, how do we undo the same?
4178 *
4179 * We are relying on the out_set_parameters() call on deep-buffer output,
4180 * once the ringtone playback is ended.
4181 * NOTE: We should not check if the current devices are same as new devices.
4182 * Because select_devices() must be called to switch back the music
4183 * playback to headset.
4184 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004185 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004186 audio_devices_t new_dev = val;
4187 bool same_dev = out->devices == new_dev;
4188 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004189
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004190 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004191 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004192 if (adev->mode == AUDIO_MODE_IN_CALL) {
4193 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004194 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4195 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4196 audio_extn_usb_set_service_interval(true /*playback*/,
4197 service_interval,
4198 &reconfig);
4199 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4200 }
4201 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004202 }
4203 } else {
4204 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004205 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004206 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004207 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004208
4209 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004210 if (!same_dev) {
4211 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304212 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4213 adev->perf_lock_opts,
4214 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004215 if (adev->adm_on_routing_change)
4216 adev->adm_on_routing_change(adev->adm_data,
4217 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004218 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304219 if (!bypass_a2dp) {
4220 select_devices(adev, out->usecase);
4221 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004222 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4223 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4224 else
4225 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304226 select_devices(adev, out->usecase);
4227 out->devices = new_dev;
4228 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004229
4230 if (!same_dev) {
4231 // on device switch force swap, lower functions will make sure
4232 // to check if swap is allowed or not.
4233 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304234 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004235 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304236 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4237 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004238 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304239 pthread_mutex_lock(&out->compr_mute_lock);
4240 out->a2dp_compress_mute = false;
4241 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4242 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004243 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4244 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304245 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004246 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004247 }
4248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004250 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004251
4252 /*handles device and call state changes*/
4253 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004255 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004256
4257 if (out == adev->primary_output) {
4258 pthread_mutex_lock(&adev->lock);
4259 audio_extn_set_parameters(adev, parms);
4260 pthread_mutex_unlock(&adev->lock);
4261 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004262 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004263 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004264 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004265
4266 audio_extn_dts_create_state_notifier_node(out->usecase);
4267 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4268 popcount(out->channel_mask),
4269 out->playback_started);
4270
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004271 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004272 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004273
Surendar Karkaf51b5842018-04-26 11:28:38 +05304274 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4275 sizeof(value));
4276 if (err >= 0) {
4277 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4278 audio_extn_send_dual_mono_mixing_coefficients(out);
4279 }
4280
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304281 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4282 if (err >= 0) {
4283 strlcpy(out->profile, value, sizeof(out->profile));
4284 ALOGV("updating stream profile with value '%s'", out->profile);
4285 lock_output_stream(out);
4286 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4287 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004288 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304289 out->sample_rate, out->bit_width,
4290 out->channel_mask, out->profile,
4291 &out->app_type_cfg);
4292 pthread_mutex_unlock(&out->lock);
4293 }
4294
Alexy Joseph98988832017-01-13 14:56:59 -08004295 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004296 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4297 // and vendor.audio.hal.output.suspend.supported is set to true
4298 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004299 //check suspend parameter only for low latency and if the property
4300 //is enabled
4301 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4302 ALOGI("%s: got suspend_playback %s", __func__, value);
4303 lock_output_stream(out);
4304 if (!strncmp(value, "false", 5)) {
4305 //suspend_playback=false is supposed to set QOS value back to 75%
4306 //the mixer control sent with value Enable will achieve that
4307 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4308 } else if (!strncmp (value, "true", 4)) {
4309 //suspend_playback=true is supposed to remove QOS value
4310 //resetting the mixer control will set the default value
4311 //for the mixer control which is Disable and this removes the QOS vote
4312 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4313 } else {
4314 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4315 " got %s", __func__, value);
4316 ret = -1;
4317 }
4318
4319 if (ret != 0) {
4320 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4321 __func__, out->pm_qos_mixer_path, ret);
4322 }
4323
4324 pthread_mutex_unlock(&out->lock);
4325 }
4326 }
4327 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304329error:
Eric Laurent994a6932013-07-17 11:51:42 -07004330 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 return ret;
4332}
4333
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004334static bool stream_get_parameter_channels(struct str_parms *query,
4335 struct str_parms *reply,
4336 audio_channel_mask_t *supported_channel_masks) {
4337 int ret = -1;
4338 char value[512];
4339 bool first = true;
4340 size_t i, j;
4341
4342 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4343 ret = 0;
4344 value[0] = '\0';
4345 i = 0;
4346 while (supported_channel_masks[i] != 0) {
4347 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4348 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4349 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304350 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004351
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304352 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004353 first = false;
4354 break;
4355 }
4356 }
4357 i++;
4358 }
4359 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4360 }
4361 return ret == 0;
4362}
4363
4364static bool stream_get_parameter_formats(struct str_parms *query,
4365 struct str_parms *reply,
4366 audio_format_t *supported_formats) {
4367 int ret = -1;
4368 char value[256];
4369 size_t i, j;
4370 bool first = true;
4371
4372 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4373 ret = 0;
4374 value[0] = '\0';
4375 i = 0;
4376 while (supported_formats[i] != 0) {
4377 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4378 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4379 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304380 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004381 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304382 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004383 first = false;
4384 break;
4385 }
4386 }
4387 i++;
4388 }
4389 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4390 }
4391 return ret == 0;
4392}
4393
4394static bool stream_get_parameter_rates(struct str_parms *query,
4395 struct str_parms *reply,
4396 uint32_t *supported_sample_rates) {
4397
4398 int i;
4399 char value[256];
4400 int ret = -1;
4401 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4402 ret = 0;
4403 value[0] = '\0';
4404 i=0;
4405 int cursor = 0;
4406 while (supported_sample_rates[i]) {
4407 int avail = sizeof(value) - cursor;
4408 ret = snprintf(value + cursor, avail, "%s%d",
4409 cursor > 0 ? "|" : "",
4410 supported_sample_rates[i]);
4411 if (ret < 0 || ret >= avail) {
4412 // if cursor is at the last element of the array
4413 // overwrite with \0 is duplicate work as
4414 // snprintf already put a \0 in place.
4415 // else
4416 // we had space to write the '|' at value[cursor]
4417 // (which will be overwritten) or no space to fill
4418 // the first element (=> cursor == 0)
4419 value[cursor] = '\0';
4420 break;
4421 }
4422 cursor += ret;
4423 ++i;
4424 }
4425 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4426 value);
4427 }
4428 return ret >= 0;
4429}
4430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4432{
4433 struct stream_out *out = (struct stream_out *)stream;
4434 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004435 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436 char value[256];
4437 struct str_parms *reply = str_parms_create();
4438 size_t i, j;
4439 int ret;
4440 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004441
4442 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004443 if (reply) {
4444 str_parms_destroy(reply);
4445 }
4446 if (query) {
4447 str_parms_destroy(query);
4448 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004449 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4450 return NULL;
4451 }
4452
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004453 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4455 if (ret >= 0) {
4456 value[0] = '\0';
4457 i = 0;
4458 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004459 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4460 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004462 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004464 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 first = false;
4466 break;
4467 }
4468 }
4469 i++;
4470 }
4471 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4472 str = str_parms_to_str(reply);
4473 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004474 voice_extn_out_get_parameters(out, query, reply);
4475 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004477
Alexy Joseph62142aa2015-11-16 15:10:34 -08004478
4479 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4480 if (ret >= 0) {
4481 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304482 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4483 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004484 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304485 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004486 } else {
4487 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304488 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004489 }
4490 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004491 if (str)
4492 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004493 str = str_parms_to_str(reply);
4494 }
4495
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004496 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4497 if (ret >= 0) {
4498 value[0] = '\0';
4499 i = 0;
4500 first = true;
4501 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004502 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4503 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004504 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004505 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004506 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004507 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004508 first = false;
4509 break;
4510 }
4511 }
4512 i++;
4513 }
4514 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004515 if (str)
4516 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004517 str = str_parms_to_str(reply);
4518 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004519
4520 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4521 if (ret >= 0) {
4522 value[0] = '\0';
4523 i = 0;
4524 first = true;
4525 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004526 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4527 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004528 if (!first) {
4529 strlcat(value, "|", sizeof(value));
4530 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004531 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004532 first = false;
4533 break;
4534 }
4535 }
4536 i++;
4537 }
4538 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4539 if (str)
4540 free(str);
4541 str = str_parms_to_str(reply);
4542 }
4543
Alexy Joseph98988832017-01-13 14:56:59 -08004544 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4545 //only low latency track supports suspend_resume
4546 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004547 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004548 if (str)
4549 free(str);
4550 str = str_parms_to_str(reply);
4551 }
4552
4553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 str_parms_destroy(query);
4555 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004556 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 return str;
4558}
4559
4560static uint32_t out_get_latency(const struct audio_stream_out *stream)
4561{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004562 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004564 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565
Alexy Josephaa54c872014-12-03 02:46:47 -08004566 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304567 lock_output_stream(out);
4568 latency = audio_extn_utils_compress_get_dsp_latency(out);
4569 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004570 } else if ((out->realtime) ||
4571 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004572 // since the buffer won't be filled up faster than realtime,
4573 // return a smaller number
4574 if (out->config.rate)
4575 period_ms = (out->af_period_multiplier * out->config.period_size *
4576 1000) / (out->config.rate);
4577 else
4578 period_ms = 0;
4579 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004580 } else {
4581 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004582 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004583 }
4584
yidongh0515e042017-07-06 15:00:34 +08004585 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004586 latency += audio_extn_a2dp_get_encoder_latency();
4587
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304588 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004589 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590}
4591
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304592static float AmpToDb(float amplification)
4593{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304594 float db = DSD_VOLUME_MIN_DB;
4595 if (amplification > 0) {
4596 db = 20 * log10(amplification);
4597 if(db < DSD_VOLUME_MIN_DB)
4598 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304599 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304600 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304601}
4602
Arun Mirpuri5d170872019-03-26 13:21:31 -07004603static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4604 float right)
4605{
4606 struct stream_out *out = (struct stream_out *)stream;
4607 long volume = 0;
4608 char mixer_ctl_name[128] = "";
4609 struct audio_device *adev = out->dev;
4610 struct mixer_ctl *ctl = NULL;
4611 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4612 PCM_PLAYBACK);
4613
4614 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4615 "Playback %d Volume", pcm_device_id);
4616 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4617 if (!ctl) {
4618 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4619 __func__, mixer_ctl_name);
4620 return -EINVAL;
4621 }
4622 if (left != right)
4623 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4624 __func__, left, right);
4625 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4626 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4627 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4628 __func__, mixer_ctl_name, volume);
4629 return -EINVAL;
4630 }
4631 return 0;
4632}
4633
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304634static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4635 float right)
4636{
4637 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304638 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304639 char mixer_ctl_name[128];
4640 struct audio_device *adev = out->dev;
4641 struct mixer_ctl *ctl;
4642 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4643 PCM_PLAYBACK);
4644
4645 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4646 "Compress Playback %d Volume", pcm_device_id);
4647 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4648 if (!ctl) {
4649 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4650 __func__, mixer_ctl_name);
4651 return -EINVAL;
4652 }
4653 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4654 __func__, mixer_ctl_name, left, right);
4655 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4656 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4657 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4658
4659 return 0;
4660}
4661
Zhou Song2b8f28f2017-09-11 10:51:38 +08004662static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4663 float right)
4664{
4665 struct stream_out *out = (struct stream_out *)stream;
4666 char mixer_ctl_name[] = "App Type Gain";
4667 struct audio_device *adev = out->dev;
4668 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304669 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004670
4671 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4672 if (!ctl) {
4673 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4674 __func__, mixer_ctl_name);
4675 return -EINVAL;
4676 }
4677
4678 set_values[0] = 0; //0: Rx Session 1:Tx Session
4679 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304680 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4681 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004682
4683 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4684 return 0;
4685}
4686
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304687static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4688 float right)
4689{
4690 struct stream_out *out = (struct stream_out *)stream;
4691 /* Volume control for pcm playback */
4692 if (left != right) {
4693 return -EINVAL;
4694 } else {
4695 char mixer_ctl_name[128];
4696 struct audio_device *adev = out->dev;
4697 struct mixer_ctl *ctl;
4698 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4699 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4700 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4701 if (!ctl) {
4702 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4703 return -EINVAL;
4704 }
4705
4706 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4707 int ret = mixer_ctl_set_value(ctl, 0, volume);
4708 if (ret < 0) {
4709 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4710 return -EINVAL;
4711 }
4712
4713 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4714
4715 return 0;
4716 }
4717}
4718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719static int out_set_volume(struct audio_stream_out *stream, float left,
4720 float right)
4721{
Eric Laurenta9024de2013-04-04 09:19:12 -07004722 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004723 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304724 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004725
Arun Mirpuri5d170872019-03-26 13:21:31 -07004726 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004727 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4728 /* only take left channel into account: the API is for stereo anyway */
4729 out->muted = (left == 0.0f);
4730 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004731 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304732 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004733 /*
4734 * Set mute or umute on HDMI passthrough stream.
4735 * Only take left channel into account.
4736 * Mute is 0 and unmute 1
4737 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304738 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304739 } else if (out->format == AUDIO_FORMAT_DSD){
4740 char mixer_ctl_name[128] = "DSD Volume";
4741 struct audio_device *adev = out->dev;
4742 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4743
4744 if (!ctl) {
4745 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4746 __func__, mixer_ctl_name);
4747 return -EINVAL;
4748 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304749 volume[0] = (long)(AmpToDb(left));
4750 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304751 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4752 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004753 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304754 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004755 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304756 if (!out->a2dp_compress_mute)
4757 ret = out_set_compr_volume(stream, left, right);
4758 out->volume_l = left;
4759 out->volume_r = right;
4760 pthread_mutex_unlock(&out->compr_mute_lock);
4761 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004762 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004763 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004764 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4765 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4766 if (!out->standby) {
4767 audio_extn_utils_send_app_type_gain(out->dev,
4768 out->app_type_cfg.app_type,
4769 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004770 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004771 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004772 out->volume_l = left;
4773 out->volume_r = right;
4774 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004775 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4776 ALOGV("%s: MMAP set volume called", __func__);
4777 if (!out->standby)
4778 ret = out_set_mmap_volume(stream, left, right);
4779 out->volume_l = left;
4780 out->volume_r = right;
4781 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304782 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304783 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4784 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304785 /* Volume control for pcm playback */
4786 if (!out->standby)
4787 ret = out_set_pcm_volume(stream, left, right);
4788 else
4789 out->apply_volume = true;
4790
4791 out->volume_l = left;
4792 out->volume_r = right;
4793 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004794 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796 return -ENOSYS;
4797}
4798
Zhou Songc9672822017-08-16 16:01:39 +08004799static void update_frames_written(struct stream_out *out, size_t bytes)
4800{
4801 size_t bpf = 0;
4802
4803 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4804 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4805 bpf = 1;
4806 else if (!is_offload_usecase(out->usecase))
4807 bpf = audio_bytes_per_sample(out->format) *
4808 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004809
4810 pthread_mutex_lock(&out->position_query_lock);
4811 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004812 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004813 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4814 }
4815 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004816}
4817
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004818int split_and_write_audio_haptic_data(struct stream_out *out,
4819 const void *buffer, size_t bytes_to_write)
4820{
4821 struct audio_device *adev = out->dev;
4822
4823 int ret = 0;
4824 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4825 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4826 size_t frame_size = channel_count * bytes_per_sample;
4827 size_t frame_count = bytes_to_write / frame_size;
4828
4829 bool force_haptic_path =
4830 property_get_bool("vendor.audio.test_haptic", false);
4831
4832 // extract Haptics data from Audio buffer
4833 bool alloc_haptic_buffer = false;
4834 int haptic_channel_count = adev->haptics_config.channels;
4835 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4836 size_t audio_frame_size = frame_size - haptic_frame_size;
4837 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4838
4839 if (adev->haptic_buffer == NULL) {
4840 alloc_haptic_buffer = true;
4841 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4842 free(adev->haptic_buffer);
4843 adev->haptic_buffer_size = 0;
4844 alloc_haptic_buffer = true;
4845 }
4846
4847 if (alloc_haptic_buffer) {
4848 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4849 adev->haptic_buffer_size = total_haptic_buffer_size;
4850 }
4851
4852 size_t src_index = 0, aud_index = 0, hap_index = 0;
4853 uint8_t *audio_buffer = (uint8_t *)buffer;
4854 uint8_t *haptic_buffer = adev->haptic_buffer;
4855
4856 // This is required for testing only. This works for stereo data only.
4857 // One channel is fed to audio stream and other to haptic stream for testing.
4858 if (force_haptic_path)
4859 audio_frame_size = haptic_frame_size = bytes_per_sample;
4860
4861 for (size_t i = 0; i < frame_count; i++) {
4862 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4863 audio_frame_size);
4864 aud_index += audio_frame_size;
4865 src_index += audio_frame_size;
4866
4867 if (adev->haptic_pcm)
4868 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4869 haptic_frame_size);
4870 hap_index += haptic_frame_size;
4871 src_index += haptic_frame_size;
4872
4873 // This is required for testing only.
4874 // Discard haptic channel data.
4875 if (force_haptic_path)
4876 src_index += haptic_frame_size;
4877 }
4878
4879 // write to audio pipeline
4880 ret = pcm_write(out->pcm, (void *)audio_buffer,
4881 frame_count * audio_frame_size);
4882
4883 // write to haptics pipeline
4884 if (adev->haptic_pcm)
4885 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4886 frame_count * haptic_frame_size);
4887
4888 return ret;
4889}
4890
Aalique Grahame22e49102018-12-18 14:23:57 -08004891#ifdef NO_AUDIO_OUT
4892static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4893 const void *buffer __unused, size_t bytes)
4894{
4895 struct stream_out *out = (struct stream_out *)stream;
4896
4897 /* No Output device supported other than BT for playback.
4898 * Sleep for the amount of buffer duration
4899 */
4900 lock_output_stream(out);
4901 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4902 (const struct audio_stream_out *)&out->stream) /
4903 out_get_sample_rate(&out->stream.common));
4904 pthread_mutex_unlock(&out->lock);
4905 return bytes;
4906}
4907#endif
4908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4910 size_t bytes)
4911{
4912 struct stream_out *out = (struct stream_out *)stream;
4913 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004914 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304915 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004916 const size_t frame_size = audio_stream_out_frame_size(stream);
4917 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918
Haynes Mathew George380745d2017-10-04 15:27:45 -07004919 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004920 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304921
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304922 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004923
Dhananjay Kumarac341582017-02-23 23:42:25 +05304924 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304925 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304926 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4927 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004928 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304929 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304930 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304931 ALOGD(" %s: sound card is not active/SSR state", __func__);
4932 ret= -EIO;
4933 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304934 }
4935 }
4936
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304937 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304938 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304939 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304940 goto exit;
4941 }
4942
Haynes Mathew George16081042017-05-31 17:16:49 -07004943 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4944 ret = -EINVAL;
4945 goto exit;
4946 }
4947
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304948 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4949 !out->is_iec61937_info_available) {
4950
4951 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4952 out->is_iec61937_info_available = true;
4953 } else if (audio_extn_passthru_is_enabled()) {
4954 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304955 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304956
4957 if((out->format == AUDIO_FORMAT_DTS) ||
4958 (out->format == AUDIO_FORMAT_DTS_HD)) {
4959 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4960 buffer, bytes);
4961 if (ret) {
4962 if (ret != -ENOSYS) {
4963 out->is_iec61937_info_available = false;
4964 ALOGD("iec61937 transmission info not yet updated retry");
4965 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304966 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304967 /* if stream has started and after that there is
4968 * stream config change (iec transmission config)
4969 * then trigger select_device to update backend configuration.
4970 */
4971 out->stream_config_changed = true;
4972 pthread_mutex_lock(&adev->lock);
4973 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304974 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4975 ret = -EINVAL;
4976 goto exit;
4977 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304978 pthread_mutex_unlock(&adev->lock);
4979 out->stream_config_changed = false;
4980 out->is_iec61937_info_available = true;
4981 }
4982 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304983
Garmond Leung317cbf12017-09-13 16:20:50 -07004984 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304985 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4986 (out->is_iec61937_info_available == true)) {
4987 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4988 ret = -EINVAL;
4989 goto exit;
4990 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304991 }
4992 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304993
4994 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004995 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004996 if (!(out->devices &
4997 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304998 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304999 ret = -EIO;
5000 goto exit;
5001 }
5002 }
5003 }
5004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005006 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005007 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005008 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5009 ret = voice_extn_compress_voip_start_output_stream(out);
5010 else
5011 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005012 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005013 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005015 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016 goto exit;
5017 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305018 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005019 if (last_known_cal_step != -1) {
5020 ALOGD("%s: retry previous failed cal level set", __func__);
5021 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305022 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005023 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305024
5025 if ((out->is_iec61937_info_available == true) &&
5026 (audio_extn_passthru_is_passthrough_stream(out))&&
5027 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5028 ret = -EINVAL;
5029 goto exit;
5030 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305031 if (out->set_dual_mono)
5032 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034
Ashish Jain81eb2a82015-05-13 10:52:34 +05305035 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005036 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305037 adev->is_channel_status_set = true;
5038 }
5039
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005040 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005041 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005042 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005043 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005044 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5045 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305046 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5047 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005048 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305049 out->send_next_track_params = false;
5050 out->is_compr_metadata_avail = false;
5051 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005052 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305053 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305054 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005055
Ashish Jain83a6cc22016-06-28 14:34:17 +05305056 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305057 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305058 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305059 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005060 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305061 return -EINVAL;
5062 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305063 audio_format_t dst_format = out->hal_op_format;
5064 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305065
Dieter Luecking5d57def2018-09-07 14:23:37 +02005066 /* prevent division-by-zero */
5067 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5068 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5069 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5070 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305071 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005072 ATRACE_END();
5073 return -EINVAL;
5074 }
5075
Ashish Jainf1eaa582016-05-23 20:54:24 +05305076 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5077 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5078
Ashish Jain83a6cc22016-06-28 14:34:17 +05305079 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305080 dst_format,
5081 buffer,
5082 src_format,
5083 frames);
5084
Ashish Jain83a6cc22016-06-28 14:34:17 +05305085 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305086 bytes_to_write);
5087
5088 /*Convert written bytes in audio flinger format*/
5089 if (ret > 0)
5090 ret = ((ret * format_to_bitwidth_table[out->format]) /
5091 format_to_bitwidth_table[dst_format]);
5092 }
5093 } else
5094 ret = compress_write(out->compr, buffer, bytes);
5095
Zhou Songc9672822017-08-16 16:01:39 +08005096 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5097 update_frames_written(out, bytes);
5098
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305099 if (ret < 0)
5100 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005101 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305102 /*msg to cb thread only if non blocking write is enabled*/
5103 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305104 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005105 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305106 } else if (-ENETRESET == ret) {
5107 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305108 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305109 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305110 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005111 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305112 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005113 }
Ashish Jain5106d362016-05-11 19:23:33 +05305114
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305115 /* Call compr start only when non-zero bytes of data is there to be rendered */
5116 if (!out->playback_started && ret > 0) {
5117 int status = compress_start(out->compr);
5118 if (status < 0) {
5119 ret = status;
5120 ALOGE("%s: compr start failed with err %d", __func__, errno);
5121 goto exit;
5122 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005123 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005124 out->playback_started = 1;
5125 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005126
5127 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5128 popcount(out->channel_mask),
5129 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005130 }
5131 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005132 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005133 return ret;
5134 } else {
5135 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005136 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005137 if (out->muted)
5138 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005139 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5140 __func__, frames, frame_size, bytes_to_write);
5141
Aalique Grahame22e49102018-12-18 14:23:57 -08005142 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005143 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005144 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5145 int16_t *src = (int16_t *)buffer;
5146 int16_t *dst = (int16_t *)buffer;
5147
5148 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5149 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005150 "out_write called for %s use case with wrong properties",
5151 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005152
5153 /*
5154 * FIXME: this can be removed once audio flinger mixer supports
5155 * mono output
5156 */
5157
5158 /*
5159 * Code below goes over each frame in the buffer and adds both
5160 * L and R samples and then divides by 2 to convert to mono
5161 */
5162 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5163 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5164 }
5165 bytes_to_write /= 2;
5166 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005167
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305168 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005169
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005170 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005171
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005172 if (out->config.rate)
5173 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5174 out->config.rate;
5175
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005176 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005177 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5178
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005179 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005180 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005181 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305182 out->convert_buffer != NULL) {
5183
5184 memcpy_by_audio_format(out->convert_buffer,
5185 out->hal_op_format,
5186 buffer,
5187 out->hal_ip_format,
5188 out->config.period_size * out->config.channels);
5189
5190 ret = pcm_write(out->pcm, out->convert_buffer,
5191 (out->config.period_size *
5192 out->config.channels *
5193 format_to_bitwidth_table[out->hal_op_format]));
5194 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305195 /*
5196 * To avoid underrun in DSP when the application is not pumping
5197 * data at required rate, check for the no. of bytes and ignore
5198 * pcm_write if it is less than actual buffer size.
5199 * It is a work around to a change in compress VOIP driver.
5200 */
5201 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5202 bytes < (out->config.period_size * out->config.channels *
5203 audio_bytes_per_sample(out->format))) {
5204 size_t voip_buf_size =
5205 out->config.period_size * out->config.channels *
5206 audio_bytes_per_sample(out->format);
5207 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5208 __func__, bytes, voip_buf_size);
5209 usleep(((uint64_t)voip_buf_size - bytes) *
5210 1000000 / audio_stream_out_frame_size(stream) /
5211 out_get_sample_rate(&out->stream.common));
5212 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005213 } else {
5214 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5215 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5216 else
5217 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5218 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305219 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005220
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005221 release_out_focus(out);
5222
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305223 if (ret < 0)
5224 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005225 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305226 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 }
5229
5230exit:
Zhou Songc9672822017-08-16 16:01:39 +08005231 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305232 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305233 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005235 pthread_mutex_unlock(&out->lock);
5236
5237 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005238 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005239 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305240 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305241 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305242 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305243 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305244 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305245 out->standby = true;
5246 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305247 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005248 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5249 /* prevent division-by-zero */
5250 uint32_t stream_size = audio_stream_out_frame_size(stream);
5251 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005252
Dieter Luecking5d57def2018-09-07 14:23:37 +02005253 if ((stream_size == 0) || (srate == 0)) {
5254 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5255 ATRACE_END();
5256 return -EINVAL;
5257 }
5258 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5259 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005260 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305261 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005262 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005263 return ret;
5264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005266 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267 return bytes;
5268}
5269
5270static int out_get_render_position(const struct audio_stream_out *stream,
5271 uint32_t *dsp_frames)
5272{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005273 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005274
5275 if (dsp_frames == NULL)
5276 return -EINVAL;
5277
5278 *dsp_frames = 0;
5279 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005280 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305281
5282 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5283 * this operation and adev_close_output_stream(where out gets reset).
5284 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305285 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005286 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305287 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005288 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305289 return 0;
5290 }
5291
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005292 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305293 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305294 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005295 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305296 if (ret < 0)
5297 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005298 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305299 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005300 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305301 if (-ENETRESET == ret) {
5302 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305303 out->card_status = CARD_STATUS_OFFLINE;
5304 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305305 } else if(ret < 0) {
5306 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305307 ret = -EINVAL;
5308 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305309 /*
5310 * Handle corner case where compress session is closed during SSR
5311 * and timestamp is queried
5312 */
5313 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305314 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305315 } else if (out->prev_card_status_offline) {
5316 ALOGE("ERROR: previously sound card was offline,return error");
5317 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305318 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305319 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005320 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305321 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305322 pthread_mutex_unlock(&out->lock);
5323 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005324 } else if (audio_is_linear_pcm(out->format)) {
5325 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005326 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005327 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005328 } else
5329 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005330}
5331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005332static int out_add_audio_effect(const struct audio_stream *stream __unused,
5333 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334{
5335 return 0;
5336}
5337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005338static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5339 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340{
5341 return 0;
5342}
5343
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005344static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5345 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305347 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005348}
5349
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005350static int out_get_presentation_position(const struct audio_stream_out *stream,
5351 uint64_t *frames, struct timespec *timestamp)
5352{
5353 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305354 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005355 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005356
Ashish Jain5106d362016-05-11 19:23:33 +05305357 /* below piece of code is not guarded against any lock because audioFliner serializes
5358 * this operation and adev_close_output_stream( where out gets reset).
5359 */
5360 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305361 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005362 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305363 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5364 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5365 return 0;
5366 }
5367
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005368 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005369
Ashish Jain5106d362016-05-11 19:23:33 +05305370 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5371 ret = compress_get_tstamp(out->compr, &dsp_frames,
5372 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005373 // Adjustment accounts for A2dp encoder latency with offload usecases
5374 // Note: Encoder latency is returned in ms.
5375 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5376 unsigned long offset =
5377 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5378 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5379 }
Ashish Jain5106d362016-05-11 19:23:33 +05305380 ALOGVV("%s rendered frames %ld sample_rate %d",
5381 __func__, dsp_frames, out->sample_rate);
5382 *frames = dsp_frames;
5383 if (ret < 0)
5384 ret = -errno;
5385 if (-ENETRESET == ret) {
5386 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305387 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305388 ret = -EINVAL;
5389 } else
5390 ret = 0;
5391 /* this is the best we can do */
5392 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005393 } else {
5394 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005395 unsigned int avail;
5396 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5397 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5398 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5399 // This adjustment accounts for buffering after app processor.
5400 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005401 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005402 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005403
Weiyin Jiangd4633762018-03-16 12:05:03 +08005404 // Adjustment accounts for A2dp encoder latency with non offload usecases
5405 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5406 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5407 signed_frames -=
5408 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5409 }
5410
5411 // It would be unusual for this value to be negative, but check just in case ...
5412 if (signed_frames >= 0) {
5413 *frames = signed_frames;
5414 ret = 0;
5415 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005416 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305417 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305418 *frames = out->written;
5419 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305420 if (is_offload_usecase(out->usecase))
5421 ret = -EINVAL;
5422 else
5423 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005424 }
5425 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005426 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005427 return ret;
5428}
5429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005430static int out_set_callback(struct audio_stream_out *stream,
5431 stream_callback_t callback, void *cookie)
5432{
5433 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005434 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005435
5436 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005437 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005438 out->client_callback = callback;
5439 out->client_cookie = cookie;
5440 if (out->adsp_hdlr_stream_handle) {
5441 ret = audio_extn_adsp_hdlr_stream_set_callback(
5442 out->adsp_hdlr_stream_handle,
5443 callback,
5444 cookie);
5445 if (ret)
5446 ALOGW("%s:adsp hdlr callback registration failed %d",
5447 __func__, ret);
5448 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005449 pthread_mutex_unlock(&out->lock);
5450 return 0;
5451}
5452
5453static int out_pause(struct audio_stream_out* stream)
5454{
5455 struct stream_out *out = (struct stream_out *)stream;
5456 int status = -ENOSYS;
5457 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005458 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005459 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005461 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305462 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305463 status = compress_pause(out->compr);
5464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005465 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005466
Mingming Yin21854652016-04-13 11:54:02 -07005467 if (audio_extn_passthru_is_active()) {
5468 ALOGV("offload use case, pause passthru");
5469 audio_extn_passthru_on_pause(out);
5470 }
5471
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305472 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005473 audio_extn_dts_notify_playback_state(out->usecase, 0,
5474 out->sample_rate, popcount(out->channel_mask),
5475 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005476 }
5477 pthread_mutex_unlock(&out->lock);
5478 }
5479 return status;
5480}
5481
5482static int out_resume(struct audio_stream_out* stream)
5483{
5484 struct stream_out *out = (struct stream_out *)stream;
5485 int status = -ENOSYS;
5486 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005487 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005488 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005489 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005490 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005491 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305492 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305493 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005494 }
5495 if (!status) {
5496 out->offload_state = OFFLOAD_STATE_PLAYING;
5497 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305498 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005499 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5500 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005501 }
5502 pthread_mutex_unlock(&out->lock);
5503 }
5504 return status;
5505}
5506
5507static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5508{
5509 struct stream_out *out = (struct stream_out *)stream;
5510 int status = -ENOSYS;
5511 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005512 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005513 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005514 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5515 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5516 else
5517 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5518 pthread_mutex_unlock(&out->lock);
5519 }
5520 return status;
5521}
5522
5523static int out_flush(struct audio_stream_out* stream)
5524{
5525 struct stream_out *out = (struct stream_out *)stream;
5526 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005527 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005528 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005529 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005530 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5531 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005532 } else {
5533 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5534 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005535 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005536 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005537 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005538 return 0;
5539 }
5540 return -ENOSYS;
5541}
5542
Haynes Mathew George16081042017-05-31 17:16:49 -07005543static int out_stop(const struct audio_stream_out* stream)
5544{
5545 struct stream_out *out = (struct stream_out *)stream;
5546 struct audio_device *adev = out->dev;
5547 int ret = -ENOSYS;
5548
5549 ALOGV("%s", __func__);
5550 pthread_mutex_lock(&adev->lock);
5551 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5552 out->playback_started && out->pcm != NULL) {
5553 pcm_stop(out->pcm);
5554 ret = stop_output_stream(out);
5555 out->playback_started = false;
5556 }
5557 pthread_mutex_unlock(&adev->lock);
5558 return ret;
5559}
5560
5561static int out_start(const struct audio_stream_out* stream)
5562{
5563 struct stream_out *out = (struct stream_out *)stream;
5564 struct audio_device *adev = out->dev;
5565 int ret = -ENOSYS;
5566
5567 ALOGV("%s", __func__);
5568 pthread_mutex_lock(&adev->lock);
5569 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5570 !out->playback_started && out->pcm != NULL) {
5571 ret = start_output_stream(out);
5572 if (ret == 0) {
5573 out->playback_started = true;
5574 }
5575 }
5576 pthread_mutex_unlock(&adev->lock);
5577 return ret;
5578}
5579
5580/*
5581 * Modify config->period_count based on min_size_frames
5582 */
5583static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5584{
5585 int periodCountRequested = (min_size_frames + config->period_size - 1)
5586 / config->period_size;
5587 int periodCount = MMAP_PERIOD_COUNT_MIN;
5588
5589 ALOGV("%s original config.period_size = %d config.period_count = %d",
5590 __func__, config->period_size, config->period_count);
5591
5592 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5593 periodCount *= 2;
5594 }
5595 config->period_count = periodCount;
5596
5597 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5598}
5599
5600static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5601 int32_t min_size_frames,
5602 struct audio_mmap_buffer_info *info)
5603{
5604 struct stream_out *out = (struct stream_out *)stream;
5605 struct audio_device *adev = out->dev;
5606 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005607 unsigned int offset1 = 0;
5608 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005609 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005610 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005611 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005612
Arun Mirpuri5d170872019-03-26 13:21:31 -07005613 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305614 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005615 pthread_mutex_lock(&adev->lock);
5616
Sharad Sanglec6f32552018-05-04 16:15:38 +05305617 if (CARD_STATUS_OFFLINE == out->card_status ||
5618 CARD_STATUS_OFFLINE == adev->card_status) {
5619 ALOGW("out->card_status or adev->card_status offline, try again");
5620 ret = -EIO;
5621 goto exit;
5622 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005623 if (info == NULL || min_size_frames == 0) {
5624 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5625 ret = -EINVAL;
5626 goto exit;
5627 }
5628 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5629 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5630 ret = -ENOSYS;
5631 goto exit;
5632 }
5633 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5634 if (out->pcm_device_id < 0) {
5635 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5636 __func__, out->pcm_device_id, out->usecase);
5637 ret = -EINVAL;
5638 goto exit;
5639 }
5640
5641 adjust_mmap_period_count(&out->config, min_size_frames);
5642
Arun Mirpuri5d170872019-03-26 13:21:31 -07005643 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005644 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5645 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5646 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305647 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305648 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5649 out->card_status = CARD_STATUS_OFFLINE;
5650 adev->card_status = CARD_STATUS_OFFLINE;
5651 ret = -EIO;
5652 goto exit;
5653 }
5654
Haynes Mathew George16081042017-05-31 17:16:49 -07005655 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5656 step = "open";
5657 ret = -ENODEV;
5658 goto exit;
5659 }
5660 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5661 if (ret < 0) {
5662 step = "begin";
5663 goto exit;
5664 }
5665 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005666 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005667 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005668 ret = platform_get_mmap_data_fd(adev->platform,
5669 out->pcm_device_id, 0 /*playback*/,
5670 &info->shared_memory_fd,
5671 &mmap_size);
5672 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005673 // Fall back to non exclusive mode
5674 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5675 } else {
5676 if (mmap_size < buffer_size) {
5677 step = "mmap";
5678 goto exit;
5679 }
5680 // FIXME: indicate exclusive mode support by returning a negative buffer size
5681 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005682 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005683 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005684 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005685
5686 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5687 if (ret < 0) {
5688 step = "commit";
5689 goto exit;
5690 }
5691
5692 out->standby = false;
5693 ret = 0;
5694
Arun Mirpuri5d170872019-03-26 13:21:31 -07005695 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005696 __func__, info->shared_memory_address, info->buffer_size_frames);
5697
5698exit:
5699 if (ret != 0) {
5700 if (out->pcm == NULL) {
5701 ALOGE("%s: %s - %d", __func__, step, ret);
5702 } else {
5703 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5704 pcm_close(out->pcm);
5705 out->pcm = NULL;
5706 }
5707 }
5708 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305709 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005710 return ret;
5711}
5712
5713static int out_get_mmap_position(const struct audio_stream_out *stream,
5714 struct audio_mmap_position *position)
5715{
5716 struct stream_out *out = (struct stream_out *)stream;
5717 ALOGVV("%s", __func__);
5718 if (position == NULL) {
5719 return -EINVAL;
5720 }
5721 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005722 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005723 return -ENOSYS;
5724 }
5725 if (out->pcm == NULL) {
5726 return -ENOSYS;
5727 }
5728
5729 struct timespec ts = { 0, 0 };
5730 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5731 if (ret < 0) {
5732 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5733 return ret;
5734 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005735 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005736 return 0;
5737}
5738
5739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005740/** audio_stream_in implementation **/
5741static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5742{
5743 struct stream_in *in = (struct stream_in *)stream;
5744
5745 return in->config.rate;
5746}
5747
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005748static int in_set_sample_rate(struct audio_stream *stream __unused,
5749 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750{
5751 return -ENOSYS;
5752}
5753
5754static size_t in_get_buffer_size(const struct audio_stream *stream)
5755{
5756 struct stream_in *in = (struct stream_in *)stream;
5757
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005758 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5759 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005760 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5761 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 -07005762 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5763 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305764 else if(audio_extn_cin_attached_usecase(in->usecase))
5765 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005766
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005767 return in->config.period_size * in->af_period_multiplier *
5768 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005769}
5770
5771static uint32_t in_get_channels(const struct audio_stream *stream)
5772{
5773 struct stream_in *in = (struct stream_in *)stream;
5774
5775 return in->channel_mask;
5776}
5777
5778static audio_format_t in_get_format(const struct audio_stream *stream)
5779{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005780 struct stream_in *in = (struct stream_in *)stream;
5781
5782 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005783}
5784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005785static int in_set_format(struct audio_stream *stream __unused,
5786 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005787{
5788 return -ENOSYS;
5789}
5790
5791static int in_standby(struct audio_stream *stream)
5792{
5793 struct stream_in *in = (struct stream_in *)stream;
5794 struct audio_device *adev = in->dev;
5795 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305796 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5797 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005798 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305799
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005800 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005801 if (!in->standby && in->is_st_session) {
5802 ALOGD("%s: sound trigger pcm stop lab", __func__);
5803 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005804 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005805 in->standby = 1;
5806 }
5807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005808 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005809 if (adev->adm_deregister_stream)
5810 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5811
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005812 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005813 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005814 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005815 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005816 voice_extn_compress_voip_close_input_stream(stream);
5817 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005818 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5819 do_stop = in->capture_started;
5820 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005821 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305822 if (audio_extn_cin_attached_usecase(in->usecase))
5823 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005824 }
5825
Arun Mirpuri5d170872019-03-26 13:21:31 -07005826 if (in->pcm) {
5827 ATRACE_BEGIN("pcm_in_close");
5828 pcm_close(in->pcm);
5829 ATRACE_END();
5830 in->pcm = NULL;
5831 }
5832
5833 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005834 adev->enable_voicerx = false;
5835 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005836 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005837 }
Quinn Malef6050362019-01-30 15:55:40 -08005838
5839 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5840 adev->num_va_sessions--;
5841
Eric Laurent150dbfe2013-02-27 14:31:02 -08005842 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005843 }
5844 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005845 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 return status;
5847}
5848
Aalique Grahame22e49102018-12-18 14:23:57 -08005849static int in_dump(const struct audio_stream *stream,
5850 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851{
Aalique Grahame22e49102018-12-18 14:23:57 -08005852 struct stream_in *in = (struct stream_in *)stream;
5853
5854 // We try to get the lock for consistency,
5855 // but it isn't necessary for these variables.
5856 // If we're not in standby, we may be blocked on a read.
5857 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5858 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5859 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5860 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5861
5862 if (locked) {
5863 pthread_mutex_unlock(&in->lock);
5864 }
5865
5866 // dump error info
5867 (void)error_log_dump(
5868 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005870 return 0;
5871}
5872
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305873static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5874{
5875 if (!stream || !parms)
5876 return;
5877
5878 struct stream_in *in = (struct stream_in *)stream;
5879 struct audio_device *adev = in->dev;
5880
5881 card_status_t status;
5882 int card;
5883 if (parse_snd_card_status(parms, &card, &status) < 0)
5884 return;
5885
5886 pthread_mutex_lock(&adev->lock);
5887 bool valid_cb = (card == adev->snd_card);
5888 pthread_mutex_unlock(&adev->lock);
5889
5890 if (!valid_cb)
5891 return;
5892
5893 lock_input_stream(in);
5894 if (in->card_status != status)
5895 in->card_status = status;
5896 pthread_mutex_unlock(&in->lock);
5897
5898 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5899 use_case_table[in->usecase],
5900 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5901
5902 // a better solution would be to report error back to AF and let
5903 // it put the stream to standby
5904 if (status == CARD_STATUS_OFFLINE)
5905 in_standby(&in->stream.common);
5906
5907 return;
5908}
5909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005910static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5911{
5912 struct stream_in *in = (struct stream_in *)stream;
5913 struct audio_device *adev = in->dev;
5914 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005915 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005916 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005917
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305918 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005919 parms = str_parms_create_str(kvpairs);
5920
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305921 if (!parms)
5922 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005923 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005924 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005925
5926 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5927 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005928 val = atoi(value);
5929 /* no audio source uses val == 0 */
5930 if ((in->source != val) && (val != 0)) {
5931 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005932 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5933 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5934 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005935 (in->config.rate == 8000 || in->config.rate == 16000 ||
5936 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005937 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005938 err = voice_extn_compress_voip_open_input_stream(in);
5939 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005940 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005941 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005942 }
5943 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005944 }
5945 }
5946
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005947 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5948 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005949 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005950 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5951
5952 // Workaround: If routing to an non existing usb device, fail gracefully
5953 // The routing request will otherwise block during 10 second
5954 int card;
5955 if (audio_is_usb_in_device(val) &&
5956 (card = get_alive_usb_card(parms)) >= 0) {
5957
5958 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5959 ret = -ENOSYS;
5960 } else {
5961
5962 in->device = val;
5963 /* If recording is in progress, change the tx device to new device */
5964 if (!in->standby && !in->is_st_session) {
5965 ALOGV("update input routing change");
5966 // inform adm before actual routing to prevent glitches.
5967 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005968 adev->adm_on_routing_change(adev->adm_data,
5969 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005970 ret = select_devices(adev, in->usecase);
5971 }
5972 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005973 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005974 }
5975 }
5976
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305977 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5978 if (err >= 0) {
5979 strlcpy(in->profile, value, sizeof(in->profile));
5980 ALOGV("updating stream profile with value '%s'", in->profile);
5981 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5982 &adev->streams_input_cfg_list,
5983 in->device, in->flags, in->format,
5984 in->sample_rate, in->bit_width,
5985 in->profile, &in->app_type_cfg);
5986 }
5987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005988 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005989 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005990
5991 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305992error:
Eric Laurent994a6932013-07-17 11:51:42 -07005993 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005994 return ret;
5995}
5996
5997static char* in_get_parameters(const struct audio_stream *stream,
5998 const char *keys)
5999{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006000 struct stream_in *in = (struct stream_in *)stream;
6001 struct str_parms *query = str_parms_create_str(keys);
6002 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006003 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006004
6005 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006006 if (reply) {
6007 str_parms_destroy(reply);
6008 }
6009 if (query) {
6010 str_parms_destroy(query);
6011 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006012 ALOGE("in_get_parameters: failed to create query or reply");
6013 return NULL;
6014 }
6015
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006016 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006017
6018 voice_extn_in_get_parameters(in, query, reply);
6019
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006020 stream_get_parameter_channels(query, reply,
6021 &in->supported_channel_masks[0]);
6022 stream_get_parameter_formats(query, reply,
6023 &in->supported_formats[0]);
6024 stream_get_parameter_rates(query, reply,
6025 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006026 str = str_parms_to_str(reply);
6027 str_parms_destroy(query);
6028 str_parms_destroy(reply);
6029
6030 ALOGV("%s: exit: returns - %s", __func__, str);
6031 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006032}
6033
Aalique Grahame22e49102018-12-18 14:23:57 -08006034static int in_set_gain(struct audio_stream_in *stream,
6035 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006036{
Aalique Grahame22e49102018-12-18 14:23:57 -08006037 struct stream_in *in = (struct stream_in *)stream;
6038 char mixer_ctl_name[128];
6039 struct mixer_ctl *ctl;
6040 int ctl_value;
6041
6042 ALOGV("%s: gain %f", __func__, gain);
6043
6044 if (stream == NULL)
6045 return -EINVAL;
6046
6047 /* in_set_gain() only used to silence MMAP capture for now */
6048 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6049 return -ENOSYS;
6050
6051 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6052
6053 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6054 if (!ctl) {
6055 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6056 __func__, mixer_ctl_name);
6057 return -ENOSYS;
6058 }
6059
6060 if (gain < RECORD_GAIN_MIN)
6061 gain = RECORD_GAIN_MIN;
6062 else if (gain > RECORD_GAIN_MAX)
6063 gain = RECORD_GAIN_MAX;
6064 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6065
6066 mixer_ctl_set_value(ctl, 0, ctl_value);
6067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006068 return 0;
6069}
6070
6071static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6072 size_t bytes)
6073{
6074 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306075
6076 if (in == NULL) {
6077 ALOGE("%s: stream_in ptr is NULL", __func__);
6078 return -EINVAL;
6079 }
6080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006081 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306082 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306083 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006084
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006085 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306086
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006087 if (in->is_st_session) {
6088 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6089 /* Read from sound trigger HAL */
6090 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006091 if (in->standby) {
6092 adev->num_va_sessions++;
6093 in->standby = 0;
6094 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006095 pthread_mutex_unlock(&in->lock);
6096 return bytes;
6097 }
6098
Haynes Mathew George16081042017-05-31 17:16:49 -07006099 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6100 ret = -ENOSYS;
6101 goto exit;
6102 }
6103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006104 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006105 pthread_mutex_lock(&adev->lock);
6106 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6107 ret = voice_extn_compress_voip_start_input_stream(in);
6108 else
6109 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006110 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6111 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006112 pthread_mutex_unlock(&adev->lock);
6113 if (ret != 0) {
6114 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006115 }
6116 in->standby = 0;
6117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006118
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006119 // what's the duration requested by the client?
6120 long ns = 0;
6121
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306122 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006123 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6124 in->config.rate;
6125
6126 request_in_focus(in, ns);
6127 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006128
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306129 if (audio_extn_cin_attached_usecase(in->usecase)) {
6130 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6131 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306132 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006133 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306134 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006135 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006136 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006137 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006138 } else if (audio_extn_ffv_get_stream() == in) {
6139 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306140 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006141 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306142 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6143 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6144 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6145 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306146 ret = -EINVAL;
6147 goto exit;
6148 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306149 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306150 ret = -errno;
6151 }
6152 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306153 /* bytes read is always set to bytes for non compress usecases */
6154 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155 }
6156
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006157 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006159 /*
Quinn Malef6050362019-01-30 15:55:40 -08006160 * Instead of writing zeroes here, we could trust the hardware to always
6161 * provide zeroes when muted. This is also muted with voice recognition
6162 * usecases so that other clients do not have access to voice recognition
6163 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006164 */
Quinn Malef6050362019-01-30 15:55:40 -08006165 if ((ret == 0 && voice_get_mic_mute(adev) &&
6166 !voice_is_in_call_rec_stream(in) &&
6167 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6168 (adev->num_va_sessions &&
6169 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6170 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6171 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006172 memset(buffer, 0, bytes);
6173
6174exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006175 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306176 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006177 pthread_mutex_unlock(&in->lock);
6178
6179 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306180 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306181 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306182 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306183 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306184 in->standby = true;
6185 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306186 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6187 bytes_read = bytes;
6188 memset(buffer, 0, bytes);
6189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006190 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006191 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306192 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306193 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006194 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306195 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006196}
6197
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006198static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006199{
6200 return 0;
6201}
6202
Aalique Grahame22e49102018-12-18 14:23:57 -08006203static int in_get_capture_position(const struct audio_stream_in *stream,
6204 int64_t *frames, int64_t *time)
6205{
6206 if (stream == NULL || frames == NULL || time == NULL) {
6207 return -EINVAL;
6208 }
6209 struct stream_in *in = (struct stream_in *)stream;
6210 int ret = -ENOSYS;
6211
6212 lock_input_stream(in);
6213 // note: ST sessions do not close the alsa pcm driver synchronously
6214 // on standby. Therefore, we may return an error even though the
6215 // pcm stream is still opened.
6216 if (in->standby) {
6217 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6218 "%s stream in standby but pcm not NULL for non ST session", __func__);
6219 goto exit;
6220 }
6221 if (in->pcm) {
6222 struct timespec timestamp;
6223 unsigned int avail;
6224 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6225 *frames = in->frames_read + avail;
6226 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6227 ret = 0;
6228 }
6229 }
6230exit:
6231 pthread_mutex_unlock(&in->lock);
6232 return ret;
6233}
6234
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006235static int add_remove_audio_effect(const struct audio_stream *stream,
6236 effect_handle_t effect,
6237 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006238{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006239 struct stream_in *in = (struct stream_in *)stream;
6240 int status = 0;
6241 effect_descriptor_t desc;
6242
6243 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006244 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6245
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006246 if (status != 0)
6247 return status;
6248
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006249 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006250 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006251 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006252 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006253 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006254 in->enable_aec != enable &&
6255 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6256 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006257 if (!enable)
6258 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6259 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6260 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6261 in->dev->enable_voicerx = enable;
6262 struct audio_usecase *usecase;
6263 struct listnode *node;
6264 list_for_each(node, &in->dev->usecase_list) {
6265 usecase = node_to_item(node, struct audio_usecase, list);
6266 if (usecase->type == PCM_PLAYBACK)
6267 select_devices(in->dev, usecase->id);
6268 }
6269 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006270 if (!in->standby) {
6271 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6272 select_devices(in->dev, in->usecase);
6273 }
6274
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006275 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006276 if (in->enable_ns != enable &&
6277 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6278 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006279 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006280 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6281 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006282 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6283 select_devices(in->dev, in->usecase);
6284 } else
6285 select_devices(in->dev, in->usecase);
6286 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006287 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006288 pthread_mutex_unlock(&in->dev->lock);
6289 pthread_mutex_unlock(&in->lock);
6290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006291 return 0;
6292}
6293
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006294static int in_add_audio_effect(const struct audio_stream *stream,
6295 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006296{
Eric Laurent994a6932013-07-17 11:51:42 -07006297 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006298 return add_remove_audio_effect(stream, effect, true);
6299}
6300
6301static int in_remove_audio_effect(const struct audio_stream *stream,
6302 effect_handle_t effect)
6303{
Eric Laurent994a6932013-07-17 11:51:42 -07006304 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006305 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006306}
6307
Derek Chenf939fb72018-11-13 13:34:41 -08006308streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6309 audio_io_handle_t input)
6310{
6311 struct listnode *node;
6312
6313 list_for_each(node, &dev->active_inputs_list) {
6314 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6315 streams_input_ctxt_t,
6316 list);
6317 if (in_ctxt->input->capture_handle == input) {
6318 return in_ctxt;
6319 }
6320 }
6321 return NULL;
6322}
6323
6324streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6325 audio_io_handle_t output)
6326{
6327 struct listnode *node;
6328
6329 list_for_each(node, &dev->active_outputs_list) {
6330 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6331 streams_output_ctxt_t,
6332 list);
6333 if (out_ctxt->output->handle == output) {
6334 return out_ctxt;
6335 }
6336 }
6337 return NULL;
6338}
6339
Haynes Mathew George16081042017-05-31 17:16:49 -07006340static int in_stop(const struct audio_stream_in* stream)
6341{
6342 struct stream_in *in = (struct stream_in *)stream;
6343 struct audio_device *adev = in->dev;
6344
6345 int ret = -ENOSYS;
6346 ALOGV("%s", __func__);
6347 pthread_mutex_lock(&adev->lock);
6348 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6349 in->capture_started && in->pcm != NULL) {
6350 pcm_stop(in->pcm);
6351 ret = stop_input_stream(in);
6352 in->capture_started = false;
6353 }
6354 pthread_mutex_unlock(&adev->lock);
6355 return ret;
6356}
6357
6358static int in_start(const struct audio_stream_in* stream)
6359{
6360 struct stream_in *in = (struct stream_in *)stream;
6361 struct audio_device *adev = in->dev;
6362 int ret = -ENOSYS;
6363
6364 ALOGV("%s in %p", __func__, in);
6365 pthread_mutex_lock(&adev->lock);
6366 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6367 !in->capture_started && in->pcm != NULL) {
6368 if (!in->capture_started) {
6369 ret = start_input_stream(in);
6370 if (ret == 0) {
6371 in->capture_started = true;
6372 }
6373 }
6374 }
6375 pthread_mutex_unlock(&adev->lock);
6376 return ret;
6377}
6378
6379static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6380 int32_t min_size_frames,
6381 struct audio_mmap_buffer_info *info)
6382{
6383 struct stream_in *in = (struct stream_in *)stream;
6384 struct audio_device *adev = in->dev;
6385 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006386 unsigned int offset1 = 0;
6387 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006388 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006389 uint32_t mmap_size = 0;
6390 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006391
6392 pthread_mutex_lock(&adev->lock);
6393 ALOGV("%s in %p", __func__, in);
6394
Sharad Sanglec6f32552018-05-04 16:15:38 +05306395 if (CARD_STATUS_OFFLINE == in->card_status||
6396 CARD_STATUS_OFFLINE == adev->card_status) {
6397 ALOGW("in->card_status or adev->card_status offline, try again");
6398 ret = -EIO;
6399 goto exit;
6400 }
6401
Haynes Mathew George16081042017-05-31 17:16:49 -07006402 if (info == NULL || min_size_frames == 0) {
6403 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6404 ret = -EINVAL;
6405 goto exit;
6406 }
6407 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6408 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6409 ALOGV("%s in %p", __func__, in);
6410 ret = -ENOSYS;
6411 goto exit;
6412 }
6413 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6414 if (in->pcm_device_id < 0) {
6415 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6416 __func__, in->pcm_device_id, in->usecase);
6417 ret = -EINVAL;
6418 goto exit;
6419 }
6420
6421 adjust_mmap_period_count(&in->config, min_size_frames);
6422
6423 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6424 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6425 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6426 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306427 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306428 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6429 in->card_status = CARD_STATUS_OFFLINE;
6430 adev->card_status = CARD_STATUS_OFFLINE;
6431 ret = -EIO;
6432 goto exit;
6433 }
6434
Haynes Mathew George16081042017-05-31 17:16:49 -07006435 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6436 step = "open";
6437 ret = -ENODEV;
6438 goto exit;
6439 }
6440
6441 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6442 if (ret < 0) {
6443 step = "begin";
6444 goto exit;
6445 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006446
Arun Mirpuri5d170872019-03-26 13:21:31 -07006447 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6448 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6449 info->burst_size_frames = in->config.period_size;
6450 ret = platform_get_mmap_data_fd(adev->platform,
6451 in->pcm_device_id, 1 /*capture*/,
6452 &info->shared_memory_fd,
6453 &mmap_size);
6454 if (ret < 0) {
6455 // Fall back to non exclusive mode
6456 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6457 } else {
6458 if (mmap_size < buffer_size) {
6459 step = "mmap";
6460 goto exit;
6461 }
6462 // FIXME: indicate exclusive mode support by returning a negative buffer size
6463 info->buffer_size_frames *= -1;
6464 }
6465
6466 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006467
6468 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6469 if (ret < 0) {
6470 step = "commit";
6471 goto exit;
6472 }
6473
6474 in->standby = false;
6475 ret = 0;
6476
6477 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6478 __func__, info->shared_memory_address, info->buffer_size_frames);
6479
6480exit:
6481 if (ret != 0) {
6482 if (in->pcm == NULL) {
6483 ALOGE("%s: %s - %d", __func__, step, ret);
6484 } else {
6485 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6486 pcm_close(in->pcm);
6487 in->pcm = NULL;
6488 }
6489 }
6490 pthread_mutex_unlock(&adev->lock);
6491 return ret;
6492}
6493
6494static int in_get_mmap_position(const struct audio_stream_in *stream,
6495 struct audio_mmap_position *position)
6496{
6497 struct stream_in *in = (struct stream_in *)stream;
6498 ALOGVV("%s", __func__);
6499 if (position == NULL) {
6500 return -EINVAL;
6501 }
6502 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6503 return -ENOSYS;
6504 }
6505 if (in->pcm == NULL) {
6506 return -ENOSYS;
6507 }
6508 struct timespec ts = { 0, 0 };
6509 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6510 if (ret < 0) {
6511 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6512 return ret;
6513 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306514 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006515 return 0;
6516}
6517
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306518static int in_get_active_microphones(const struct audio_stream_in *stream,
6519 struct audio_microphone_characteristic_t *mic_array,
6520 size_t *mic_count) {
6521 struct stream_in *in = (struct stream_in *)stream;
6522 struct audio_device *adev = in->dev;
6523 ALOGVV("%s", __func__);
6524
6525 lock_input_stream(in);
6526 pthread_mutex_lock(&adev->lock);
6527 int ret = platform_get_active_microphones(adev->platform,
6528 audio_channel_count_from_in_mask(in->channel_mask),
6529 in->usecase, mic_array, mic_count);
6530 pthread_mutex_unlock(&adev->lock);
6531 pthread_mutex_unlock(&in->lock);
6532
6533 return ret;
6534}
6535
6536static int adev_get_microphones(const struct audio_hw_device *dev,
6537 struct audio_microphone_characteristic_t *mic_array,
6538 size_t *mic_count) {
6539 struct audio_device *adev = (struct audio_device *)dev;
6540 ALOGVV("%s", __func__);
6541
6542 pthread_mutex_lock(&adev->lock);
6543 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6544 pthread_mutex_unlock(&adev->lock);
6545
6546 return ret;
6547}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306548int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006549 audio_io_handle_t handle,
6550 audio_devices_t devices,
6551 audio_output_flags_t flags,
6552 struct audio_config *config,
6553 struct audio_stream_out **stream_out,
6554 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006555{
6556 struct audio_device *adev = (struct audio_device *)dev;
6557 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306558 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006559 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006560 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306561 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006562 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6563 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6564 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6565 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006566 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006567 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006568 bool force_haptic_path =
6569 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006570
kunleizdff872d2018-08-20 14:40:33 +08006571 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006572 is_usb_dev = false;
6573 devices = AUDIO_DEVICE_OUT_SPEAKER;
6574 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6575 __func__, devices);
6576 }
6577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006580 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6581
Mingming Yin3a941d42016-02-17 18:08:05 -08006582 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6583 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306584 devices, flags, &out->stream);
6585
6586
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006587 if (!out) {
6588 return -ENOMEM;
6589 }
6590
Haynes Mathew George204045b2015-02-25 20:32:03 -08006591 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006592 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306593 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006594 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006595 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006597 if (devices == AUDIO_DEVICE_NONE)
6598 devices = AUDIO_DEVICE_OUT_SPEAKER;
6599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006600 out->flags = flags;
6601 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006602 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006603 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006604 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306605 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306606 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6607 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6608 else
6609 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006610 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006611 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006612 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306613 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306614 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306615 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006616 out->hal_output_suspend_supported = 0;
6617 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306618 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306619 out->prev_card_status_offline = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006620
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306621 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306622 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006623 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6624
Aalique Grahame22e49102018-12-18 14:23:57 -08006625 if (direct_dev &&
6626 (audio_is_linear_pcm(out->format) ||
6627 config->format == AUDIO_FORMAT_DEFAULT) &&
6628 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6629 audio_format_t req_format = config->format;
6630 audio_channel_mask_t req_channel_mask = config->channel_mask;
6631 uint32_t req_sample_rate = config->sample_rate;
6632
6633 pthread_mutex_lock(&adev->lock);
6634 if (is_hdmi) {
6635 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6636 ret = read_hdmi_sink_caps(out);
6637 if (config->sample_rate == 0)
6638 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6639 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6640 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6641 if (config->format == AUDIO_FORMAT_DEFAULT)
6642 config->format = AUDIO_FORMAT_PCM_16_BIT;
6643 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006644 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6645 &config->format,
6646 &out->supported_formats[0],
6647 MAX_SUPPORTED_FORMATS,
6648 &config->channel_mask,
6649 &out->supported_channel_masks[0],
6650 MAX_SUPPORTED_CHANNEL_MASKS,
6651 &config->sample_rate,
6652 &out->supported_sample_rates[0],
6653 MAX_SUPPORTED_SAMPLE_RATES);
6654 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006655 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006656
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006657 pthread_mutex_unlock(&adev->lock);
6658 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006659 if (ret == -ENOSYS) {
6660 /* ignore and go with default */
6661 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006662 }
6663 // For MMAP NO IRQ, allow conversions in ADSP
6664 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6665 goto error_open;
6666 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006667 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006668 goto error_open;
6669 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006670
6671 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6672 config->sample_rate = req_sample_rate;
6673 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6674 config->channel_mask = req_channel_mask;
6675 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6676 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006677 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006678
6679 out->sample_rate = config->sample_rate;
6680 out->channel_mask = config->channel_mask;
6681 out->format = config->format;
6682 if (is_hdmi) {
6683 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6684 out->config = pcm_config_hdmi_multi;
6685 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6686 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6687 out->config = pcm_config_mmap_playback;
6688 out->stream.start = out_start;
6689 out->stream.stop = out_stop;
6690 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6691 out->stream.get_mmap_position = out_get_mmap_position;
6692 } else {
6693 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6694 out->config = pcm_config_hifi;
6695 }
6696
6697 out->config.rate = out->sample_rate;
6698 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6699 if (is_hdmi) {
6700 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6701 audio_bytes_per_sample(out->format));
6702 }
6703 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006704 }
6705
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006706 /* Check for VOIP usecase */
6707 if(out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) {
6708 if (!voice_extn_is_compress_voip_supported()) {
6709 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6710 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006711 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006712 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6713 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006714
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006715 out->config = default_pcm_config_voip_copp;
6716 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6717 out->config.rate = out->sample_rate;
6718 }
6719 } else {
6720 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6721 voice_extn_compress_voip_is_active(out->dev)) &&
6722 (voice_extn_compress_voip_is_config_supported(config))) {
6723 ret = voice_extn_compress_voip_open_output_stream(out);
6724 if (ret != 0) {
6725 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6726 __func__, ret);
6727 goto error_open;
6728 }
6729 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006730 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006731 } else if (audio_is_linear_pcm(out->format) &&
6732 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6733 out->channel_mask = config->channel_mask;
6734 out->sample_rate = config->sample_rate;
6735 out->format = config->format;
6736 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6737 // does this change?
6738 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6739 out->config.rate = config->sample_rate;
6740 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6741 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6742 audio_bytes_per_sample(config->format));
6743 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006744 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306745 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306746 pthread_mutex_lock(&adev->lock);
6747 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6748 pthread_mutex_unlock(&adev->lock);
6749
6750 // reject offload during card offline to allow
6751 // fallback to s/w paths
6752 if (offline) {
6753 ret = -ENODEV;
6754 goto error_open;
6755 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006756
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006757 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6758 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6759 ALOGE("%s: Unsupported Offload information", __func__);
6760 ret = -EINVAL;
6761 goto error_open;
6762 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006763
Atul Khare3fa6e542017-08-09 00:56:17 +05306764 if (config->offload_info.format == 0)
6765 config->offload_info.format = config->format;
6766 if (config->offload_info.sample_rate == 0)
6767 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006768
Mingming Yin90310102013-11-13 16:57:00 -08006769 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306770 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006771 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006772 ret = -EINVAL;
6773 goto error_open;
6774 }
6775
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006776 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6777 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6778 (audio_extn_passthru_is_passthrough_stream(out)) &&
6779 !((config->sample_rate == 48000) ||
6780 (config->sample_rate == 96000) ||
6781 (config->sample_rate == 192000))) {
6782 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6783 __func__, config->sample_rate, config->offload_info.format);
6784 ret = -EINVAL;
6785 goto error_open;
6786 }
6787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006788 out->compr_config.codec = (struct snd_codec *)
6789 calloc(1, sizeof(struct snd_codec));
6790
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006791 if (!out->compr_config.codec) {
6792 ret = -ENOMEM;
6793 goto error_open;
6794 }
6795
Dhananjay Kumarac341582017-02-23 23:42:25 +05306796 out->stream.pause = out_pause;
6797 out->stream.resume = out_resume;
6798 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306799 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306800 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006801 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306802 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006803 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306804 } else {
6805 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6806 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006807 }
vivek mehta446c3962015-09-14 10:57:35 -07006808
6809 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006810 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6811 config->format == 0 && config->sample_rate == 0 &&
6812 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006813 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006814 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6815 } else {
6816 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6817 ret = -EEXIST;
6818 goto error_open;
6819 }
vivek mehta446c3962015-09-14 10:57:35 -07006820 }
6821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006822 if (config->offload_info.channel_mask)
6823 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006824 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006825 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006826 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006827 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306828 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006829 ret = -EINVAL;
6830 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006831 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006832
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006833 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006834 out->sample_rate = config->offload_info.sample_rate;
6835
Mingming Yin3ee55c62014-08-04 14:23:35 -07006836 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006837
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306838 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306839 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306840 audio_extn_dolby_send_ddp_endp_params(adev);
6841 audio_extn_dolby_set_dmid(adev);
6842 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006843
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006844 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006845 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006846 out->compr_config.codec->bit_rate =
6847 config->offload_info.bit_rate;
6848 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306849 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006850 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306851 /* Update bit width only for non passthrough usecases.
6852 * For passthrough usecases, the output will always be opened @16 bit
6853 */
6854 if (!audio_extn_passthru_is_passthrough_stream(out))
6855 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306856
6857 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6858 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6859 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6860
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006861 /*TODO: Do we need to change it for passthrough */
6862 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006863
Manish Dewangana6fc5442015-08-24 20:30:31 +05306864 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6865 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306866 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306867 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306868 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6869 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306870
6871 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6872 AUDIO_FORMAT_PCM) {
6873
6874 /*Based on platform support, configure appropriate alsa format for corresponding
6875 *hal input format.
6876 */
6877 out->compr_config.codec->format = hal_format_to_alsa(
6878 config->offload_info.format);
6879
Ashish Jain83a6cc22016-06-28 14:34:17 +05306880 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306881 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306882 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306883
Dhananjay Kumarac341582017-02-23 23:42:25 +05306884 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306885 *hal input format and alsa format might differ based on platform support.
6886 */
6887 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306888 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306889
6890 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6891
6892 /* Check if alsa session is configured with the same format as HAL input format,
6893 * if not then derive correct fragment size needed to accomodate the
6894 * conversion of HAL input format to alsa format.
6895 */
6896 audio_extn_utils_update_direct_pcm_fragment_size(out);
6897
6898 /*if hal input and output fragment size is different this indicates HAL input format is
6899 *not same as the alsa format
6900 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306901 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306902 /*Allocate a buffer to convert input data to the alsa configured format.
6903 *size of convert buffer is equal to the size required to hold one fragment size
6904 *worth of pcm data, this is because flinger does not write more than fragment_size
6905 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306906 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6907 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306908 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6909 ret = -ENOMEM;
6910 goto error_open;
6911 }
6912 }
6913 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6914 out->compr_config.fragment_size =
6915 audio_extn_passthru_get_buffer_size(&config->offload_info);
6916 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6917 } else {
6918 out->compr_config.fragment_size =
6919 platform_get_compress_offload_buffer_size(&config->offload_info);
6920 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6921 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006922
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306923 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6924 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6925 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006926 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306927 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006928
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306929 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6930 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6931 }
6932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006933 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6934 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006935
Manish Dewangan69426c82017-01-30 17:35:36 +05306936 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6937 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6938 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6939 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6940 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6941 } else {
6942 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6943 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006944
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306945 memset(&out->channel_map_param, 0,
6946 sizeof(struct audio_out_channel_map_param));
6947
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006948 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306949 out->send_next_track_params = false;
6950 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006951 out->offload_state = OFFLOAD_STATE_IDLE;
6952 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006953 out->writeAt.tv_sec = 0;
6954 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006955
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006956 audio_extn_dts_create_state_notifier_node(out->usecase);
6957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006958 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6959 __func__, config->offload_info.version,
6960 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306961
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306962 /* Check if DSD audio format is supported in codec
6963 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306964 */
6965
6966 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306967 (!platform_check_codec_dsd_support(adev->platform) ||
6968 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306969 ret = -EINVAL;
6970 goto error_open;
6971 }
6972
Ashish Jain5106d362016-05-11 19:23:33 +05306973 /* Disable gapless if any of the following is true
6974 * passthrough playback
6975 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306976 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306977 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306978 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306979 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006980 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306981 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306982 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306983 check_and_set_gapless_mode(adev, false);
6984 } else
6985 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006986
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306987 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006988 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6989 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306990 if (config->format == AUDIO_FORMAT_DSD) {
6991 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6992 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6993 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006994
6995 create_offload_callback_thread(out);
6996
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006997 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006998 switch (config->sample_rate) {
6999 case 0:
7000 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7001 break;
7002 case 8000:
7003 case 16000:
7004 case 48000:
7005 out->sample_rate = config->sample_rate;
7006 break;
7007 default:
7008 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7009 config->sample_rate);
7010 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7011 ret = -EINVAL;
7012 goto error_open;
7013 }
7014 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7015 switch (config->channel_mask) {
7016 case AUDIO_CHANNEL_NONE:
7017 case AUDIO_CHANNEL_OUT_STEREO:
7018 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7019 break;
7020 default:
7021 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7022 config->channel_mask);
7023 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7024 ret = -EINVAL;
7025 goto error_open;
7026 }
7027 switch (config->format) {
7028 case AUDIO_FORMAT_DEFAULT:
7029 case AUDIO_FORMAT_PCM_16_BIT:
7030 out->format = AUDIO_FORMAT_PCM_16_BIT;
7031 break;
7032 default:
7033 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7034 config->format);
7035 config->format = AUDIO_FORMAT_PCM_16_BIT;
7036 ret = -EINVAL;
7037 goto error_open;
7038 }
7039
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307040 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007041 if (ret != 0) {
7042 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007043 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007044 goto error_open;
7045 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007046 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007047 switch (config->sample_rate) {
7048 case 0:
7049 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7050 break;
7051 case 8000:
7052 case 16000:
7053 case 48000:
7054 out->sample_rate = config->sample_rate;
7055 break;
7056 default:
7057 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7058 config->sample_rate);
7059 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7060 ret = -EINVAL;
7061 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007062 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007063 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7064 switch (config->channel_mask) {
7065 case AUDIO_CHANNEL_NONE:
7066 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7067 break;
7068 case AUDIO_CHANNEL_OUT_STEREO:
7069 out->channel_mask = config->channel_mask;
7070 break;
7071 default:
7072 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7073 config->channel_mask);
7074 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7075 ret = -EINVAL;
7076 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007077 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007078 switch (config->format) {
7079 case AUDIO_FORMAT_DEFAULT:
7080 out->format = AUDIO_FORMAT_PCM_16_BIT;
7081 break;
7082 case AUDIO_FORMAT_PCM_16_BIT:
7083 out->format = config->format;
7084 break;
7085 default:
7086 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7087 config->format);
7088 config->format = AUDIO_FORMAT_PCM_16_BIT;
7089 ret = -EINVAL;
7090 break;
7091 }
7092 if (ret != 0)
7093 goto error_open;
7094
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007095 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7096 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007097 out->config.rate = out->sample_rate;
7098 out->config.channels =
7099 audio_channel_count_from_out_mask(out->channel_mask);
7100 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007101 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007102 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307103 unsigned int channels = 0;
7104 /*Update config params to default if not set by the caller*/
7105 if (config->sample_rate == 0)
7106 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7107 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7108 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7109 if (config->format == AUDIO_FORMAT_DEFAULT)
7110 config->format = AUDIO_FORMAT_PCM_16_BIT;
7111
7112 channels = audio_channel_count_from_out_mask(out->channel_mask);
7113
Varun Balaraje49253e2017-07-06 19:48:56 +05307114 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7115 out->usecase = get_interactive_usecase(adev);
7116 out->config = pcm_config_low_latency;
7117 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307118 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007119 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7120 out->flags);
7121 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007122 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7123 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7124 out->config = pcm_config_mmap_playback;
7125 out->stream.start = out_start;
7126 out->stream.stop = out_stop;
7127 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7128 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307129 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7130 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007131 out->hal_output_suspend_supported =
7132 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7133 out->dynamic_pm_qos_config_supported =
7134 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7135 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007136 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7137 } else {
7138 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7139 //the mixer path will be a string similar to "low-latency-playback resume"
7140 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7141 strlcat(out->pm_qos_mixer_path,
7142 " resume", MAX_MIXER_PATH_LEN);
7143 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7144 out->pm_qos_mixer_path);
7145 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307146 out->config = pcm_config_low_latency;
7147 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7148 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7149 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307150 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7151 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7152 if (out->config.period_size <= 0) {
7153 ALOGE("Invalid configuration period size is not valid");
7154 ret = -EINVAL;
7155 goto error_open;
7156 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007157 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7158 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7159 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007160 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7161 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7162 out->config = pcm_config_haptics_audio;
7163 if (force_haptic_path)
7164 adev->haptics_config = pcm_config_haptics_audio;
7165 else
7166 adev->haptics_config = pcm_config_haptics;
7167
7168 out->config.channels =
7169 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7170
7171 if (force_haptic_path) {
7172 out->config.channels = 1;
7173 adev->haptics_config.channels = 1;
7174 } else
7175 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307176 } else {
7177 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007178 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7179 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307180 }
7181 out->hal_ip_format = format = out->format;
7182 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7183 out->hal_op_format = pcm_format_to_hal(out->config.format);
7184 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7185 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007186 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307187 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307188 if (out->hal_ip_format != out->hal_op_format) {
7189 uint32_t buffer_size = out->config.period_size *
7190 format_to_bitwidth_table[out->hal_op_format] *
7191 out->config.channels;
7192 out->convert_buffer = calloc(1, buffer_size);
7193 if (out->convert_buffer == NULL){
7194 ALOGE("Allocation failed for convert buffer for size %d",
7195 out->compr_config.fragment_size);
7196 ret = -ENOMEM;
7197 goto error_open;
7198 }
7199 ALOGD("Convert buffer allocated of size %d", buffer_size);
7200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201 }
7202
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007203 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7204 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307205
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007206 /* TODO remove this hardcoding and check why width is zero*/
7207 if (out->bit_width == 0)
7208 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307209 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007210 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007211 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307212 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307213 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007214 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007215 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7216 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007217 if(adev->primary_output == NULL)
7218 adev->primary_output = out;
7219 else {
7220 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007221 ret = -EEXIST;
7222 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007223 }
7224 }
7225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007226 /* Check if this usecase is already existing */
7227 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007228 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7229 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007230 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007231 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007232 ret = -EEXIST;
7233 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007234 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236 pthread_mutex_unlock(&adev->lock);
7237
7238 out->stream.common.get_sample_rate = out_get_sample_rate;
7239 out->stream.common.set_sample_rate = out_set_sample_rate;
7240 out->stream.common.get_buffer_size = out_get_buffer_size;
7241 out->stream.common.get_channels = out_get_channels;
7242 out->stream.common.get_format = out_get_format;
7243 out->stream.common.set_format = out_set_format;
7244 out->stream.common.standby = out_standby;
7245 out->stream.common.dump = out_dump;
7246 out->stream.common.set_parameters = out_set_parameters;
7247 out->stream.common.get_parameters = out_get_parameters;
7248 out->stream.common.add_audio_effect = out_add_audio_effect;
7249 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7250 out->stream.get_latency = out_get_latency;
7251 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007252#ifdef NO_AUDIO_OUT
7253 out->stream.write = out_write_for_no_output;
7254#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007255 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007256#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007257 out->stream.get_render_position = out_get_render_position;
7258 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007259 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007260
Haynes Mathew George16081042017-05-31 17:16:49 -07007261 if (out->realtime)
7262 out->af_period_multiplier = af_period_multiplier;
7263 else
7264 out->af_period_multiplier = 1;
7265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007266 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007267 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007268 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007269
7270 config->format = out->stream.common.get_format(&out->stream.common);
7271 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7272 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307273 register_format(out->format, out->supported_formats);
7274 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7275 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007276
Aalique Grahame22e49102018-12-18 14:23:57 -08007277 out->error_log = error_log_create(
7278 ERROR_LOG_ENTRIES,
7279 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7280
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307281 /*
7282 By locking output stream before registering, we allow the callback
7283 to update stream's state only after stream's initial state is set to
7284 adev state.
7285 */
7286 lock_output_stream(out);
7287 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7288 pthread_mutex_lock(&adev->lock);
7289 out->card_status = adev->card_status;
7290 pthread_mutex_unlock(&adev->lock);
7291 pthread_mutex_unlock(&out->lock);
7292
Aalique Grahame22e49102018-12-18 14:23:57 -08007293 stream_app_type_cfg_init(&out->app_type_cfg);
7294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007295 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307296 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007297 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007298
7299 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7300 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7301 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007302 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307303 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007304 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007305 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307306 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007307 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7308 out->usecase, PCM_PLAYBACK);
7309 hdlr_stream_cfg.flags = out->flags;
7310 hdlr_stream_cfg.type = PCM_PLAYBACK;
7311 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7312 &hdlr_stream_cfg);
7313 if (ret) {
7314 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7315 out->adsp_hdlr_stream_handle = NULL;
7316 }
7317 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307318 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007319 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007320 if (ret < 0) {
7321 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7322 out->ip_hdlr_handle = NULL;
7323 }
7324 }
Derek Chenf939fb72018-11-13 13:34:41 -08007325
7326 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7327 calloc(1, sizeof(streams_output_ctxt_t));
7328 if (out_ctxt == NULL) {
7329 ALOGE("%s fail to allocate output ctxt", __func__);
7330 ret = -ENOMEM;
7331 goto error_open;
7332 }
7333 out_ctxt->output = out;
7334
7335 pthread_mutex_lock(&adev->lock);
7336 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7337 pthread_mutex_unlock(&adev->lock);
7338
Eric Laurent994a6932013-07-17 11:51:42 -07007339 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007340 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007341
7342error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307343 if (out->convert_buffer)
7344 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007345 free(out);
7346 *stream_out = NULL;
7347 ALOGD("%s: exit: ret %d", __func__, ret);
7348 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007349}
7350
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307351void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007352 struct audio_stream_out *stream)
7353{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007354 struct stream_out *out = (struct stream_out *)stream;
7355 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007356 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007357
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007358 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307359
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307360 // must deregister from sndmonitor first to prevent races
7361 // between the callback and close_stream
7362 audio_extn_snd_mon_unregister_listener(out);
7363
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007364 /* close adsp hdrl session before standby */
7365 if (out->adsp_hdlr_stream_handle) {
7366 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7367 if (ret)
7368 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7369 out->adsp_hdlr_stream_handle = NULL;
7370 }
7371
Manish Dewangan21a850a2017-08-14 12:03:55 +05307372 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007373 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7374 out->ip_hdlr_handle = NULL;
7375 }
7376
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007377 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307378 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007379 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307380 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307381 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007382 if(ret != 0)
7383 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7384 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007385 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007386 out_standby(&stream->common);
7387
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007388 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007389 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007390 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007391 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007392 if (out->compr_config.codec != NULL)
7393 free(out->compr_config.codec);
7394 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007395
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307396 out->a2dp_compress_mute = false;
7397
Varun Balaraje49253e2017-07-06 19:48:56 +05307398 if (is_interactive_usecase(out->usecase))
7399 free_interactive_usecase(adev, out->usecase);
7400
Ashish Jain83a6cc22016-06-28 14:34:17 +05307401 if (out->convert_buffer != NULL) {
7402 free(out->convert_buffer);
7403 out->convert_buffer = NULL;
7404 }
7405
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007406 if (adev->voice_tx_output == out)
7407 adev->voice_tx_output = NULL;
7408
Aalique Grahame22e49102018-12-18 14:23:57 -08007409 error_log_destroy(out->error_log);
7410 out->error_log = NULL;
7411
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307412 if (adev->primary_output == out)
7413 adev->primary_output = NULL;
7414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007415 pthread_cond_destroy(&out->cond);
7416 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007417
7418 pthread_mutex_lock(&adev->lock);
7419 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7420 if (out_ctxt != NULL) {
7421 list_remove(&out_ctxt->list);
7422 free(out_ctxt);
7423 } else {
7424 ALOGW("%s, output stream already closed", __func__);
7425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007426 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007427 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007428 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007429}
7430
7431static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7432{
7433 struct audio_device *adev = (struct audio_device *)dev;
7434 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007435 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007436 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007437 int ret;
7438 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007439 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007440
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007441 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007442 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007443
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307444 if (!parms)
7445 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307446
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307447 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7448 if (ret >= 0) {
7449 /* When set to false, HAL should disable EC and NS */
7450 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7451 adev->bt_sco_on = true;
7452 else
7453 adev->bt_sco_on = false;
7454 }
7455
Naresh Tanniru4c630392014-05-12 01:05:52 +05307456 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007457 status = voice_set_parameters(adev, parms);
7458 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007459 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007460
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007461 status = platform_set_parameters(adev->platform, parms);
7462 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007463 goto done;
7464
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007465 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7466 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007467 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7469 adev->bluetooth_nrec = true;
7470 else
7471 adev->bluetooth_nrec = false;
7472 }
7473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007474 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7475 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007476 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7477 adev->screen_off = false;
7478 else
7479 adev->screen_off = true;
7480 }
7481
Aalique Grahame22e49102018-12-18 14:23:57 -08007482#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007483 ret = str_parms_get_int(parms, "rotation", &val);
7484 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007485 bool reverse_speakers = false;
7486 switch(val) {
7487 // FIXME: note that the code below assumes that the speakers are in the correct placement
7488 // relative to the user when the device is rotated 90deg from its default rotation. This
7489 // assumption is device-specific, not platform-specific like this code.
7490 case 270:
7491 reverse_speakers = true;
7492 break;
7493 case 0:
7494 case 90:
7495 case 180:
7496 break;
7497 default:
7498 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007499 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007500 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007501 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007502 // check and set swap
7503 // - check if orientation changed and speaker active
7504 // - set rotation and cache the rotation value
7505 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007506 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007507 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007508#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007509
Mingming Yin514a8bc2014-07-29 15:22:21 -07007510 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7511 if (ret >= 0) {
7512 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7513 adev->bt_wb_speech_enabled = true;
7514 else
7515 adev->bt_wb_speech_enabled = false;
7516 }
7517
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007518 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7519 if (ret >= 0) {
7520 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307521 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007522 if (audio_is_output_device(val) &&
7523 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007524 ALOGV("cache new ext disp type and edid");
7525 ret = platform_get_ext_disp_type(adev->platform);
7526 if (ret < 0) {
7527 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307528 } else {
7529 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007530 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307531 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007532 /*
7533 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7534 * Per AudioPolicyManager, USB device is higher priority than WFD.
7535 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7536 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7537 * starting voice call on USB
7538 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007539 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307540 if (ret >= 0)
7541 audio_extn_usb_add_device(device, atoi(value));
7542
Zhou Song6f862822017-11-06 17:27:57 +08007543 if (!audio_extn_usb_is_tunnel_supported()) {
7544 ALOGV("detected USB connect .. disable proxy");
7545 adev->allow_afe_proxy_usage = false;
7546 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007547 }
7548 }
7549
7550 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7551 if (ret >= 0) {
7552 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307553 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007554 /*
7555 * The HDMI / Displayport disconnect handling has been moved to
7556 * audio extension to ensure that its parameters are not
7557 * invalidated prior to updating sysfs of the disconnect event
7558 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7559 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307560 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007561 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307562 if (ret >= 0)
7563 audio_extn_usb_remove_device(device, atoi(value));
7564
Zhou Song6f862822017-11-06 17:27:57 +08007565 if (!audio_extn_usb_is_tunnel_supported()) {
7566 ALOGV("detected USB disconnect .. enable proxy");
7567 adev->allow_afe_proxy_usage = true;
7568 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007569 }
7570 }
7571
Aalique Grahame22e49102018-12-18 14:23:57 -08007572 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007573 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007574
7575 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007576 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307577 struct audio_usecase *usecase;
7578 struct listnode *node;
7579 list_for_each(node, &adev->usecase_list) {
7580 usecase = node_to_item(node, struct audio_usecase, list);
7581 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007582 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307583 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007584
7585 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307586 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007587 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307588 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307589 //force device switch to re configure encoder
7590 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307591 audio_extn_a2dp_set_handoff_mode(false);
7592 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307593 break;
7594 }
7595 }
7596 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007597
7598 //handle vr audio setparam
7599 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7600 value, sizeof(value));
7601 if (ret >= 0) {
7602 ALOGI("Setting vr mode to be %s", value);
7603 if (!strncmp(value, "true", 4)) {
7604 adev->vr_audio_mode_enabled = true;
7605 ALOGI("Setting vr mode to true");
7606 } else if (!strncmp(value, "false", 5)) {
7607 adev->vr_audio_mode_enabled = false;
7608 ALOGI("Setting vr mode to false");
7609 } else {
7610 ALOGI("wrong vr mode set");
7611 }
7612 }
7613
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307614 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007615done:
7616 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007617 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307618error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007619 ALOGV("%s: exit with code(%d)", __func__, status);
7620 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007621}
7622
7623static char* adev_get_parameters(const struct audio_hw_device *dev,
7624 const char *keys)
7625{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307626 ALOGD("%s:%s", __func__, keys);
7627
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007628 struct audio_device *adev = (struct audio_device *)dev;
7629 struct str_parms *reply = str_parms_create();
7630 struct str_parms *query = str_parms_create_str(keys);
7631 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307632 char value[256] = {0};
7633 int ret = 0;
7634
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007635 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007636 if (reply) {
7637 str_parms_destroy(reply);
7638 }
7639 if (query) {
7640 str_parms_destroy(query);
7641 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007642 ALOGE("adev_get_parameters: failed to create query or reply");
7643 return NULL;
7644 }
7645
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007646 //handle vr audio getparam
7647
7648 ret = str_parms_get_str(query,
7649 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7650 value, sizeof(value));
7651
7652 if (ret >= 0) {
7653 bool vr_audio_enabled = false;
7654 pthread_mutex_lock(&adev->lock);
7655 vr_audio_enabled = adev->vr_audio_mode_enabled;
7656 pthread_mutex_unlock(&adev->lock);
7657
7658 ALOGI("getting vr mode to %d", vr_audio_enabled);
7659
7660 if (vr_audio_enabled) {
7661 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7662 "true");
7663 goto exit;
7664 } else {
7665 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7666 "false");
7667 goto exit;
7668 }
7669 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007670
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007671 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007672 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007673 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007674 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007675 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307676 pthread_mutex_unlock(&adev->lock);
7677
Naresh Tannirud7205b62014-06-20 02:54:48 +05307678exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007679 str = str_parms_to_str(reply);
7680 str_parms_destroy(query);
7681 str_parms_destroy(reply);
7682
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307683 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007684 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007685}
7686
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007687static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007688{
7689 return 0;
7690}
7691
7692static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7693{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007694 int ret;
7695 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007696
7697 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7698
Haynes Mathew George5191a852013-09-11 14:19:36 -07007699 pthread_mutex_lock(&adev->lock);
7700 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007701 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007702 pthread_mutex_unlock(&adev->lock);
7703 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007704}
7705
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007706static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7707 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007708{
7709 return -ENOSYS;
7710}
7711
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007712static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7713 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007714{
7715 return -ENOSYS;
7716}
7717
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007718static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7719 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007720{
7721 return -ENOSYS;
7722}
7723
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007724static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7725 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007726{
7727 return -ENOSYS;
7728}
7729
7730static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7731{
7732 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007733 struct listnode *node;
7734 struct audio_usecase *usecase = NULL;
7735 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007736 pthread_mutex_lock(&adev->lock);
7737 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007738 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007739 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007740 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007741 list_for_each(node, &adev->usecase_list) {
7742 usecase = node_to_item(node, struct audio_usecase, list);
7743 if (usecase->type == VOICE_CALL)
7744 break;
7745 }
7746 if (usecase &&
7747 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7748 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7749 true);
7750 if (ret != 0) {
7751 /* default service interval was successfully updated,
7752 reopen USB backend with new service interval */
7753 check_usecases_codec_backend(adev,
7754 usecase,
7755 usecase->out_snd_device);
7756 }
7757 }
7758
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007759 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007760 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007761 adev->current_call_output = NULL;
7762 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007763 }
7764 pthread_mutex_unlock(&adev->lock);
7765 return 0;
7766}
7767
7768static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7769{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007770 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007771 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007772
7773 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007774 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007775 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007776
Derek Chend2530072014-11-24 12:39:14 -08007777 if (adev->ext_hw_plugin)
7778 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007779
7780 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007781 pthread_mutex_unlock(&adev->lock);
7782
7783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007784}
7785
7786static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7787{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007788 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007789 return 0;
7790}
7791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007792static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007793 const struct audio_config *config)
7794{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007795 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796
Aalique Grahame22e49102018-12-18 14:23:57 -08007797 /* Don't know if USB HIFI in this context so use true to be conservative */
7798 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7799 true /*is_usb_hifi */) != 0)
7800 return 0;
7801
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007802 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7803 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007804}
7805
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007806static bool adev_input_allow_hifi_record(struct audio_device *adev,
7807 audio_devices_t devices,
7808 audio_input_flags_t flags,
7809 audio_source_t source) {
7810 const bool allowed = true;
7811
7812 if (!audio_is_usb_in_device(devices))
7813 return !allowed;
7814
7815 switch (flags) {
7816 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007817 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007818 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7819 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007820 default:
7821 return !allowed;
7822 }
7823
7824 switch (source) {
7825 case AUDIO_SOURCE_DEFAULT:
7826 case AUDIO_SOURCE_MIC:
7827 case AUDIO_SOURCE_UNPROCESSED:
7828 break;
7829 default:
7830 return !allowed;
7831 }
7832
7833 switch (adev->mode) {
7834 case 0:
7835 break;
7836 default:
7837 return !allowed;
7838 }
7839
7840 return allowed;
7841}
7842
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007843static int adev_update_voice_comm_input_stream(struct stream_in *in,
7844 struct audio_config *config)
7845{
7846 bool valid_rate = (config->sample_rate == 8000 ||
7847 config->sample_rate == 16000 ||
7848 config->sample_rate == 32000 ||
7849 config->sample_rate == 48000);
7850 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7851
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007852 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08007853 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007854 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7855 in->config = default_pcm_config_voip_copp;
7856 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7857 DEFAULT_VOIP_BUF_DURATION_MS,
7858 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007859 } else {
7860 ALOGW("%s No valid input in voip, use defaults"
7861 "sample rate %u, channel mask 0x%X",
7862 __func__, config->sample_rate, in->channel_mask);
7863 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007864 in->config.rate = config->sample_rate;
7865 in->sample_rate = config->sample_rate;
7866 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007867 //XXX needed for voice_extn_compress_voip_open_input_stream
7868 in->config.rate = config->sample_rate;
7869 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7870 voice_extn_compress_voip_is_active(in->dev)) &&
7871 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7872 valid_rate && valid_ch) {
7873 voice_extn_compress_voip_open_input_stream(in);
7874 // update rate entries to match config from AF
7875 in->config.rate = config->sample_rate;
7876 in->sample_rate = config->sample_rate;
7877 } else {
7878 ALOGW("%s compress voip not active, use defaults", __func__);
7879 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007880 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007881 return 0;
7882}
7883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007884static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007885 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007886 audio_devices_t devices,
7887 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007888 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307889 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007890 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007891 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007892{
7893 struct audio_device *adev = (struct audio_device *)dev;
7894 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007895 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007896 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007897 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307898 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007899 bool is_usb_dev = audio_is_usb_in_device(devices);
7900 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7901 devices,
7902 flags,
7903 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307904
kunleizdff872d2018-08-20 14:40:33 +08007905 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007906 is_usb_dev = false;
7907 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7908 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7909 __func__, devices);
7910 }
7911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007912 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007913
7914 if (!(is_usb_dev && may_use_hifi_record)) {
7915 if (config->sample_rate == 0)
7916 config->sample_rate = 48000;
7917 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7918 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7919 if (config->format == AUDIO_FORMAT_DEFAULT)
7920 config->format = AUDIO_FORMAT_PCM_16_BIT;
7921
7922 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7923
Aalique Grahame22e49102018-12-18 14:23:57 -08007924 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7925 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007926 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307927 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007928
7929 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007930
7931 if (!in) {
7932 ALOGE("failed to allocate input stream");
7933 return -ENOMEM;
7934 }
7935
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307936 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307937 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7938 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007939 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007940 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007942 in->stream.common.get_sample_rate = in_get_sample_rate;
7943 in->stream.common.set_sample_rate = in_set_sample_rate;
7944 in->stream.common.get_buffer_size = in_get_buffer_size;
7945 in->stream.common.get_channels = in_get_channels;
7946 in->stream.common.get_format = in_get_format;
7947 in->stream.common.set_format = in_set_format;
7948 in->stream.common.standby = in_standby;
7949 in->stream.common.dump = in_dump;
7950 in->stream.common.set_parameters = in_set_parameters;
7951 in->stream.common.get_parameters = in_get_parameters;
7952 in->stream.common.add_audio_effect = in_add_audio_effect;
7953 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7954 in->stream.set_gain = in_set_gain;
7955 in->stream.read = in_read;
7956 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08007957 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307958 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007959
7960 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007961 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007962 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007963 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007964 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007965 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007966 in->bit_width = 16;
7967 in->af_period_multiplier = 1;
7968
Aalique Grahame22e49102018-12-18 14:23:57 -08007969 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
7970 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
7971 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
7972 /* Force channel config requested to mono if incall
7973 record is being requested for only uplink/downlink */
7974 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
7975 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7976 ret = -EINVAL;
7977 goto err_open;
7978 }
7979 }
7980
Haynes Mathew George46740472017-10-27 18:40:12 -07007981 /* Update config params with the requested sample rate and channels */
7982 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7983 (adev->mode != AUDIO_MODE_IN_CALL)) {
7984 ret = -EINVAL;
7985 goto err_open;
7986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007987
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007988 if (is_usb_dev && may_use_hifi_record) {
7989 /* HiFi record selects an appropriate format, channel, rate combo
7990 depending on sink capabilities*/
7991 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7992 &config->format,
7993 &in->supported_formats[0],
7994 MAX_SUPPORTED_FORMATS,
7995 &config->channel_mask,
7996 &in->supported_channel_masks[0],
7997 MAX_SUPPORTED_CHANNEL_MASKS,
7998 &config->sample_rate,
7999 &in->supported_sample_rates[0],
8000 MAX_SUPPORTED_SAMPLE_RATES);
8001 if (ret != 0) {
8002 ret = -EINVAL;
8003 goto err_open;
8004 }
8005 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008006 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308007 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308008 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8009 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8010 in->config.format = PCM_FORMAT_S32_LE;
8011 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308012 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8013 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8014 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8015 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8016 bool ret_error = false;
8017 in->bit_width = 24;
8018 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8019 from HAL is 24_packed and 8_24
8020 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8021 24_packed return error indicating supported format is 24_packed
8022 *> In case of any other source requesting 24 bit or float return error
8023 indicating format supported is 16 bit only.
8024
8025 on error flinger will retry with supported format passed
8026 */
8027 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8028 (source != AUDIO_SOURCE_CAMCORDER)) {
8029 config->format = AUDIO_FORMAT_PCM_16_BIT;
8030 if (config->sample_rate > 48000)
8031 config->sample_rate = 48000;
8032 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008033 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8034 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308035 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8036 ret_error = true;
8037 }
8038
8039 if (ret_error) {
8040 ret = -EINVAL;
8041 goto err_open;
8042 }
8043 }
8044
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008045 in->channel_mask = config->channel_mask;
8046 in->format = config->format;
8047
8048 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308049
8050 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8051 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8052 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8053 else {
8054 ret = -EINVAL;
8055 goto err_open;
8056 }
8057 }
8058
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008059 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8060 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8061 is_low_latency = true;
8062#if LOW_LATENCY_CAPTURE_USE_CASE
8063 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8064#endif
8065 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008066 if (!in->realtime) {
8067 in->config = pcm_config_audio_capture;
8068 frame_size = audio_stream_in_frame_size(&in->stream);
8069 buffer_size = get_input_buffer_size(config->sample_rate,
8070 config->format,
8071 channel_count,
8072 is_low_latency);
8073 in->config.period_size = buffer_size / frame_size;
8074 in->config.rate = config->sample_rate;
8075 in->af_period_multiplier = 1;
8076 } else {
8077 // period size is left untouched for rt mode playback
8078 in->config = pcm_config_audio_capture_rt;
8079 in->af_period_multiplier = af_period_multiplier;
8080 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008081 }
8082
8083 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8084 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8085 in->realtime = 0;
8086 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8087 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008088 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08008089 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008090 in->stream.start = in_start;
8091 in->stream.stop = in_stop;
8092 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8093 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008094 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008095 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8096 } else if (in->realtime) {
8097 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008098 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008099 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008100 in->sample_rate = in->config.rate;
8101 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008102 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008103 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8104 in->config = pcm_config_audio_capture;
8105 frame_size = audio_stream_in_frame_size(&in->stream);
8106 buffer_size = get_input_buffer_size(config->sample_rate,
8107 config->format,
8108 channel_count,
8109 false /*is_low_latency*/);
8110 in->config.period_size = buffer_size / frame_size;
8111 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008112 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008113 switch (config->format) {
8114 case AUDIO_FORMAT_PCM_32_BIT:
8115 in->bit_width = 32;
8116 break;
8117 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8118 case AUDIO_FORMAT_PCM_8_24_BIT:
8119 in->bit_width = 24;
8120 break;
8121 default:
8122 in->bit_width = 16;
8123 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008124 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008125 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008126 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308127 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008128 if (config->sample_rate == 0)
8129 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8130 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8131 config->sample_rate != 8000) {
8132 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8133 ret = -EINVAL;
8134 goto err_open;
8135 }
8136 if (config->format == AUDIO_FORMAT_DEFAULT)
8137 config->format = AUDIO_FORMAT_PCM_16_BIT;
8138 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8139 config->format = AUDIO_FORMAT_PCM_16_BIT;
8140 ret = -EINVAL;
8141 goto err_open;
8142 }
8143
8144 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8145 in->config = pcm_config_afe_proxy_record;
8146 in->config.channels = channel_count;
8147 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308148 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008149 in->af_period_multiplier = 1;
8150 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8151 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8152 (config->sample_rate == 8000 ||
8153 config->sample_rate == 16000 ||
8154 config->sample_rate == 32000 ||
8155 config->sample_rate == 48000) &&
8156 channel_count == 1) {
8157 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8158 in->config = pcm_config_audio_capture;
8159 frame_size = audio_stream_in_frame_size(&in->stream);
8160 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8161 config->sample_rate,
8162 config->format,
8163 channel_count, false /*is_low_latency*/);
8164 in->config.period_size = buffer_size / frame_size;
8165 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8166 in->config.rate = config->sample_rate;
8167 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008168 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308169 int ret_val;
8170 pthread_mutex_lock(&adev->lock);
8171 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8172 in, config, &channel_mask_updated);
8173 pthread_mutex_unlock(&adev->lock);
8174
8175 if (!ret_val) {
8176 if (channel_mask_updated == true) {
8177 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8178 __func__, config->channel_mask);
8179 ret = -EINVAL;
8180 goto err_open;
8181 }
8182 ALOGD("%s: created multi-channel session succesfully",__func__);
8183 } else if (audio_extn_compr_cap_enabled() &&
8184 audio_extn_compr_cap_format_supported(config->format) &&
8185 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8186 audio_extn_compr_cap_init(in);
8187 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05308188 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05308189 ret = audio_extn_cin_configure_input_stream(in);
8190 if (ret)
8191 goto err_open;
8192 } else {
8193 in->config = pcm_config_audio_capture;
8194 in->config.rate = config->sample_rate;
8195 in->config.format = pcm_format_from_audio_format(config->format);
8196 in->config.channels = channel_count;
8197 in->sample_rate = config->sample_rate;
8198 in->format = config->format;
8199 frame_size = audio_stream_in_frame_size(&in->stream);
8200 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008201 config->format,
8202 channel_count,
8203 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008204 /* prevent division-by-zero */
8205 if (frame_size == 0) {
8206 ALOGE("%s: Error frame_size==0", __func__);
8207 ret = -EINVAL;
8208 goto err_open;
8209 }
8210
Revathi Uddarajud2634032017-12-07 14:42:34 +05308211 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008212 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008213
Revathi Uddarajud2634032017-12-07 14:42:34 +05308214 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8215 /* optionally use VOIP usecase depending on config(s) */
8216 ret = adev_update_voice_comm_input_stream(in, config);
8217 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008218
Revathi Uddarajud2634032017-12-07 14:42:34 +05308219 if (ret) {
8220 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8221 goto err_open;
8222 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008223 }
kunleiz28c73e72019-03-27 17:24:04 +08008224#ifdef CONCURRENT_CAPTURE_ENABLED
8225 /* Acquire lock to avoid two concurrent use cases initialized to
8226 same pcm record use case */
8227
8228 pthread_mutex_lock(&adev->lock);
8229 if (in->usecase == USECASE_AUDIO_RECORD) {
8230 if (!(adev->pcm_record_uc_state)) {
8231 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8232 adev->pcm_record_uc_state = 1;
8233 } else {
8234 /* Assign compress record use case for second record */
8235 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8236 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8237 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8238 }
8239 }
8240 pthread_mutex_unlock(&adev->lock);
8241#endif
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008242 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308243 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8244 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008245 devices, flags, in->format,
8246 in->sample_rate, in->bit_width,
8247 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308248 register_format(in->format, in->supported_formats);
8249 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8250 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308251
Aalique Grahame22e49102018-12-18 14:23:57 -08008252 in->error_log = error_log_create(
8253 ERROR_LOG_ENTRIES,
8254 1000000000 /* aggregate consecutive identical errors within one second */);
8255
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008256 /* This stream could be for sound trigger lab,
8257 get sound trigger pcm if present */
8258 audio_extn_sound_trigger_check_and_get_session(in);
8259
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308260 lock_input_stream(in);
8261 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8262 pthread_mutex_lock(&adev->lock);
8263 in->card_status = adev->card_status;
8264 pthread_mutex_unlock(&adev->lock);
8265 pthread_mutex_unlock(&in->lock);
8266
Aalique Grahame22e49102018-12-18 14:23:57 -08008267 stream_app_type_cfg_init(&in->app_type_cfg);
8268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008269 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008270
8271 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8272 calloc(1, sizeof(streams_input_ctxt_t));
8273 if (in_ctxt == NULL) {
8274 ALOGE("%s fail to allocate input ctxt", __func__);
8275 ret = -ENOMEM;
8276 goto err_open;
8277 }
8278 in_ctxt->input = in;
8279
8280 pthread_mutex_lock(&adev->lock);
8281 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8282 pthread_mutex_unlock(&adev->lock);
8283
Eric Laurent994a6932013-07-17 11:51:42 -07008284 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008285 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008286
8287err_open:
8288 free(in);
8289 *stream_in = NULL;
8290 return ret;
8291}
8292
8293static void adev_close_input_stream(struct audio_hw_device *dev,
8294 struct audio_stream_in *stream)
8295{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008296 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008297 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008298 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308299
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308300 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008301
kunleiz70e57612018-12-28 17:50:23 +08008302 /* must deregister from sndmonitor first to prevent races
8303 * between the callback and close_stream
8304 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308305 audio_extn_snd_mon_unregister_listener(stream);
8306
kunleiz70e57612018-12-28 17:50:23 +08008307 /* Disable echo reference if there are no active input, hfp call
8308 * and sound trigger while closing input stream
8309 */
8310 if (!adev->active_input &&
8311 !audio_extn_hfp_is_active(adev) &&
8312 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008313 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008314 else
8315 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308316
Aalique Grahame22e49102018-12-18 14:23:57 -08008317 error_log_destroy(in->error_log);
8318 in->error_log = NULL;
8319
Pallavid7c7a272018-01-16 11:22:55 +05308320 if (in == NULL) {
8321 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8322 return;
8323 }
8324
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008325 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308326 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008327 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308328 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008329 if (ret != 0)
8330 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8331 __func__, ret);
8332 } else
8333 in_standby(&stream->common);
8334
Revathi Uddarajud2634032017-12-07 14:42:34 +05308335 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308336 if (in->usecase == USECASE_AUDIO_RECORD) {
8337 adev->pcm_record_uc_state = 0;
8338 }
8339
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008340 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008341 audio_extn_ssr_deinit();
8342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008343
Garmond Leunge2433c32017-09-28 21:51:22 -07008344 if (audio_extn_ffv_get_stream() == in) {
8345 audio_extn_ffv_stream_deinit();
8346 }
8347
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308348 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008349 audio_extn_compr_cap_format_supported(in->config.format))
8350 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308351
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308352 if (audio_extn_cin_attached_usecase(in->usecase))
8353 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008354
Mingming Yinfd7607b2016-01-22 12:48:44 -08008355 if (in->is_st_session) {
8356 ALOGV("%s: sound trigger pcm stop lab", __func__);
8357 audio_extn_sound_trigger_stop_lab(in);
8358 }
Derek Chenf939fb72018-11-13 13:34:41 -08008359 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8360 if (in_ctxt != NULL) {
8361 list_remove(&in_ctxt->list);
8362 free(in_ctxt);
8363 } else {
8364 ALOGW("%s, input stream already closed", __func__);
8365 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008366 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308367 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008368 return;
8369}
8370
Aalique Grahame22e49102018-12-18 14:23:57 -08008371/* verifies input and output devices and their capabilities.
8372 *
8373 * This verification is required when enabling extended bit-depth or
8374 * sampling rates, as not all qcom products support it.
8375 *
8376 * Suitable for calling only on initialization such as adev_open().
8377 * It fills the audio_device use_case_table[] array.
8378 *
8379 * Has a side-effect that it needs to configure audio routing / devices
8380 * in order to power up the devices and read the device parameters.
8381 * It does not acquire any hw device lock. Should restore the devices
8382 * back to "normal state" upon completion.
8383 */
8384static int adev_verify_devices(struct audio_device *adev)
8385{
8386 /* enumeration is a bit difficult because one really wants to pull
8387 * the use_case, device id, etc from the hidden pcm_device_table[].
8388 * In this case there are the following use cases and device ids.
8389 *
8390 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8391 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8392 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8393 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8394 * [USECASE_AUDIO_RECORD] = {0, 0},
8395 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8396 * [USECASE_VOICE_CALL] = {2, 2},
8397 *
8398 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8399 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8400 */
8401
8402 /* should be the usecases enabled in adev_open_input_stream() */
8403 static const int test_in_usecases[] = {
8404 USECASE_AUDIO_RECORD,
8405 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8406 };
8407 /* should be the usecases enabled in adev_open_output_stream()*/
8408 static const int test_out_usecases[] = {
8409 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8410 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8411 };
8412 static const usecase_type_t usecase_type_by_dir[] = {
8413 PCM_PLAYBACK,
8414 PCM_CAPTURE,
8415 };
8416 static const unsigned flags_by_dir[] = {
8417 PCM_OUT,
8418 PCM_IN,
8419 };
8420
8421 size_t i;
8422 unsigned dir;
8423 const unsigned card_id = adev->snd_card;
8424
8425 for (dir = 0; dir < 2; ++dir) {
8426 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8427 const unsigned flags_dir = flags_by_dir[dir];
8428 const size_t testsize =
8429 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8430 const int *testcases =
8431 dir ? test_in_usecases : test_out_usecases;
8432 const audio_devices_t audio_device =
8433 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8434
8435 for (i = 0; i < testsize; ++i) {
8436 const audio_usecase_t audio_usecase = testcases[i];
8437 int device_id;
8438 struct pcm_params **pparams;
8439 struct stream_out out;
8440 struct stream_in in;
8441 struct audio_usecase uc_info;
8442 int retval;
8443
8444 pparams = &adev->use_case_table[audio_usecase];
8445 pcm_params_free(*pparams); /* can accept null input */
8446 *pparams = NULL;
8447
8448 /* find the device ID for the use case (signed, for error) */
8449 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8450 if (device_id < 0)
8451 continue;
8452
8453 /* prepare structures for device probing */
8454 memset(&uc_info, 0, sizeof(uc_info));
8455 uc_info.id = audio_usecase;
8456 uc_info.type = usecase_type;
8457 if (dir) {
8458 adev->active_input = &in;
8459 memset(&in, 0, sizeof(in));
8460 in.device = audio_device;
8461 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8462 uc_info.stream.in = &in;
8463 } else {
8464 adev->active_input = NULL;
8465 }
8466 memset(&out, 0, sizeof(out));
8467 out.devices = audio_device; /* only field needed in select_devices */
8468 uc_info.stream.out = &out;
8469 uc_info.devices = audio_device;
8470 uc_info.in_snd_device = SND_DEVICE_NONE;
8471 uc_info.out_snd_device = SND_DEVICE_NONE;
8472 list_add_tail(&adev->usecase_list, &uc_info.list);
8473
8474 /* select device - similar to start_(in/out)put_stream() */
8475 retval = select_devices(adev, audio_usecase);
8476 if (retval >= 0) {
8477 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8478#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008479 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008480 if (*pparams) {
8481 ALOGV("%s: (%s) card %d device %d", __func__,
8482 dir ? "input" : "output", card_id, device_id);
8483 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8484 } else {
8485 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8486 }
8487#endif
8488 }
8489
8490 /* deselect device - similar to stop_(in/out)put_stream() */
8491 /* 1. Get and set stream specific mixer controls */
8492 retval = disable_audio_route(adev, &uc_info);
8493 /* 2. Disable the rx device */
8494 retval = disable_snd_device(adev,
8495 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8496 list_remove(&uc_info.list);
8497 }
8498 }
8499 adev->active_input = NULL; /* restore adev state */
8500 return 0;
8501}
8502
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308503int adev_create_audio_patch(struct audio_hw_device *dev,
8504 unsigned int num_sources,
8505 const struct audio_port_config *sources,
8506 unsigned int num_sinks,
8507 const struct audio_port_config *sinks,
8508 audio_patch_handle_t *handle)
8509{
Derek Chenf939fb72018-11-13 13:34:41 -08008510 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308511
Derek Chenf939fb72018-11-13 13:34:41 -08008512 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8513 num_sources,
8514 sources,
8515 num_sinks,
8516 sinks,
8517 handle);
8518 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8519 num_sources,
8520 sources,
8521 num_sinks,
8522 sinks,
8523 handle);
8524 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308525}
8526
8527int adev_release_audio_patch(struct audio_hw_device *dev,
8528 audio_patch_handle_t handle)
8529{
Derek Chenf939fb72018-11-13 13:34:41 -08008530 int ret;
8531
8532 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8533 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8534 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308535}
8536
8537int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8538{
8539 return audio_extn_hw_loopback_get_audio_port(dev, config);
8540}
8541
8542int adev_set_audio_port_config(struct audio_hw_device *dev,
8543 const struct audio_port_config *config)
8544{
8545 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8546}
8547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008548static int adev_dump(const audio_hw_device_t *device __unused,
8549 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008550{
8551 return 0;
8552}
8553
8554static int adev_close(hw_device_t *device)
8555{
Aalique Grahame22e49102018-12-18 14:23:57 -08008556 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008557 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008558
8559 if (!adev)
8560 return 0;
8561
8562 pthread_mutex_lock(&adev_init_lock);
8563
8564 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308565 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008566 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008567 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008568 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008569 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308570 audio_extn_utils_release_streams_cfg_lists(
8571 &adev->streams_output_cfg_list,
8572 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308573 if (audio_extn_qaf_is_enabled())
8574 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008575 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008576 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008577 free(adev->snd_dev_ref_cnt);
8578 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008579 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8580 pcm_params_free(adev->use_case_table[i]);
8581 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008582 if (adev->adm_deinit)
8583 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308584 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008585 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308586 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308587 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008588 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308589 if (adev->device_cfg_params) {
8590 free(adev->device_cfg_params);
8591 adev->device_cfg_params = NULL;
8592 }
Derek Chend2530072014-11-24 12:39:14 -08008593 if(adev->ext_hw_plugin)
8594 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008595 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008596 free(device);
8597 adev = NULL;
8598 }
8599 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308600 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008601 return 0;
8602}
8603
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008604/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8605 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8606 * just that it _might_ work.
8607 */
8608static int period_size_is_plausible_for_low_latency(int period_size)
8609{
8610 switch (period_size) {
8611 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008612 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008613 case 240:
8614 case 320:
8615 case 480:
8616 return 1;
8617 default:
8618 return 0;
8619 }
8620}
8621
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308622static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8623{
8624 bool is_snd_card_status = false;
8625 bool is_ext_device_status = false;
8626 char value[32];
8627 int card = -1;
8628 card_status_t status;
8629
8630 if (cookie != adev || !parms)
8631 return;
8632
8633 if (!parse_snd_card_status(parms, &card, &status)) {
8634 is_snd_card_status = true;
8635 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8636 is_ext_device_status = true;
8637 } else {
8638 // not a valid event
8639 return;
8640 }
8641
8642 pthread_mutex_lock(&adev->lock);
8643 if (card == adev->snd_card || is_ext_device_status) {
8644 if (is_snd_card_status && adev->card_status != status) {
8645 adev->card_status = status;
8646 platform_snd_card_update(adev->platform, status);
8647 audio_extn_fm_set_parameters(adev, parms);
8648 } else if (is_ext_device_status) {
8649 platform_set_parameters(adev->platform, parms);
8650 }
8651 }
8652 pthread_mutex_unlock(&adev->lock);
8653 return;
8654}
8655
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308656/* out and adev lock held */
8657static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8658{
8659 struct audio_usecase *uc_info;
8660 float left_p;
8661 float right_p;
8662 audio_devices_t devices;
8663
8664 uc_info = get_usecase_from_list(adev, out->usecase);
8665 if (uc_info == NULL) {
8666 ALOGE("%s: Could not find the usecase (%d) in the list",
8667 __func__, out->usecase);
8668 return -EINVAL;
8669 }
8670
8671 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8672 out->usecase, use_case_table[out->usecase]);
8673
8674 if (restore) {
8675 // restore A2DP device for active usecases and unmute if required
8676 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8677 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8678 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8679 select_devices(adev, uc_info->id);
8680 pthread_mutex_lock(&out->compr_mute_lock);
8681 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8682 (out->a2dp_compress_mute)) {
8683 out->a2dp_compress_mute = false;
8684 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8685 }
8686 pthread_mutex_unlock(&out->compr_mute_lock);
8687 }
8688 } else {
8689 // mute compress stream if suspended
8690 pthread_mutex_lock(&out->compr_mute_lock);
8691 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8692 (!out->a2dp_compress_mute)) {
8693 if (!out->standby) {
8694 ALOGD("%s: selecting speaker and muting stream", __func__);
8695 devices = out->devices;
8696 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8697 left_p = out->volume_l;
8698 right_p = out->volume_r;
8699 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8700 compress_pause(out->compr);
8701 out_set_compr_volume(&out->stream, (float)0, (float)0);
8702 out->a2dp_compress_mute = true;
8703 select_devices(adev, out->usecase);
8704 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8705 compress_resume(out->compr);
8706 out->devices = devices;
8707 out->volume_l = left_p;
8708 out->volume_r = right_p;
8709 }
8710 }
8711 pthread_mutex_unlock(&out->compr_mute_lock);
8712 }
8713 ALOGV("%s: exit", __func__);
8714 return 0;
8715}
8716
8717int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8718{
8719 int ret = 0;
8720
8721 lock_output_stream(out);
8722 pthread_mutex_lock(&adev->lock);
8723
8724 ret = check_a2dp_restore_l(adev, out, restore);
8725
8726 pthread_mutex_unlock(&adev->lock);
8727 pthread_mutex_unlock(&out->lock);
8728 return ret;
8729}
8730
Haynes Mathew George01156f92018-04-13 15:29:54 -07008731void adev_on_battery_status_changed(bool charging)
8732{
8733 pthread_mutex_lock(&adev->lock);
8734 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8735 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008736 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008737 pthread_mutex_unlock(&adev->lock);
8738}
8739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008740static int adev_open(const hw_module_t *module, const char *name,
8741 hw_device_t **device)
8742{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308743 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008744 char value[PROPERTY_VALUE_MAX] = {0};
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308745
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008746 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008747 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8748
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008749 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008750 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008751 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008752 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008753 ALOGD("%s: returning existing instance of adev", __func__);
8754 ALOGD("%s: exit", __func__);
8755 pthread_mutex_unlock(&adev_init_lock);
8756 return 0;
8757 }
8758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008759 adev = calloc(1, sizeof(struct audio_device));
8760
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008761 if (!adev) {
8762 pthread_mutex_unlock(&adev_init_lock);
8763 return -ENOMEM;
8764 }
8765
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008766 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8767
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008768 // register audio ext hidl at the earliest
8769 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308770#ifdef DYNAMIC_LOG_ENABLED
8771 register_for_dynamic_logging("hal");
8772#endif
8773
Derek Chenf939fb72018-11-13 13:34:41 -08008774 /* default audio HAL major version */
8775 uint32_t maj_version = 2;
8776 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8777 maj_version = atoi(value);
8778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008780 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008781 adev->device.common.module = (struct hw_module_t *)module;
8782 adev->device.common.close = adev_close;
8783
8784 adev->device.init_check = adev_init_check;
8785 adev->device.set_voice_volume = adev_set_voice_volume;
8786 adev->device.set_master_volume = adev_set_master_volume;
8787 adev->device.get_master_volume = adev_get_master_volume;
8788 adev->device.set_master_mute = adev_set_master_mute;
8789 adev->device.get_master_mute = adev_get_master_mute;
8790 adev->device.set_mode = adev_set_mode;
8791 adev->device.set_mic_mute = adev_set_mic_mute;
8792 adev->device.get_mic_mute = adev_get_mic_mute;
8793 adev->device.set_parameters = adev_set_parameters;
8794 adev->device.get_parameters = adev_get_parameters;
8795 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8796 adev->device.open_output_stream = adev_open_output_stream;
8797 adev->device.close_output_stream = adev_close_output_stream;
8798 adev->device.open_input_stream = adev_open_input_stream;
8799 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308800 adev->device.create_audio_patch = adev_create_audio_patch;
8801 adev->device.release_audio_patch = adev_release_audio_patch;
8802 adev->device.get_audio_port = adev_get_audio_port;
8803 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008804 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308805 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008806
8807 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008808 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008809 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008810 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008811 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008812 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008813 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008814 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308815 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008816 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008817 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008818 /* Init audio feature manager */
8819 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008820 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008821 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08008822 list_init(&adev->active_inputs_list);
8823 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008824 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008825 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308826 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308827 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308828 adev->perf_lock_opts[0] = 0x101;
8829 adev->perf_lock_opts[1] = 0x20E;
8830 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008831 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07008832 adev->enable_hfp = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008834 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008835 adev->platform = platform_init(adev);
8836 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008837 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008838 free(adev->snd_dev_ref_cnt);
8839 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008840 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008841 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8842 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008843 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008844 return -EINVAL;
8845 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008846
Aalique Grahame22e49102018-12-18 14:23:57 -08008847 adev->extspk = audio_extn_extspk_init(adev);
8848
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308849 if (audio_extn_qaf_is_enabled()) {
8850 ret = audio_extn_qaf_init(adev);
8851 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008852 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308853 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008854 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308855 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8856 *device = NULL;
8857 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308858 return ret;
8859 }
8860
8861 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8862 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8863 }
8864
Derek Chenae7b0342019-02-08 15:17:04 -08008865 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08008866 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8867
Eric Laurentc4aef752013-09-12 17:45:53 -07008868 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8869 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8870 if (adev->visualizer_lib == NULL) {
8871 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8872 } else {
8873 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8874 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008875 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008876 "visualizer_hal_start_output");
8877 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008878 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008879 "visualizer_hal_stop_output");
8880 }
8881 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308882 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008883 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008884 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008885 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308886 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008887 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008888
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008889 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8890 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8891 if (adev->offload_effects_lib == NULL) {
8892 ALOGE("%s: DLOPEN failed for %s", __func__,
8893 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8894 } else {
8895 ALOGV("%s: DLOPEN successful for %s", __func__,
8896 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8897 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308898 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008899 "offload_effects_bundle_hal_start_output");
8900 adev->offload_effects_stop_output =
8901 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8902 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008903 adev->offload_effects_set_hpx_state =
8904 (int (*)(bool))dlsym(adev->offload_effects_lib,
8905 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308906 adev->offload_effects_get_parameters =
8907 (void (*)(struct str_parms *, struct str_parms *))
8908 dlsym(adev->offload_effects_lib,
8909 "offload_effects_bundle_get_parameters");
8910 adev->offload_effects_set_parameters =
8911 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8912 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008913 }
8914 }
8915
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008916 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8917 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8918 if (adev->adm_lib == NULL) {
8919 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8920 } else {
8921 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8922 adev->adm_init = (adm_init_t)
8923 dlsym(adev->adm_lib, "adm_init");
8924 adev->adm_deinit = (adm_deinit_t)
8925 dlsym(adev->adm_lib, "adm_deinit");
8926 adev->adm_register_input_stream = (adm_register_input_stream_t)
8927 dlsym(adev->adm_lib, "adm_register_input_stream");
8928 adev->adm_register_output_stream = (adm_register_output_stream_t)
8929 dlsym(adev->adm_lib, "adm_register_output_stream");
8930 adev->adm_deregister_stream = (adm_deregister_stream_t)
8931 dlsym(adev->adm_lib, "adm_deregister_stream");
8932 adev->adm_request_focus = (adm_request_focus_t)
8933 dlsym(adev->adm_lib, "adm_request_focus");
8934 adev->adm_abandon_focus = (adm_abandon_focus_t)
8935 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008936 adev->adm_set_config = (adm_set_config_t)
8937 dlsym(adev->adm_lib, "adm_set_config");
8938 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8939 dlsym(adev->adm_lib, "adm_request_focus_v2");
8940 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8941 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8942 adev->adm_on_routing_change = (adm_on_routing_change_t)
8943 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008944 }
8945 }
8946
Aalique Grahame22e49102018-12-18 14:23:57 -08008947 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008948 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008949 //initialize this to false for now,
8950 //this will be set to true through set param
8951 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008952
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008953 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008954 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08008955
8956 if (k_enable_extended_precision)
8957 adev_verify_devices(adev);
8958
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008959 adev->dsp_bit_width_enforce_mode =
8960 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008961
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308962 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8963 &adev->streams_output_cfg_list,
8964 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008965
Kiran Kandi910e1862013-10-29 13:29:42 -07008966 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008967
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008968 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08008969 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
8970 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008971 trial = atoi(value);
8972 if (period_size_is_plausible_for_low_latency(trial)) {
8973 pcm_config_low_latency.period_size = trial;
8974 pcm_config_low_latency.start_threshold = trial / 4;
8975 pcm_config_low_latency.avail_min = trial / 4;
8976 configured_low_latency_capture_period_size = trial;
8977 }
8978 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008979 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
8980 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008981 trial = atoi(value);
8982 if (period_size_is_plausible_for_low_latency(trial)) {
8983 configured_low_latency_capture_period_size = trial;
8984 }
8985 }
8986
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008987 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8988
Aalique Grahame22e49102018-12-18 14:23:57 -08008989 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
8990 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008991 af_period_multiplier = atoi(value);
8992 if (af_period_multiplier < 0)
8993 af_period_multiplier = 2;
8994 else if (af_period_multiplier > 4)
8995 af_period_multiplier = 4;
8996
8997 ALOGV("new period_multiplier = %d", af_period_multiplier);
8998 }
8999
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009000 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009001
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009002 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009003 pthread_mutex_unlock(&adev_init_lock);
9004
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009005 if (adev->adm_init)
9006 adev->adm_data = adev->adm_init();
9007
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309008 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309009 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009010 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309011
9012 audio_extn_snd_mon_init();
9013 pthread_mutex_lock(&adev->lock);
9014 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9015 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009016 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9017 /*
9018 * if the battery state callback happens before charging can be queried,
9019 * it will be guarded with the adev->lock held in the cb function and so
9020 * the callback value will reflect the latest state
9021 */
9022 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309023 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009024 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
9025 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309026 /* Allocate memory for Device config params */
9027 adev->device_cfg_params = (struct audio_device_config_param*)
9028 calloc(platform_get_max_codec_backend(),
9029 sizeof(struct audio_device_config_param));
9030 if (adev->device_cfg_params == NULL)
9031 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309032
Eric Laurent994a6932013-07-17 11:51:42 -07009033 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009034 return 0;
9035}
9036
9037static struct hw_module_methods_t hal_module_methods = {
9038 .open = adev_open,
9039};
9040
9041struct audio_module HAL_MODULE_INFO_SYM = {
9042 .common = {
9043 .tag = HARDWARE_MODULE_TAG,
9044 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9045 .hal_api_version = HARDWARE_HAL_API_VERSION,
9046 .id = AUDIO_HARDWARE_MODULE_ID,
9047 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009048 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009049 .methods = &hal_module_methods,
9050 },
9051};