blob: ab99b4772ef93488bca4dc9d15df326b092ea68f [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);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301110 if (usecase->stream.out != NULL)
1111 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 ALOGV("%s: exit", __func__);
1113 return 0;
1114}
1115
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001116int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001117 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301119 int i, num_devices = 0;
1120 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001121 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1122
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001123 if (snd_device < SND_DEVICE_MIN ||
1124 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001125 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001126 return -EINVAL;
1127 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128
1129 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001130
1131 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1132 ALOGE("%s: Invalid sound device returned", __func__);
1133 return -EINVAL;
1134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001136 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001137 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 return 0;
1139 }
1140
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301141
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001142 if (audio_extn_spkr_prot_is_enabled())
1143 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001144
Aalique Grahame22e49102018-12-18 14:23:57 -08001145 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1146
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001147 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1148 audio_extn_spkr_prot_is_enabled()) {
1149 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001150 adev->snd_dev_ref_cnt[snd_device]--;
1151 return -EINVAL;
1152 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001153 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001154 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001155 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001156 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001157 return -EINVAL;
1158 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001159 } else if (platform_split_snd_device(adev->platform,
1160 snd_device,
1161 &num_devices,
1162 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301163 for (i = 0; i < num_devices; i++) {
1164 enable_snd_device(adev, new_snd_devices[i]);
1165 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001166 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001167 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001168 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301169
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301170
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301171 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1172 (audio_extn_a2dp_start_playback() < 0)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02001173 ALOGE(" fail to configure A2dp Source control path ");
1174 return -EINVAL;
1175 }
1176
1177 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1178 (audio_extn_a2dp_start_capture() < 0)) {
1179 ALOGE(" fail to configure A2dp Sink control path ");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301180 return -EINVAL;
1181 }
1182
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001183 /* due to the possibility of calibration overwrite between listen
1184 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001185 audio_extn_sound_trigger_update_device_status(snd_device,
1186 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301187 audio_extn_listen_update_device_status(snd_device,
1188 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001189 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001190 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001191 audio_extn_sound_trigger_update_device_status(snd_device,
1192 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301193 audio_extn_listen_update_device_status(snd_device,
1194 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001195 return -EINVAL;
1196 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001197 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001198 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301199
1200 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1201 !adev->native_playback_enabled &&
1202 audio_is_true_native_stream_active(adev)) {
1203 ALOGD("%s: %d: napb: enabling native mode in hardware",
1204 __func__, __LINE__);
1205 audio_route_apply_and_update_path(adev->audio_route,
1206 "true-native-mode");
1207 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301208 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301209 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1210 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001211 (audio_extn_ffv_get_stream() == adev->active_input)) {
1212 ALOGD("%s: init ec ref loopback", __func__);
1213 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216 return 0;
1217}
1218
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001219int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001220 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301222 int i, num_devices = 0;
1223 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001224 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1225
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001226 if (snd_device < SND_DEVICE_MIN ||
1227 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001228 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001229 return -EINVAL;
1230 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1232 ALOGE("%s: device ref cnt is already 0", __func__);
1233 return -EINVAL;
1234 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001235
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001237
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001238 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1239 ALOGE("%s: Invalid sound device returned", __func__);
1240 return -EINVAL;
1241 }
1242
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001244 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301245
Aalique Grahame22e49102018-12-18 14:23:57 -08001246 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1247
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001248 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1249 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001250 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001251
1252 // when speaker device is disabled, reset swap.
1253 // will be renabled on usecase start
1254 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001255 } else if (platform_split_snd_device(adev->platform,
1256 snd_device,
1257 &num_devices,
1258 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301259 for (i = 0; i < num_devices; i++) {
1260 disable_snd_device(adev, new_snd_devices[i]);
1261 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001262 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001263 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001264 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001265 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001266
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301267 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1268 audio_extn_a2dp_stop_playback();
1269
Florian Pfister1a84f312018-07-19 14:38:18 +02001270 if (SND_DEVICE_IN_BT_A2DP == snd_device)
1271 audio_extn_a2dp_stop_capture();
1272
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001273 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301274 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301275 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1276 adev->native_playback_enabled) {
1277 ALOGD("%s: %d: napb: disabling native mode in hardware",
1278 __func__, __LINE__);
1279 audio_route_reset_and_update_path(adev->audio_route,
1280 "true-native-mode");
1281 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301282 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1283 adev->asrc_mode_enabled) {
1284 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301285 disable_asrc_mode(adev);
1286 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301287 }
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301288 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1289 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001290 (audio_extn_ffv_get_stream() == adev->active_input)) {
1291 ALOGD("%s: deinit ec ref loopback", __func__);
1292 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1293 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001294 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001295 audio_extn_sound_trigger_update_device_status(snd_device,
1296 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301297 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001298 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 return 0;
1302}
1303
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001304/*
1305 legend:
1306 uc - existing usecase
1307 new_uc - new usecase
1308 d1, d11, d2 - SND_DEVICE enums
1309 a1, a2 - corresponding ANDROID device enums
1310 B1, B2 - backend strings
1311
1312case 1
1313 uc->dev d1 (a1) B1
1314 new_uc->dev d1 (a1), d2 (a2) B1, B2
1315
1316 resolution: disable and enable uc->dev on d1
1317
1318case 2
1319 uc->dev d1 (a1) B1
1320 new_uc->dev d11 (a1) B1
1321
1322 resolution: need to switch uc since d1 and d11 are related
1323 (e.g. speaker and voice-speaker)
1324 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1325
1326case 3
1327 uc->dev d1 (a1) B1
1328 new_uc->dev d2 (a2) B2
1329
1330 resolution: no need to switch uc
1331
1332case 4
1333 uc->dev d1 (a1) B1
1334 new_uc->dev d2 (a2) B1
1335
1336 resolution: disable enable uc-dev on d2 since backends match
1337 we cannot enable two streams on two different devices if they
1338 share the same backend. e.g. if offload is on speaker device using
1339 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1340 using the same backend, offload must also be switched to voice-handset.
1341
1342case 5
1343 uc->dev d1 (a1) B1
1344 new_uc->dev d1 (a1), d2 (a2) B1
1345
1346 resolution: disable enable uc-dev on d2 since backends match
1347 we cannot enable two streams on two different devices if they
1348 share the same backend.
1349
1350case 6
1351 uc->dev d1 (a1) B1
1352 new_uc->dev d2 (a1) B2
1353
1354 resolution: no need to switch
1355
1356case 7
1357 uc->dev d1 (a1), d2 (a2) B1, B2
1358 new_uc->dev d1 (a1) B1
1359
1360 resolution: no need to switch
1361
Zhou Song4ba65882018-07-09 14:48:07 +08001362case 8
1363 uc->dev d1 (a1) B1
1364 new_uc->dev d11 (a1), d2 (a2) B1, B2
1365 resolution: compared to case 1, for this case, d1 and d11 are related
1366 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001367*/
1368static snd_device_t derive_playback_snd_device(void * platform,
1369 struct audio_usecase *uc,
1370 struct audio_usecase *new_uc,
1371 snd_device_t new_snd_device)
1372{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301373 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001374
1375 snd_device_t d1 = uc->out_snd_device;
1376 snd_device_t d2 = new_snd_device;
1377
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301378 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301379 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301380 a1 = uc->stream.inout->out_config.devices;
1381 a2 = new_uc->stream.inout->out_config.devices;
1382 break;
1383 default :
1384 a1 = uc->stream.out->devices;
1385 a2 = new_uc->stream.out->devices;
1386 break;
1387 }
1388
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001389 // Treat as a special case when a1 and a2 are not disjoint
1390 if ((a1 != a2) && (a1 & a2)) {
1391 snd_device_t d3[2];
1392 int num_devices = 0;
1393 int ret = platform_split_snd_device(platform,
1394 popcount(a1) > 1 ? d1 : d2,
1395 &num_devices,
1396 d3);
1397 if (ret < 0) {
1398 if (ret != -ENOSYS) {
1399 ALOGW("%s failed to split snd_device %d",
1400 __func__,
1401 popcount(a1) > 1 ? d1 : d2);
1402 }
1403 goto end;
1404 }
1405
1406 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1407 // But if it does happen, we need to give priority to d2 if
1408 // the combo devices active on the existing usecase share a backend.
1409 // This is because we cannot have a usecase active on a combo device
1410 // and a new usecase requests one device in this combo pair.
1411 if (platform_check_backends_match(d3[0], d3[1])) {
1412 return d2; // case 5
1413 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001414 // check if d1 is related to any of d3's
1415 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001416 return d1; // case 1
1417 else
1418 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001419 }
1420 } else {
1421 if (platform_check_backends_match(d1, d2)) {
1422 return d2; // case 2, 4
1423 } else {
1424 return d1; // case 6, 3
1425 }
1426 }
1427
1428end:
1429 return d2; // return whatever was calculated before.
1430}
1431
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301433 struct audio_usecase *uc_info,
1434 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435{
1436 struct listnode *node;
1437 struct audio_usecase *usecase;
1438 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301439 snd_device_t uc_derive_snd_device;
1440 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001442 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301443 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 /*
1445 * This function is to make sure that all the usecases that are active on
1446 * the hardware codec backend are always routed to any one device that is
1447 * handled by the hardware codec.
1448 * For example, if low-latency and deep-buffer usecases are currently active
1449 * on speaker and out_set_parameters(headset) is received on low-latency
1450 * output, then we have to make sure deep-buffer is also switched to headset,
1451 * because of the limitation that both the devices cannot be enabled
1452 * at the same time as they share the same backend.
1453 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001454 /*
1455 * This call is to check if we need to force routing for a particular stream
1456 * If there is a backend configuration change for the device when a
1457 * new stream starts, then ADM needs to be closed and re-opened with the new
1458 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001459 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001460 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001461 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1462 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301463 /* For a2dp device reconfigure all active sessions
1464 * with new AFE encoder format based on a2dp state
1465 */
1466 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1467 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1468 audio_extn_a2dp_is_force_device_switch()) {
1469 force_routing = true;
1470 force_restart_session = true;
1471 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301472 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1473
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001475 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001476 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1478 switch_device[i] = false;
1479
1480 list_for_each(node, &adev->usecase_list) {
1481 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001482
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301483 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1484 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301485 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 platform_get_snd_device_name(usecase->out_snd_device),
1487 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301488 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1489 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1490 usecase, uc_info, snd_device);
1491 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1492 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1493 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1494 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001495 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301496 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1497 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1498 ((force_restart_session) ||
1499 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301500 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1501 __func__, use_case_table[usecase->id],
1502 platform_get_snd_device_name(usecase->out_snd_device));
1503 disable_audio_route(adev, usecase);
1504 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301505 /* Enable existing usecase on derived playback device */
1506 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301507 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301508 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001509 }
1510 }
1511
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301512 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1513 num_uc_to_switch);
1514
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001516 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301518 /* Make sure the previous devices to be disabled first and then enable the
1519 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 list_for_each(node, &adev->usecase_list) {
1521 usecase = node_to_item(node, struct audio_usecase, list);
1522 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001523 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524 }
1525 }
1526
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001527 list_for_each(node, &adev->usecase_list) {
1528 usecase = node_to_item(node, struct audio_usecase, list);
1529 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301530 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001531 }
1532 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001533
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 /* Re-route all the usecases on the shared backend other than the
1535 specified usecase to new snd devices */
1536 list_for_each(node, &adev->usecase_list) {
1537 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301538 /* Update the out_snd_device only before enabling the audio route */
1539 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301540 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301541 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301542 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301543 use_case_table[usecase->id],
1544 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001545 /* Update voc calibration before enabling VoIP route */
1546 if (usecase->type == VOIP_CALL)
1547 status = platform_switch_voice_call_device_post(adev->platform,
1548 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001549 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301550 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001551 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1552 out_set_voip_volume(&usecase->stream.out->stream,
1553 usecase->stream.out->volume_l,
1554 usecase->stream.out->volume_r);
1555 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301556 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 }
1558 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 }
1560}
1561
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301562static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001563 struct audio_usecase *uc_info,
1564 snd_device_t snd_device)
1565{
1566 struct listnode *node;
1567 struct audio_usecase *usecase;
1568 bool switch_device[AUDIO_USECASE_MAX];
1569 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301570 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001571 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001572
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301573 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1574 snd_device);
1575 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301576
1577 /*
1578 * Make sure out devices is checked against out codec backend device and
1579 * also in devices against in codec backend. Checking out device against in
1580 * codec backend or vice versa causes issues.
1581 */
1582 if (uc_info->type == PCM_CAPTURE)
1583 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001584 /*
1585 * This function is to make sure that all the active capture usecases
1586 * are always routed to the same input sound device.
1587 * For example, if audio-record and voice-call usecases are currently
1588 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1589 * is received for voice call then we have to make sure that audio-record
1590 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1591 * because of the limitation that two devices cannot be enabled
1592 * at the same time if they share the same backend.
1593 */
1594 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1595 switch_device[i] = false;
1596
1597 list_for_each(node, &adev->usecase_list) {
1598 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301599 /*
1600 * TODO: Enhance below condition to handle BT sco/USB multi recording
1601 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001602 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001603 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301604 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301605 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301606 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301607 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001608 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001609 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1610 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001611 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001612 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001613 switch_device[usecase->id] = true;
1614 num_uc_to_switch++;
1615 }
1616 }
1617
1618 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001619 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001620
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301621 /* Make sure the previous devices to be disabled first and then enable the
1622 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001623 list_for_each(node, &adev->usecase_list) {
1624 usecase = node_to_item(node, struct audio_usecase, list);
1625 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001626 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001627 }
1628 }
1629
1630 list_for_each(node, &adev->usecase_list) {
1631 usecase = node_to_item(node, struct audio_usecase, list);
1632 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001633 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001634 }
1635 }
1636
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001637 /* Re-route all the usecases on the shared backend other than the
1638 specified usecase to new snd devices */
1639 list_for_each(node, &adev->usecase_list) {
1640 usecase = node_to_item(node, struct audio_usecase, list);
1641 /* Update the in_snd_device only before enabling the audio route */
1642 if (switch_device[usecase->id] ) {
1643 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001644 if (usecase->type != VOICE_CALL) {
1645 /* Update voc calibration before enabling VoIP route */
1646 if (usecase->type == VOIP_CALL)
1647 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001648 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001649 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301650 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001651 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001652 }
1653 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001654 }
1655}
1656
Mingming Yin3a941d42016-02-17 18:08:05 -08001657static void reset_hdmi_sink_caps(struct stream_out *out) {
1658 int i = 0;
1659
1660 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1661 out->supported_channel_masks[i] = 0;
1662 }
1663 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1664 out->supported_formats[i] = 0;
1665 }
1666 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1667 out->supported_sample_rates[i] = 0;
1668 }
1669}
1670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001672static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673{
Mingming Yin3a941d42016-02-17 18:08:05 -08001674 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001675 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676
Mingming Yin3a941d42016-02-17 18:08:05 -08001677 reset_hdmi_sink_caps(out);
1678
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001679 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001680 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001681 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001682 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001683 }
1684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001687 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001688 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001689 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1690 case 6:
1691 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1692 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1693 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1694 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1695 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1696 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 break;
1698 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001699 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001700 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 break;
1702 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001703
1704 // check channel format caps
1705 i = 0;
1706 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1707 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1708 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1709 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1710 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1711 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1712 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1713 }
1714
Ben Romberger1aaaf862017-04-06 17:49:46 -07001715 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1716 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1717 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1718 }
1719
Mingming Yin3a941d42016-02-17 18:08:05 -08001720 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1721 ALOGV(":%s HDMI supports DTS format", __func__);
1722 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1723 }
1724
1725 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1726 ALOGV(":%s HDMI supports DTS HD format", __func__);
1727 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1728 }
1729
Naresh Tanniru928f0862017-04-07 16:44:23 -07001730 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1731 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1732 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1733 }
1734
Mingming Yin3a941d42016-02-17 18:08:05 -08001735
1736 // check sample rate caps
1737 i = 0;
1738 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1739 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1740 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1741 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1742 }
1743 }
1744
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001745 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746}
1747
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001748static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1749 uint32_t *supported_sample_rates __unused,
1750 uint32_t max_rates __unused)
1751{
1752 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1753 supported_sample_rates,
1754 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301755 ssize_t i = 0;
1756
1757 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001758 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1759 supported_sample_rates[i]);
1760 }
1761 return count;
1762}
1763
1764static inline int read_usb_sup_channel_masks(bool is_playback,
1765 audio_channel_mask_t *supported_channel_masks,
1766 uint32_t max_masks)
1767{
1768 int channels = audio_extn_usb_get_max_channels(is_playback);
1769 int channel_count;
1770 uint32_t num_masks = 0;
1771 if (channels > MAX_HIFI_CHANNEL_COUNT)
1772 channels = MAX_HIFI_CHANNEL_COUNT;
1773
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301774 channel_count = DEFAULT_CHANNEL_COUNT;
1775
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001776 if (is_playback) {
1777 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001778 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301779 // above 2 but we want indexed masks here.
1780 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001781 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001782 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1783 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301784 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001785 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301786
1787 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1788 (num_masks < max_masks)); channel_count--) {
1789 supported_channel_masks[num_masks++] =
1790 audio_channel_mask_for_index_assignment_from_count(channel_count);
1791 }
1792
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001793 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1794 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1795 return num_masks;
1796}
1797
1798static inline int read_usb_sup_formats(bool is_playback __unused,
1799 audio_format_t *supported_formats,
1800 uint32_t max_formats __unused)
1801{
1802 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1803 switch (bitwidth) {
1804 case 24:
1805 // XXX : usb.c returns 24 for s24 and s24_le?
1806 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1807 break;
1808 case 32:
1809 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1810 break;
1811 case 16:
1812 default :
1813 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1814 break;
1815 }
1816 ALOGV("%s: %s supported format %d", __func__,
1817 is_playback ? "P" : "C", bitwidth);
1818 return 1;
1819}
1820
1821static inline int read_usb_sup_params_and_compare(bool is_playback,
1822 audio_format_t *format,
1823 audio_format_t *supported_formats,
1824 uint32_t max_formats,
1825 audio_channel_mask_t *mask,
1826 audio_channel_mask_t *supported_channel_masks,
1827 uint32_t max_masks,
1828 uint32_t *rate,
1829 uint32_t *supported_sample_rates,
1830 uint32_t max_rates) {
1831 int ret = 0;
1832 int num_formats;
1833 int num_masks;
1834 int num_rates;
1835 int i;
1836
1837 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1838 max_formats);
1839 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1840 max_masks);
1841
1842 num_rates = read_usb_sup_sample_rates(is_playback,
1843 supported_sample_rates, max_rates);
1844
1845#define LUT(table, len, what, dflt) \
1846 for (i=0; i<len && (table[i] != what); i++); \
1847 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1848
1849 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1850 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1851 LUT(supported_sample_rates, num_rates, *rate, 0);
1852
1853#undef LUT
1854 return ret < 0 ? -EINVAL : 0; // HACK TBD
1855}
1856
Alexy Josephb1379942016-01-29 15:49:38 -08001857audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001858 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001859{
1860 struct audio_usecase *usecase;
1861 struct listnode *node;
1862
1863 list_for_each(node, &adev->usecase_list) {
1864 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001865 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001866 ALOGV("%s: usecase id %d", __func__, usecase->id);
1867 return usecase->id;
1868 }
1869 }
1870 return USECASE_INVALID;
1871}
1872
Alexy Josephb1379942016-01-29 15:49:38 -08001873struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001874 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875{
1876 struct audio_usecase *usecase;
1877 struct listnode *node;
1878
1879 list_for_each(node, &adev->usecase_list) {
1880 usecase = node_to_item(node, struct audio_usecase, list);
1881 if (usecase->id == uc_id)
1882 return usecase;
1883 }
1884 return NULL;
1885}
1886
Dhananjay Kumard4833242016-10-06 22:09:12 +05301887struct stream_in *get_next_active_input(const struct audio_device *adev)
1888{
1889 struct audio_usecase *usecase;
1890 struct listnode *node;
1891
1892 list_for_each_reverse(node, &adev->usecase_list) {
1893 usecase = node_to_item(node, struct audio_usecase, list);
1894 if (usecase->type == PCM_CAPTURE)
1895 return usecase->stream.in;
1896 }
1897 return NULL;
1898}
1899
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301900/*
1901 * is a true native playback active
1902 */
1903bool audio_is_true_native_stream_active(struct audio_device *adev)
1904{
1905 bool active = false;
1906 int i = 0;
1907 struct listnode *node;
1908
1909 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1910 ALOGV("%s:napb: not in true mode or non hdphones device",
1911 __func__);
1912 active = false;
1913 goto exit;
1914 }
1915
1916 list_for_each(node, &adev->usecase_list) {
1917 struct audio_usecase *uc;
1918 uc = node_to_item(node, struct audio_usecase, list);
1919 struct stream_out *curr_out =
1920 (struct stream_out*) uc->stream.out;
1921
1922 if (curr_out && PCM_PLAYBACK == uc->type) {
1923 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1924 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1925 uc->id, curr_out->sample_rate,
1926 curr_out->bit_width,
1927 platform_get_snd_device_name(uc->out_snd_device));
1928
1929 if (is_offload_usecase(uc->id) &&
1930 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1931 active = true;
1932 ALOGD("%s:napb:native stream detected", __func__);
1933 }
1934 }
1935 }
1936exit:
1937 return active;
1938}
1939
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001940uint32_t adev_get_dsp_bit_width_enforce_mode()
1941{
1942 if (adev == NULL) {
1943 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1944 return 0;
1945 }
1946 return adev->dsp_bit_width_enforce_mode;
1947}
1948
1949static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1950{
1951 char value[PROPERTY_VALUE_MAX];
1952 int trial;
1953 uint32_t dsp_bit_width_enforce_mode = 0;
1954
1955 if (!mixer) {
1956 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1957 __func__);
1958 return 0;
1959 }
1960
1961 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1962 value, NULL) > 0) {
1963 trial = atoi(value);
1964 switch (trial) {
1965 case 16:
1966 dsp_bit_width_enforce_mode = 16;
1967 break;
1968 case 24:
1969 dsp_bit_width_enforce_mode = 24;
1970 break;
1971 case 32:
1972 dsp_bit_width_enforce_mode = 32;
1973 break;
1974 default:
1975 dsp_bit_width_enforce_mode = 0;
1976 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1977 break;
1978 }
1979 }
1980
1981 return dsp_bit_width_enforce_mode;
1982}
1983
1984static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1985 uint32_t enforce_mode,
1986 bool enable)
1987{
1988 struct mixer_ctl *ctl = NULL;
1989 const char *mixer_ctl_name = "ASM Bit Width";
1990 uint32_t asm_bit_width_mode = 0;
1991
1992 if (enforce_mode == 0) {
1993 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1994 return;
1995 }
1996
1997 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1998 if (!ctl) {
1999 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2000 __func__, mixer_ctl_name);
2001 return;
2002 }
2003
2004 if (enable)
2005 asm_bit_width_mode = enforce_mode;
2006 else
2007 asm_bit_width_mode = 0;
2008
2009 ALOGV("%s DSP bit width feature status is %d width=%d",
2010 __func__, enable, asm_bit_width_mode);
2011 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2012 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2013 asm_bit_width_mode);
2014
2015 return;
2016}
2017
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302018/*
2019 * if native DSD playback active
2020 */
2021bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2022{
2023 bool active = false;
2024 struct listnode *node = NULL;
2025 struct audio_usecase *uc = NULL;
2026 struct stream_out *curr_out = NULL;
2027
2028 list_for_each(node, &adev->usecase_list) {
2029 uc = node_to_item(node, struct audio_usecase, list);
2030 curr_out = (struct stream_out*) uc->stream.out;
2031
2032 if (curr_out && PCM_PLAYBACK == uc->type &&
2033 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2034 active = true;
2035 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302036 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302037 }
2038 }
2039 return active;
2040}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302041
2042static bool force_device_switch(struct audio_usecase *usecase)
2043{
2044 bool ret = false;
2045 bool is_it_true_mode = false;
2046
Zhou Song30f2c3e2018-02-08 14:02:15 +08002047 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302048 usecase->type == TRANSCODE_LOOPBACK_RX ||
2049 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002050 return false;
2051 }
2052
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002053 if(usecase->stream.out == NULL) {
2054 ALOGE("%s: stream.out is NULL", __func__);
2055 return false;
2056 }
2057
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302058 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002059 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2060 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2061 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302062 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2063 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2064 (!is_it_true_mode && adev->native_playback_enabled)){
2065 ret = true;
2066 ALOGD("napb: time to toggle native mode");
2067 }
2068 }
2069
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302070 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302071 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2072 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002073 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302074 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302075 ALOGD("Force a2dp device switch to update new encoder config");
2076 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002077 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302078
Florian Pfister1a84f312018-07-19 14:38:18 +02002079 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302080 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2081 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002082 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302083 return ret;
2084}
2085
Aalique Grahame22e49102018-12-18 14:23:57 -08002086static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2087{
2088 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2089}
2090
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302091bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2092{
2093 bool ret=false;
2094 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2095 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2096 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2097 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2098 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2099 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2100 ret = true;
2101
2102 return ret;
2103}
2104
2105bool is_a2dp_device(snd_device_t out_snd_device)
2106{
2107 bool ret=false;
2108 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2109 ret = true;
2110
2111 return ret;
2112}
2113
2114bool is_bt_soc_on(struct audio_device *adev)
2115{
2116 struct mixer_ctl *ctl;
2117 char *mixer_ctl_name = "BT SOC status";
2118 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2119 bool bt_soc_status = true;
2120 if (!ctl) {
2121 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2122 __func__, mixer_ctl_name);
2123 /*This is to ensure we dont break targets which dont have the kernel change*/
2124 return true;
2125 }
2126 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2127 ALOGD("BT SOC status: %d",bt_soc_status);
2128 return bt_soc_status;
2129}
2130
2131int out_standby_l(struct audio_stream *stream);
2132
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002133int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002135 snd_device_t out_snd_device = SND_DEVICE_NONE;
2136 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002137 struct audio_usecase *usecase = NULL;
2138 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002139 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002140 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302141 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002142 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002143 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302145 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2146
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002147 usecase = get_usecase_from_list(adev, uc_id);
2148 if (usecase == NULL) {
2149 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2150 return -EINVAL;
2151 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002153 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002154 (usecase->type == VOIP_CALL) ||
2155 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302156 if(usecase->stream.out == NULL) {
2157 ALOGE("%s: stream.out is NULL", __func__);
2158 return -EINVAL;
2159 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002160 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002161 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002162 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002163 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302164 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302165 if (usecase->stream.inout == NULL) {
2166 ALOGE("%s: stream.inout is NULL", __func__);
2167 return -EINVAL;
2168 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302169 stream_out.devices = usecase->stream.inout->out_config.devices;
2170 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2171 stream_out.format = usecase->stream.inout->out_config.format;
2172 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2173 out_snd_device = platform_get_output_snd_device(adev->platform,
2174 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302175 usecase->devices = out_snd_device;
2176 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2177 if (usecase->stream.inout == NULL) {
2178 ALOGE("%s: stream.inout is NULL", __func__);
2179 return -EINVAL;
2180 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302181 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302182 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183 } else {
2184 /*
2185 * If the voice call is active, use the sound devices of voice call usecase
2186 * so that it would not result any device switch. All the usecases will
2187 * be switched to new device when select_devices() is called for voice call
2188 * usecase. This is to avoid switching devices for voice call when
2189 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002190 * choose voice call device only if the use case device is
2191 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002192 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002193 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002194 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002195 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002196 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2197 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302198 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2199 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002200 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002201 in_snd_device = vc_usecase->in_snd_device;
2202 out_snd_device = vc_usecase->out_snd_device;
2203 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002204 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002205 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002206 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002207 if ((voip_usecase != NULL) &&
2208 (usecase->type == PCM_PLAYBACK) &&
2209 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002210 out_snd_device_backend_match = platform_check_backends_match(
2211 voip_usecase->out_snd_device,
2212 platform_get_output_snd_device(
2213 adev->platform,
2214 usecase->stream.out));
2215 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002216 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002217 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2218 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002219 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002220 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002221 in_snd_device = voip_usecase->in_snd_device;
2222 out_snd_device = voip_usecase->out_snd_device;
2223 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002224 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002225 hfp_ucid = audio_extn_hfp_get_usecase();
2226 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002227 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002228 in_snd_device = hfp_usecase->in_snd_device;
2229 out_snd_device = hfp_usecase->out_snd_device;
2230 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002231 }
2232 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302233 if (usecase->stream.out == NULL) {
2234 ALOGE("%s: stream.out is NULL", __func__);
2235 return -EINVAL;
2236 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002237 usecase->devices = usecase->stream.out->devices;
2238 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002239 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002240 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002241 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002242 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002243 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002244 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2245
2246 if ((usecase->stream.out != NULL &&
2247 voip_usecase != NULL &&
2248 usecase->stream.out->usecase == voip_usecase->id) &&
2249 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002250 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2251 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002252 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002253 select_devices(adev, adev->active_input->usecase);
2254 }
2255 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002256 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302257 if (usecase->stream.in == NULL) {
2258 ALOGE("%s: stream.in is NULL", __func__);
2259 return -EINVAL;
2260 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002261 usecase->devices = usecase->stream.in->device;
2262 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002263 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002264 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002265 if (adev->active_input &&
2266 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302267 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002268 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2269 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2270 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2271 out_device = voip_usecase->stream.out->devices;
2272 else if (adev->primary_output && !adev->primary_output->standby)
2273 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002274 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002275 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2276 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002277 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002278 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002279 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 }
2281 }
2282
2283 if (out_snd_device == usecase->out_snd_device &&
2284 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302285
2286 if (!force_device_switch(usecase))
2287 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288 }
2289
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302290 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002291 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302292 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2293 return 0;
2294 }
2295
Aalique Grahame22e49102018-12-18 14:23:57 -08002296 if (out_snd_device != SND_DEVICE_NONE &&
2297 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2298 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2299 __func__,
2300 use_case_table[uc_id],
2301 adev->last_logged_snd_device[uc_id][0],
2302 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2303 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2304 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2305 -1,
2306 out_snd_device,
2307 platform_get_snd_device_name(out_snd_device),
2308 platform_get_snd_device_acdb_id(out_snd_device));
2309 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2310 }
2311 if (in_snd_device != SND_DEVICE_NONE &&
2312 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2313 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2314 __func__,
2315 use_case_table[uc_id],
2316 adev->last_logged_snd_device[uc_id][1],
2317 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2318 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2319 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2320 -1,
2321 in_snd_device,
2322 platform_get_snd_device_name(in_snd_device),
2323 platform_get_snd_device_acdb_id(in_snd_device));
2324 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2325 }
2326
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 /*
2329 * Limitation: While in call, to do a device switch we need to disable
2330 * and enable both RX and TX devices though one of them is same as current
2331 * device.
2332 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002333 if ((usecase->type == VOICE_CALL) &&
2334 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2335 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002336 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002337 }
2338
2339 if (((usecase->type == VOICE_CALL) ||
2340 (usecase->type == VOIP_CALL)) &&
2341 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2342 /* Disable sidetone only if voice/voip call already exists */
2343 if (voice_is_call_state_active(adev) ||
2344 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002345 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002346
2347 /* Disable aanc only if voice call exists */
2348 if (voice_is_call_state_active(adev))
2349 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002350 }
2351
Aalique Grahame22e49102018-12-18 14:23:57 -08002352 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2353 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002354 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302355 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002356 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2357 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2358 else
2359 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302360 }
2361
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002362 /* Disable current sound devices */
2363 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002364 disable_audio_route(adev, usecase);
2365 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 }
2367
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002368 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002369 disable_audio_route(adev, usecase);
2370 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 }
2372
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002373 /* Applicable only on the targets that has external modem.
2374 * New device information should be sent to modem before enabling
2375 * the devices to reduce in-call device switch time.
2376 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002377 if ((usecase->type == VOICE_CALL) &&
2378 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2379 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002380 status = platform_switch_voice_call_enable_device_config(adev->platform,
2381 out_snd_device,
2382 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002383 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002384
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002385 /* Enable new sound devices */
2386 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002387 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302388 if (platform_check_codec_asrc_support(adev->platform))
2389 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002390 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 }
2392
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002393 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302394 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002395 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002396 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002397
Avinash Vaish71a8b972014-07-24 15:36:33 +05302398 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002399 status = platform_switch_voice_call_device_post(adev->platform,
2400 out_snd_device,
2401 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302402 enable_audio_route_for_voice_usecases(adev, usecase);
2403 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002404
sangwoo170731f2013-06-08 15:36:36 +09002405 usecase->in_snd_device = in_snd_device;
2406 usecase->out_snd_device = out_snd_device;
2407
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302408 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2409 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302410 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002411 if ((24 == usecase->stream.out->bit_width) &&
2412 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2413 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2414 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2415 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2416 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2417 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2418 /*
2419 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2420 * configured device sample rate, if not update the COPP rate to be equal to the
2421 * device sample rate, else open COPP at stream sample rate
2422 */
2423 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2424 usecase->stream.out->sample_rate,
2425 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302426 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2427 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002428 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2429 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2430 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2431 }
2432
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002433 /* Notify device change info to effect clients registered */
2434 audio_extn_gef_notify_device_config(
2435 usecase->stream.out->devices,
2436 usecase->stream.out->channel_mask,
2437 usecase->stream.out->app_type_cfg.sample_rate,
2438 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302439 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002440 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002441
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002442 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002443
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002444 /* If input stream is already running then effect needs to be
2445 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002446 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2447 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002448 check_and_enable_effect(adev);
2449
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002450 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002451 /* Enable aanc only if voice call exists */
2452 if (voice_is_call_state_active(adev))
2453 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2454
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002455 /* Enable sidetone only if other voice/voip call already exists */
2456 if (voice_is_call_state_active(adev) ||
2457 voice_extn_compress_voip_is_started(adev))
2458 voice_set_sidetone(adev, out_snd_device, true);
2459 }
2460
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002461 /* Applicable only on the targets that has external modem.
2462 * Enable device command should be sent to modem only after
2463 * enabling voice call mixer controls
2464 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002465 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002466 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2467 out_snd_device,
2468 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302469
2470 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2471
2472 if (usecase->type == VOIP_CALL) {
2473 if (adev->active_input != NULL &&
2474 !adev->active_input->standby) {
2475 if (is_bt_soc_on(adev) == false){
2476 ALOGD("BT SCO MIC disconnected while in connection");
2477 if (adev->active_input->pcm != NULL)
2478 pcm_stop(adev->active_input->pcm);
2479 }
2480 }
2481 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2482 && usecase->stream.out->started) {
2483 if (is_bt_soc_on(adev) == false) {
2484 ALOGD("BT SCO/A2DP disconnected while in connection");
2485 out_standby_l(&usecase->stream.out->stream.common);
2486 }
2487 }
2488 } else if ((usecase->stream.out != NULL) &&
2489 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302490 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2491 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302492 usecase->stream.out->started) {
2493 if (is_bt_soc_on(adev) == false) {
2494 ALOGD("BT SCO/A2dp disconnected while in connection");
2495 out_standby_l(&usecase->stream.out->stream.common);
2496 }
2497 }
2498 }
2499
Aalique Grahame22e49102018-12-18 14:23:57 -08002500 if (usecase == voip_usecase) {
2501 struct stream_out *voip_out = voip_usecase->stream.out;
2502 audio_extn_utils_send_app_type_gain(adev,
2503 voip_out->app_type_cfg.app_type,
2504 &voip_out->app_type_cfg.gain[0]);
2505 }
2506
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302507 ALOGD("%s: done",__func__);
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 return status;
2510}
2511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512static int stop_input_stream(struct stream_in *in)
2513{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302514 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302516
2517 if (in == NULL) {
2518 ALOGE("%s: stream_in ptr is NULL", __func__);
2519 return -EINVAL;
2520 }
2521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 struct audio_device *adev = in->dev;
2523
Eric Laurent994a6932013-07-17 11:51:42 -07002524 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002525 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 uc_info = get_usecase_from_list(adev, in->usecase);
2527 if (uc_info == NULL) {
2528 ALOGE("%s: Could not find the usecase (%d) in the list",
2529 __func__, in->usecase);
2530 return -EINVAL;
2531 }
2532
Derek Chenea197282019-01-07 17:35:01 -08002533 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2534 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002535
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002536 /* Close in-call recording streams */
2537 voice_check_and_stop_incall_rec_usecase(adev, in);
2538
Eric Laurent150dbfe2013-02-27 14:31:02 -08002539 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002540 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002541
2542 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002543 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002545 list_remove(&uc_info->list);
2546 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002548 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302549 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002550 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 return ret;
2552}
2553
2554int start_input_stream(struct stream_in *in)
2555{
2556 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002557 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302559
2560 if (in == NULL) {
2561 ALOGE("%s: stream_in ptr is NULL", __func__);
2562 return -EINVAL;
2563 }
2564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002566 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002567 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568
Mingming Yin2664a5b2015-09-03 10:53:11 -07002569 if (get_usecase_from_list(adev, usecase) == NULL)
2570 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302571 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2572 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002573
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302574 if (CARD_STATUS_OFFLINE == in->card_status||
2575 CARD_STATUS_OFFLINE == adev->card_status) {
2576 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302577 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302578 goto error_config;
2579 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302580
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302581 if (audio_is_bluetooth_sco_device(in->device)) {
2582 if (!adev->bt_sco_on) {
2583 ALOGE("%s: SCO profile is not ready, return error", __func__);
2584 ret = -EIO;
2585 goto error_config;
2586 }
2587 }
2588
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002589 /* Check if source matches incall recording usecase criteria */
2590 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2591 if (ret)
2592 goto error_config;
2593 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002594 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2595
2596 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2597 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2598 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002599 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002600 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002601
Eric Laurentb23d5282013-05-14 15:27:20 -07002602 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 if (in->pcm_device_id < 0) {
2604 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2605 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002606 ret = -EINVAL;
2607 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002609
2610 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002612
2613 if (!uc_info) {
2614 ret = -ENOMEM;
2615 goto error_config;
2616 }
2617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 uc_info->id = in->usecase;
2619 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002620 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002621 uc_info->devices = in->device;
2622 uc_info->in_snd_device = SND_DEVICE_NONE;
2623 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002625 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302626 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2627 adev->perf_lock_opts,
2628 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002629 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630
Derek Chenea197282019-01-07 17:35:01 -08002631 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2632 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002633
Haynes Mathew George16081042017-05-31 17:16:49 -07002634 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302635 ret = audio_extn_cin_start_input_stream(in);
2636 if (ret)
2637 goto error_open;
2638 else
2639 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002640 }
2641
Haynes Mathew George16081042017-05-31 17:16:49 -07002642 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002643 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002644 ALOGE("%s: pcm stream not ready", __func__);
2645 goto error_open;
2646 }
2647 ret = pcm_start(in->pcm);
2648 if (ret < 0) {
2649 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2650 goto error_open;
2651 }
2652 } else {
2653 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2654 unsigned int pcm_open_retry_count = 0;
2655
2656 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2657 flags |= PCM_MMAP | PCM_NOIRQ;
2658 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2659 } else if (in->realtime) {
2660 flags |= PCM_MMAP | PCM_NOIRQ;
2661 }
2662
Garmond Leunge2433c32017-09-28 21:51:22 -07002663 if (audio_extn_ffv_get_stream() == in) {
2664 ALOGD("%s: ffv stream, update pcm config", __func__);
2665 audio_extn_ffv_update_pcm_config(&config);
2666 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002667 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2668 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2669
2670 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002671 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002672 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002673 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002674 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302675 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302676 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2677 adev->card_status = CARD_STATUS_OFFLINE;
2678 in->card_status = CARD_STATUS_OFFLINE;
2679 ret = -EIO;
2680 goto error_open;
2681 }
2682
Haynes Mathew George16081042017-05-31 17:16:49 -07002683 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2684 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2685 if (in->pcm != NULL) {
2686 pcm_close(in->pcm);
2687 in->pcm = NULL;
2688 }
2689 if (pcm_open_retry_count-- == 0) {
2690 ret = -EIO;
2691 goto error_open;
2692 }
2693 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2694 continue;
2695 }
2696 break;
2697 }
2698
2699 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002700 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002701 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002702 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002703 if (ret < 0) {
2704 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2705 pcm_close(in->pcm);
2706 in->pcm = NULL;
2707 goto error_open;
2708 }
2709 register_in_stream(in);
2710 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002711 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002712 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002713 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002714 if (ret < 0) {
2715 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002716 pcm_close(in->pcm);
2717 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002718 goto error_open;
2719 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002720 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002721 }
2722
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002723 check_and_enable_effect(adev);
2724
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302725done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302726 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002727 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302728 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002729 return ret;
2730
2731error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302732 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002734error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302735 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302736 /*
2737 * sleep 50ms to allow sufficient time for kernel
2738 * drivers to recover incases like SSR.
2739 */
2740 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002741 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302742 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002743 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744}
2745
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002746void lock_input_stream(struct stream_in *in)
2747{
2748 pthread_mutex_lock(&in->pre_lock);
2749 pthread_mutex_lock(&in->lock);
2750 pthread_mutex_unlock(&in->pre_lock);
2751}
2752
2753void lock_output_stream(struct stream_out *out)
2754{
2755 pthread_mutex_lock(&out->pre_lock);
2756 pthread_mutex_lock(&out->lock);
2757 pthread_mutex_unlock(&out->pre_lock);
2758}
2759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002760/* must be called with out->lock locked */
2761static int send_offload_cmd_l(struct stream_out* out, int command)
2762{
2763 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2764
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002765 if (!cmd) {
2766 ALOGE("failed to allocate mem for command 0x%x", command);
2767 return -ENOMEM;
2768 }
2769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002770 ALOGVV("%s %d", __func__, command);
2771
2772 cmd->cmd = command;
2773 list_add_tail(&out->offload_cmd_list, &cmd->node);
2774 pthread_cond_signal(&out->offload_cond);
2775 return 0;
2776}
2777
2778/* must be called iwth out->lock locked */
2779static void stop_compressed_output_l(struct stream_out *out)
2780{
2781 out->offload_state = OFFLOAD_STATE_IDLE;
2782 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002783 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002784 if (out->compr != NULL) {
2785 compress_stop(out->compr);
2786 while (out->offload_thread_blocked) {
2787 pthread_cond_wait(&out->cond, &out->lock);
2788 }
2789 }
2790}
2791
Varun Balaraje49253e2017-07-06 19:48:56 +05302792bool is_interactive_usecase(audio_usecase_t uc_id)
2793{
2794 unsigned int i;
2795 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2796 if (uc_id == interactive_usecases[i])
2797 return true;
2798 }
2799 return false;
2800}
2801
2802static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2803{
2804 audio_usecase_t ret_uc = USECASE_INVALID;
2805 unsigned int intract_uc_index;
2806 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2807
2808 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2809 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2810 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2811 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2812 ret_uc = interactive_usecases[intract_uc_index];
2813 break;
2814 }
2815 }
2816
2817 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2818 return ret_uc;
2819}
2820
2821static void free_interactive_usecase(struct audio_device *adev,
2822 audio_usecase_t uc_id)
2823{
2824 unsigned int interact_uc_index;
2825 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2826
2827 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2828 if (interactive_usecases[interact_uc_index] == uc_id) {
2829 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2830 break;
2831 }
2832 }
2833 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2834}
2835
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002836bool is_offload_usecase(audio_usecase_t uc_id)
2837{
2838 unsigned int i;
2839 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2840 if (uc_id == offload_usecases[i])
2841 return true;
2842 }
2843 return false;
2844}
2845
Dhananjay Kumarac341582017-02-23 23:42:25 +05302846static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002847{
vivek mehta446c3962015-09-14 10:57:35 -07002848 audio_usecase_t ret_uc = USECASE_INVALID;
2849 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002850 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002851 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302852 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002853 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2854 else
2855 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002856
vivek mehta446c3962015-09-14 10:57:35 -07002857 pthread_mutex_lock(&adev->lock);
2858 if (get_usecase_from_list(adev, ret_uc) != NULL)
2859 ret_uc = USECASE_INVALID;
2860 pthread_mutex_unlock(&adev->lock);
2861
2862 return ret_uc;
2863 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002864
2865 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002866 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2867 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2868 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2869 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002870 break;
2871 }
2872 }
vivek mehta446c3962015-09-14 10:57:35 -07002873
2874 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2875 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002876}
2877
2878static void free_offload_usecase(struct audio_device *adev,
2879 audio_usecase_t uc_id)
2880{
vivek mehta446c3962015-09-14 10:57:35 -07002881 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002882 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002883
2884 if (!adev->multi_offload_enable)
2885 return;
2886
2887 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2888 if (offload_usecases[offload_uc_index] == uc_id) {
2889 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002890 break;
2891 }
2892 }
2893 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2894}
2895
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896static void *offload_thread_loop(void *context)
2897{
2898 struct stream_out *out = (struct stream_out *) context;
2899 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002900 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002903 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2905
2906 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002907 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 for (;;) {
2909 struct offload_cmd *cmd = NULL;
2910 stream_callback_event_t event;
2911 bool send_callback = false;
2912
2913 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2914 __func__, list_empty(&out->offload_cmd_list),
2915 out->offload_state);
2916 if (list_empty(&out->offload_cmd_list)) {
2917 ALOGV("%s SLEEPING", __func__);
2918 pthread_cond_wait(&out->offload_cond, &out->lock);
2919 ALOGV("%s RUNNING", __func__);
2920 continue;
2921 }
2922
2923 item = list_head(&out->offload_cmd_list);
2924 cmd = node_to_item(item, struct offload_cmd, node);
2925 list_remove(item);
2926
2927 ALOGVV("%s STATE %d CMD %d out->compr %p",
2928 __func__, out->offload_state, cmd->cmd, out->compr);
2929
2930 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2931 free(cmd);
2932 break;
2933 }
2934
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002935 // allow OFFLOAD_CMD_ERROR reporting during standby
2936 // this is needed to handle failures during compress_open
2937 // Note however that on a pause timeout, the stream is closed
2938 // and no offload usecase will be active. Therefore this
2939 // special case is needed for compress_open failures alone
2940 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2941 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002943 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 pthread_cond_signal(&out->cond);
2945 continue;
2946 }
2947 out->offload_thread_blocked = true;
2948 pthread_mutex_unlock(&out->lock);
2949 send_callback = false;
2950 switch(cmd->cmd) {
2951 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002952 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002954 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 send_callback = true;
2956 event = STREAM_CBK_EVENT_WRITE_READY;
2957 break;
2958 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002959 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302960 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002961 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302962 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002963 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302964 if (ret < 0)
2965 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302966 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302967 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002968 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002969 else
2970 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002971 if (-ENETRESET != ret && !(-EINTR == ret &&
2972 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302973 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302974 pthread_mutex_lock(&out->lock);
2975 out->send_new_metadata = 1;
2976 out->send_next_track_params = true;
2977 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302978 event = STREAM_CBK_EVENT_DRAIN_READY;
2979 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2980 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302981 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 break;
2983 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002984 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002985 ret = compress_drain(out->compr);
2986 ALOGD("copl(%p):out of compress_drain", out);
2987 // EINTR check avoids drain interruption due to SSR
2988 if (-ENETRESET != ret && !(-EINTR == ret &&
2989 CARD_STATUS_OFFLINE == out->card_status)) {
2990 send_callback = true;
2991 event = STREAM_CBK_EVENT_DRAIN_READY;
2992 } else
2993 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302995 case OFFLOAD_CMD_ERROR:
2996 ALOGD("copl(%p): sending error callback to AF", out);
2997 send_callback = true;
2998 event = STREAM_CBK_EVENT_ERROR;
2999 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 default:
3001 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3002 break;
3003 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003004 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003005 out->offload_thread_blocked = false;
3006 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003007 if (send_callback && out->client_callback) {
3008 ALOGVV("%s: sending client_callback event %d", __func__, event);
3009 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003010 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 free(cmd);
3012 }
3013
3014 pthread_cond_signal(&out->cond);
3015 while (!list_empty(&out->offload_cmd_list)) {
3016 item = list_head(&out->offload_cmd_list);
3017 list_remove(item);
3018 free(node_to_item(item, struct offload_cmd, node));
3019 }
3020 pthread_mutex_unlock(&out->lock);
3021
3022 return NULL;
3023}
3024
3025static int create_offload_callback_thread(struct stream_out *out)
3026{
3027 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3028 list_init(&out->offload_cmd_list);
3029 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3030 offload_thread_loop, out);
3031 return 0;
3032}
3033
3034static int destroy_offload_callback_thread(struct stream_out *out)
3035{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003036 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 stop_compressed_output_l(out);
3038 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3039
3040 pthread_mutex_unlock(&out->lock);
3041 pthread_join(out->offload_thread, (void **) NULL);
3042 pthread_cond_destroy(&out->offload_cond);
3043
3044 return 0;
3045}
3046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047static int stop_output_stream(struct stream_out *out)
3048{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303049 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 struct audio_usecase *uc_info;
3051 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003052 bool has_voip_usecase =
3053 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054
Eric Laurent994a6932013-07-17 11:51:42 -07003055 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003056 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 uc_info = get_usecase_from_list(adev, out->usecase);
3058 if (uc_info == NULL) {
3059 ALOGE("%s: Could not find the usecase (%d) in the list",
3060 __func__, out->usecase);
3061 return -EINVAL;
3062 }
3063
Derek Chenea197282019-01-07 17:35:01 -08003064 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3065 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003066
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003067 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303068 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003069 if (adev->visualizer_stop_output != NULL)
3070 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003071
3072 audio_extn_dts_remove_state_notifier_node(out->usecase);
3073
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003074 if (adev->offload_effects_stop_output != NULL)
3075 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3076 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003077
Arun Mirpurief53ce52018-09-11 18:00:09 -07003078 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3079 voice_set_device_mute_flag(adev, false);
3080
Eric Laurent150dbfe2013-02-27 14:31:02 -08003081 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003082 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003083
3084 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003085 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086
Aalique Grahame22e49102018-12-18 14:23:57 -08003087 audio_extn_extspk_update(adev->extspk);
3088
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003089 if (is_offload_usecase(out->usecase)) {
3090 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3091 adev->dsp_bit_width_enforce_mode,
3092 false);
3093 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003094 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3095 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3096 false);
3097
3098 if (ret != 0)
3099 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3100 /* default service interval was successfully updated,
3101 reopen USB backend with new service interval */
3102 ret = 0;
3103 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003104
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003105 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303106 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003107 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303108 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003109 ALOGV("Disable passthrough , reset mixer to pcm");
3110 /* NO_PASSTHROUGH */
3111 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003112 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003113 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3114 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003115
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303116 /* Must be called after removing the usecase from list */
3117 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303118 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303119
Manish Dewangan21a850a2017-08-14 12:03:55 +05303120 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003121 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3122 if (ret < 0)
3123 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3124 }
3125
Aalique Grahame22e49102018-12-18 14:23:57 -08003126 if (has_voip_usecase ||
3127 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3128 struct listnode *node;
3129 struct audio_usecase *usecase;
3130 list_for_each(node, &adev->usecase_list) {
3131 usecase = node_to_item(node, struct audio_usecase, list);
3132 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3133 continue;
3134
3135 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3136 __func__, usecase->id, use_case_table[usecase->id],
3137 out->usecase, use_case_table[out->usecase]);
3138 select_devices(adev, usecase->id);
3139 }
3140 }
3141
Garmond Leung5fd0b552018-04-17 11:56:12 -07003142 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003143 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 return ret;
3145}
3146
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003147struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3148 unsigned int flags, unsigned int pcm_open_retry_count,
3149 struct pcm_config *config)
3150{
3151 struct pcm* pcm = NULL;
3152
3153 while (1) {
3154 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3155 if (pcm == NULL || !pcm_is_ready(pcm)) {
3156 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3157 if (pcm != NULL) {
3158 pcm_close(pcm);
3159 pcm = NULL;
3160 }
3161 if (pcm_open_retry_count-- == 0)
3162 return NULL;
3163
3164 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3165 continue;
3166 }
3167 break;
3168 }
3169
3170 if (pcm_is_ready(pcm)) {
3171 int ret = pcm_prepare(pcm);
3172 if (ret < 0) {
3173 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3174 pcm_close(pcm);
3175 pcm = NULL;
3176 }
3177 }
3178
3179 return pcm;
3180}
3181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182int start_output_stream(struct stream_out *out)
3183{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 struct audio_usecase *uc_info;
3186 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003187 char mixer_ctl_name[128];
3188 struct mixer_ctl *ctl = NULL;
3189 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303190 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003191 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192
Haynes Mathew George380745d2017-10-04 15:27:45 -07003193 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003194 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3195 ret = -EINVAL;
3196 goto error_config;
3197 }
3198
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003199 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303200 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003201 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303202
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303203 if (CARD_STATUS_OFFLINE == out->card_status ||
3204 CARD_STATUS_OFFLINE == adev->card_status) {
3205 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303206 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303207 goto error_config;
3208 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303209
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303210 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003211 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003212 if (out->devices &
3213 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303214 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303215 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303216 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3217 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3218 ret = -EAGAIN;
3219 goto error_config;
3220 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303221 }
3222 }
3223 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303224 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3225 if (!adev->bt_sco_on) {
3226 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3227 //combo usecase just by pass a2dp
3228 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3229 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3230 } else {
3231 ALOGE("%s: SCO profile is not ready, return error", __func__);
3232 ret = -EAGAIN;
3233 goto error_config;
3234 }
3235 }
3236 }
3237
Eric Laurentb23d5282013-05-14 15:27:20 -07003238 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 if (out->pcm_device_id < 0) {
3240 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3241 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003242 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003243 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 }
3245
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003246 if (is_haptic_usecase) {
3247 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3248 if (adev->haptic_pcm_device_id < 0) {
3249 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3250 __func__, adev->haptic_pcm_device_id, out->usecase);
3251 ret = -EINVAL;
3252 goto error_config;
3253 }
3254 }
3255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003257
3258 if (!uc_info) {
3259 ret = -ENOMEM;
3260 goto error_config;
3261 }
3262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 uc_info->id = out->usecase;
3264 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003265 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003266 uc_info->devices = out->devices;
3267 uc_info->in_snd_device = SND_DEVICE_NONE;
3268 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003269
3270 /* This must be called before adding this usecase to the list */
3271 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3272 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3273 /* USB backend is not reopened immediately.
3274 This is eventually done as part of select_devices */
3275 }
3276
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003277 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303279 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3280 adev->perf_lock_opts,
3281 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303282
3283 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303284 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303285 if (audio_extn_passthru_is_enabled() &&
3286 audio_extn_passthru_is_passthrough_stream(out)) {
3287 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303288 }
3289 }
3290
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303291 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003292 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303293 if (!a2dp_combo) {
3294 check_a2dp_restore_l(adev, out, false);
3295 } else {
3296 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003297 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3298 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3299 else
3300 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303301 select_devices(adev, out->usecase);
3302 out->devices = dev;
3303 }
3304 } else {
3305 select_devices(adev, out->usecase);
3306 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003307
Arun Mirpurief53ce52018-09-11 18:00:09 -07003308 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3309 voice_set_device_mute_flag(adev, true);
3310
Derek Chenea197282019-01-07 17:35:01 -08003311 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3312 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003313
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003314 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3315 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003316
3317 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003318 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003319 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3320 ALOGE("%s: pcm stream not ready", __func__);
3321 goto error_open;
3322 }
3323 ret = pcm_start(out->pcm);
3324 if (ret < 0) {
3325 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3326 goto error_open;
3327 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003328 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003329 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003330 unsigned int flags = PCM_OUT;
3331 unsigned int pcm_open_retry_count = 0;
3332 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3333 flags |= PCM_MMAP | PCM_NOIRQ;
3334 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003335 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003336 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003337 } else
3338 flags |= PCM_MONOTONIC;
3339
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003340 if ((adev->vr_audio_mode_enabled) &&
3341 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3342 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3343 "PCM_Dev %d Topology", out->pcm_device_id);
3344 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3345 if (!ctl) {
3346 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3347 __func__, mixer_ctl_name);
3348 } else {
3349 //if success use ULLPP
3350 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3351 __func__, mixer_ctl_name, out->pcm_device_id);
3352 //There is a still a possibility that some sessions
3353 // that request for FAST|RAW when 3D audio is active
3354 //can go through ULLPP. Ideally we expects apps to
3355 //listen to audio focus and stop concurrent playback
3356 //Also, we will look for mode flag (voice_in_communication)
3357 //before enabling the realtime flag.
3358 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3359 }
3360 }
3361
Surendar Karka91fa3682018-07-02 18:12:12 +05303362 if (out->realtime)
3363 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3364 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3365
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003366 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3367 flags, pcm_open_retry_count,
3368 &(out->config));
3369 if (out->pcm == NULL) {
3370 ret = -EIO;
3371 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003373
3374 if (is_haptic_usecase) {
3375 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3376 adev->haptic_pcm_device_id,
3377 flags, pcm_open_retry_count,
3378 &(adev->haptics_config));
3379 // failure to open haptics pcm shouldnt stop audio,
3380 // so do not close audio pcm in case of error
3381 }
3382
Surendar Karka91fa3682018-07-02 18:12:12 +05303383 if (!out->realtime)
3384 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303385 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003386
Zhou Song2b8f28f2017-09-11 10:51:38 +08003387 // apply volume for voip playback after path is set up
3388 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3389 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303390 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3391 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303392 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3393 out->apply_volume = false;
3394 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003396 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303397 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003398 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3399 adev->dsp_bit_width_enforce_mode,
3400 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003402 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003403 out->compr = compress_open(adev->snd_card,
3404 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003405 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003406 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303407 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303408 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3409 adev->card_status = CARD_STATUS_OFFLINE;
3410 out->card_status = CARD_STATUS_OFFLINE;
3411 ret = -EIO;
3412 goto error_open;
3413 }
3414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003416 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003417 compress_close(out->compr);
3418 out->compr = NULL;
3419 ret = -EIO;
3420 goto error_open;
3421 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303422 /* compress_open sends params of the track, so reset the flag here */
3423 out->is_compr_metadata_avail = false;
3424
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003425 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003427
Fred Oh3f43e742015-03-04 18:42:34 -08003428 /* Since small bufs uses blocking writes, a write will be blocked
3429 for the default max poll time (20s) in the event of an SSR.
3430 Reduce the poll time to observe and deal with SSR faster.
3431 */
Ashish Jain5106d362016-05-11 19:23:33 +05303432 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003433 compress_set_max_poll_wait(out->compr, 1000);
3434 }
3435
Manish Dewangan69426c82017-01-30 17:35:36 +05303436 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303437 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303438
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003439 audio_extn_dts_create_state_notifier_node(out->usecase);
3440 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3441 popcount(out->channel_mask),
3442 out->playback_started);
3443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003444#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303445 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003446 audio_extn_dolby_send_ddp_endp_params(adev);
3447#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303448 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3449 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003450 if (adev->visualizer_start_output != NULL)
3451 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3452 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303453 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003454 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003455 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003457
3458 if (ret == 0) {
3459 register_out_stream(out);
3460 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003461 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3462 ALOGE("%s: pcm stream not ready", __func__);
3463 goto error_open;
3464 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003465 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003466 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003467 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003468 if (ret < 0)
3469 goto error_open;
3470 }
3471 }
3472
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303473 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003474 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003475
Manish Dewangan21a850a2017-08-14 12:03:55 +05303476 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003477 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003478 if (ret < 0)
3479 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3480 }
3481
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003482 // consider a scenario where on pause lower layers are tear down.
3483 // so on resume, swap mixer control need to be sent only when
3484 // backend is active, hence rather than sending from enable device
3485 // sending it from start of streamtream
3486
3487 platform_set_swap_channels(adev, true);
3488
Haynes Mathew George380745d2017-10-04 15:27:45 -07003489 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303490 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003491 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003493 if (adev->haptic_pcm) {
3494 pcm_close(adev->haptic_pcm);
3495 adev->haptic_pcm = NULL;
3496 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303497 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003499error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303500 /*
3501 * sleep 50ms to allow sufficient time for kernel
3502 * drivers to recover incases like SSR.
3503 */
3504 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003505 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303506 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003507 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508}
3509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510static int check_input_parameters(uint32_t sample_rate,
3511 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003512 int channel_count,
3513 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003515 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303517 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3518 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3519 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003520 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003521 !audio_extn_compr_cap_format_supported(format) &&
3522 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003523 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003524
Aalique Grahame22e49102018-12-18 14:23:57 -08003525 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3526 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3527 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3528 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3529 return -EINVAL;
3530 }
3531
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003532 switch (channel_count) {
3533 case 1:
3534 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303535 case 3:
3536 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003537 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003538 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003539 break;
3540 default:
3541 ret = -EINVAL;
3542 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
3544 switch (sample_rate) {
3545 case 8000:
3546 case 11025:
3547 case 12000:
3548 case 16000:
3549 case 22050:
3550 case 24000:
3551 case 32000:
3552 case 44100:
3553 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003554 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303555 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003556 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303557 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 break;
3559 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003560 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 }
3562
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003563 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564}
3565
Naresh Tanniru04f71882018-06-26 17:46:22 +05303566
3567/** Add a value in a list if not already present.
3568 * @return true if value was successfully inserted or already present,
3569 * false if the list is full and does not contain the value.
3570 */
3571static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3572 for (size_t i = 0; i < list_length; i++) {
3573 if (list[i] == value) return true; // value is already present
3574 if (list[i] == 0) { // no values in this slot
3575 list[i] = value;
3576 return true; // value inserted
3577 }
3578 }
3579 return false; // could not insert value
3580}
3581
3582/** Add channel_mask in supported_channel_masks if not already present.
3583 * @return true if channel_mask was successfully inserted or already present,
3584 * false if supported_channel_masks is full and does not contain channel_mask.
3585 */
3586static void register_channel_mask(audio_channel_mask_t channel_mask,
3587 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3588 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3589 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3590}
3591
3592/** Add format in supported_formats if not already present.
3593 * @return true if format was successfully inserted or already present,
3594 * false if supported_formats is full and does not contain format.
3595 */
3596static void register_format(audio_format_t format,
3597 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3598 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3599 "%s: stream can not declare supporting its format %x", __func__, format);
3600}
3601/** Add sample_rate in supported_sample_rates if not already present.
3602 * @return true if sample_rate was successfully inserted or already present,
3603 * false if supported_sample_rates is full and does not contain sample_rate.
3604 */
3605static void register_sample_rate(uint32_t sample_rate,
3606 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3607 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3608 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3609}
3610
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003611static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3612{
3613 uint32_t high = num1, low = num2, temp = 0;
3614
3615 if (!num1 || !num2)
3616 return 0;
3617
3618 if (num1 < num2) {
3619 high = num2;
3620 low = num1;
3621 }
3622
3623 while (low != 0) {
3624 temp = low;
3625 low = high % low;
3626 high = temp;
3627 }
3628 return (num1 * num2)/high;
3629}
3630
3631static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3632{
3633 uint32_t remainder = 0;
3634
3635 if (!multiplier)
3636 return num;
3637
3638 remainder = num % multiplier;
3639 if (remainder)
3640 num += (multiplier - remainder);
3641
3642 return num;
3643}
3644
Aalique Grahame22e49102018-12-18 14:23:57 -08003645static size_t get_stream_buffer_size(size_t duration_ms,
3646 uint32_t sample_rate,
3647 audio_format_t format,
3648 int channel_count,
3649 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650{
3651 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003652 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653
Aalique Grahame22e49102018-12-18 14:23:57 -08003654 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003655 if (is_low_latency)
3656 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303657
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003658 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003659 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660
Ralf Herzbd08d632018-09-28 15:50:49 +02003661 /* make sure the size is multiple of 32 bytes and additionally multiple of
3662 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003663 * At 48 kHz mono 16-bit PCM:
3664 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3665 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003666 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003667 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003668 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003669
3670 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671}
3672
Aalique Grahame22e49102018-12-18 14:23:57 -08003673static size_t get_input_buffer_size(uint32_t sample_rate,
3674 audio_format_t format,
3675 int channel_count,
3676 bool is_low_latency)
3677{
3678 /* Don't know if USB HIFI in this context so use true to be conservative */
3679 if (check_input_parameters(sample_rate, format, channel_count,
3680 true /*is_usb_hifi */) != 0)
3681 return 0;
3682
3683 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3684 sample_rate,
3685 format,
3686 channel_count,
3687 is_low_latency);
3688}
3689
Ashish Jain058165c2016-09-28 23:18:48 +05303690static size_t get_output_period_size(uint32_t sample_rate,
3691 audio_format_t format,
3692 int channel_count,
3693 int duration /*in millisecs*/)
3694{
3695 size_t size = 0;
3696 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3697
3698 if ((duration == 0) || (sample_rate == 0) ||
3699 (bytes_per_sample == 0) || (channel_count == 0)) {
3700 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3701 bytes_per_sample, channel_count);
3702 return -EINVAL;
3703 }
3704
3705 size = (sample_rate *
3706 duration *
3707 bytes_per_sample *
3708 channel_count) / 1000;
3709 /*
3710 * To have same PCM samples for all channels, the buffer size requires to
3711 * be multiple of (number of channels * bytes per sample)
3712 * For writes to succeed, the buffer must be written at address which is multiple of 32
3713 */
3714 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3715
3716 return (size/(channel_count * bytes_per_sample));
3717}
3718
Zhou Song48453a02018-01-10 17:50:59 +08003719static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303720{
3721 uint64_t actual_frames_rendered = 0;
3722 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3723
3724 /* This adjustment accounts for buffering after app processor.
3725 * It is based on estimated DSP latency per use case, rather than exact.
3726 */
3727 int64_t platform_latency = platform_render_latency(out->usecase) *
3728 out->sample_rate / 1000000LL;
3729
Zhou Song48453a02018-01-10 17:50:59 +08003730 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303731 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3732 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3733 * hence only estimate.
3734 */
3735 int64_t signed_frames = out->written - kernel_buffer_size;
3736
3737 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3738
Zhou Song48453a02018-01-10 17:50:59 +08003739 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303740 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003741 if (timestamp != NULL )
3742 *timestamp = out->writeAt;
3743 } else if (timestamp != NULL) {
3744 clock_gettime(CLOCK_MONOTONIC, timestamp);
3745 }
3746 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303747
3748 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3749 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3750 (long long int)out->written, (int)kernel_buffer_size,
3751 audio_bytes_per_sample(out->compr_config.codec->format),
3752 popcount(out->channel_mask));
3753
3754 return actual_frames_rendered;
3755}
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3758{
3759 struct stream_out *out = (struct stream_out *)stream;
3760
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003761 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762}
3763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003764static int out_set_sample_rate(struct audio_stream *stream __unused,
3765 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766{
3767 return -ENOSYS;
3768}
3769
3770static size_t out_get_buffer_size(const struct audio_stream *stream)
3771{
3772 struct stream_out *out = (struct stream_out *)stream;
3773
Varun Balaraje49253e2017-07-06 19:48:56 +05303774 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303775 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303776 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303777 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3778 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3779 else
3780 return out->compr_config.fragment_size;
3781 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003782 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003783 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3784 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 +05303785 else if (is_offload_usecase(out->usecase) &&
3786 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303787 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003788
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003789 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003790 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791}
3792
3793static uint32_t out_get_channels(const struct audio_stream *stream)
3794{
3795 struct stream_out *out = (struct stream_out *)stream;
3796
3797 return out->channel_mask;
3798}
3799
3800static audio_format_t out_get_format(const struct audio_stream *stream)
3801{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802 struct stream_out *out = (struct stream_out *)stream;
3803
3804 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805}
3806
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003807static int out_set_format(struct audio_stream *stream __unused,
3808 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809{
3810 return -ENOSYS;
3811}
3812
3813static int out_standby(struct audio_stream *stream)
3814{
3815 struct stream_out *out = (struct stream_out *)stream;
3816 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003817 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003818
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303819 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3820 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003822 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003824 if (adev->adm_deregister_stream)
3825 adev->adm_deregister_stream(adev->adm_data, out->handle);
3826
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003827 if (is_offload_usecase(out->usecase))
3828 stop_compressed_output_l(out);
3829
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003830 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003832 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3833 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303834 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003835 pthread_mutex_unlock(&adev->lock);
3836 pthread_mutex_unlock(&out->lock);
3837 ALOGD("VOIP output entered standby");
3838 return 0;
3839 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 if (out->pcm) {
3841 pcm_close(out->pcm);
3842 out->pcm = NULL;
3843 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003844 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3845 do_stop = out->playback_started;
3846 out->playback_started = false;
3847 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003848 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003849 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303850 out->send_next_track_params = false;
3851 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003852 out->gapless_mdata.encoder_delay = 0;
3853 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003854 if (out->compr != NULL) {
3855 compress_close(out->compr);
3856 out->compr = NULL;
3857 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003858 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003859 if (do_stop) {
3860 stop_output_stream(out);
3861 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003862 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 }
3864 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303865 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 return 0;
3867}
3868
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303869static int out_on_error(struct audio_stream *stream)
3870{
3871 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003872 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303873
3874 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003875 // always send CMD_ERROR for offload streams, this
3876 // is needed e.g. when SSR happens within compress_open
3877 // since the stream is active, offload_callback_thread is also active.
3878 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3879 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003880 }
3881 pthread_mutex_unlock(&out->lock);
3882
3883 status = out_standby(&out->stream.common);
3884
3885 lock_output_stream(out);
3886 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003887 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303888 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303889
3890 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3891 ALOGD("Setting previous card status if offline");
3892 out->prev_card_status_offline = true;
3893 }
3894
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303895 pthread_mutex_unlock(&out->lock);
3896
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003897 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303898}
3899
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303900/*
3901 *standby implementation without locks, assumes that the callee already
3902 *has taken adev and out lock.
3903 */
3904int out_standby_l(struct audio_stream *stream)
3905{
3906 struct stream_out *out = (struct stream_out *)stream;
3907 struct audio_device *adev = out->dev;
3908
3909 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3910 stream, out->usecase, use_case_table[out->usecase]);
3911
3912 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003913 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303914 if (adev->adm_deregister_stream)
3915 adev->adm_deregister_stream(adev->adm_data, out->handle);
3916
3917 if (is_offload_usecase(out->usecase))
3918 stop_compressed_output_l(out);
3919
3920 out->standby = true;
3921 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3922 voice_extn_compress_voip_close_output_stream(stream);
3923 out->started = 0;
3924 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003925 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303926 return 0;
3927 } else if (!is_offload_usecase(out->usecase)) {
3928 if (out->pcm) {
3929 pcm_close(out->pcm);
3930 out->pcm = NULL;
3931 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003932 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3933 if (adev->haptic_pcm) {
3934 pcm_close(adev->haptic_pcm);
3935 adev->haptic_pcm = NULL;
3936 }
3937
3938 if (adev->haptic_buffer != NULL) {
3939 free(adev->haptic_buffer);
3940 adev->haptic_buffer = NULL;
3941 adev->haptic_buffer_size = 0;
3942 }
3943 adev->haptic_pcm_device_id = 0;
3944 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303945 } else {
3946 ALOGD("copl(%p):standby", out);
3947 out->send_next_track_params = false;
3948 out->is_compr_metadata_avail = false;
3949 out->gapless_mdata.encoder_delay = 0;
3950 out->gapless_mdata.encoder_padding = 0;
3951 if (out->compr != NULL) {
3952 compress_close(out->compr);
3953 out->compr = NULL;
3954 }
3955 }
3956 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003957 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303958 }
3959 ALOGD("%s: exit", __func__);
3960 return 0;
3961}
3962
Aalique Grahame22e49102018-12-18 14:23:57 -08003963static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964{
Aalique Grahame22e49102018-12-18 14:23:57 -08003965 struct stream_out *out = (struct stream_out *)stream;
3966
3967 // We try to get the lock for consistency,
3968 // but it isn't necessary for these variables.
3969 // If we're not in standby, we may be blocked on a write.
3970 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
3971 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
3972 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
3973
3974 if (locked) {
3975 pthread_mutex_unlock(&out->lock);
3976 }
3977
3978 // dump error info
3979 (void)error_log_dump(
3980 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
3981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 return 0;
3983}
3984
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003985static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3986{
3987 int ret = 0;
3988 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003989
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003990 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003991 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003992 return -EINVAL;
3993 }
3994
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303995 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003996
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003997 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3998 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303999 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004000 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004001 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4002 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304003 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004004 }
4005
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004006 ALOGV("%s new encoder delay %u and padding %u", __func__,
4007 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4008
4009 return 0;
4010}
4011
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004012static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4013{
4014 return out == adev->primary_output || out == adev->voice_tx_output;
4015}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004016
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304017// note: this call is safe only if the stream_cb is
4018// removed first in close_output_stream (as is done now).
4019static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4020{
4021 if (!stream || !parms)
4022 return;
4023
4024 struct stream_out *out = (struct stream_out *)stream;
4025 struct audio_device *adev = out->dev;
4026
4027 card_status_t status;
4028 int card;
4029 if (parse_snd_card_status(parms, &card, &status) < 0)
4030 return;
4031
4032 pthread_mutex_lock(&adev->lock);
4033 bool valid_cb = (card == adev->snd_card);
4034 pthread_mutex_unlock(&adev->lock);
4035
4036 if (!valid_cb)
4037 return;
4038
4039 lock_output_stream(out);
4040 if (out->card_status != status)
4041 out->card_status = status;
4042 pthread_mutex_unlock(&out->lock);
4043
4044 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4045 use_case_table[out->usecase],
4046 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4047
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304048 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304049 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304050 if (voice_is_call_state_active(adev) &&
4051 out == adev->primary_output) {
4052 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4053 pthread_mutex_lock(&adev->lock);
4054 voice_stop_call(adev);
4055 adev->mode = AUDIO_MODE_NORMAL;
4056 pthread_mutex_unlock(&adev->lock);
4057 }
4058 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304059 return;
4060}
4061
Kevin Rocardfce19002017-08-07 19:21:36 -07004062static int get_alive_usb_card(struct str_parms* parms) {
4063 int card;
4064 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4065 !audio_extn_usb_alive(card)) {
4066 return card;
4067 }
4068 return -ENODEV;
4069}
4070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4072{
4073 struct stream_out *out = (struct stream_out *)stream;
4074 struct audio_device *adev = out->dev;
4075 struct str_parms *parms;
4076 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004077 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304078 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004079 bool reconfig = false;
4080 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081
sangwoobc677242013-08-08 16:53:43 +09004082 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004083 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304085 if (!parms)
4086 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004087 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4088 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004090 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004091 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004093 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004094 * When HDMI cable is unplugged the music playback is paused and
4095 * the policy manager sends routing=0. But the audioflinger continues
4096 * to write data until standby time (3sec). As the HDMI core is
4097 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004098 * Avoid this by routing audio to speaker until standby.
4099 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004100 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4101 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304102 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004103 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4104 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004105 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304106 /*
4107 * When A2DP is disconnected the
4108 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004109 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304110 * (3sec). As BT is turned off, the write gets blocked.
4111 * Avoid this by routing audio to speaker until standby.
4112 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004113 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004114 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004115 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304116 val = AUDIO_DEVICE_OUT_SPEAKER;
4117 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304118 /*
4119 * When USB headset is disconnected the music platback paused
4120 * and the policy manager send routing=0. But if the USB is connected
4121 * back before the standby time, AFE is not closed and opened
4122 * when USB is connected back. So routing to speker will guarantee
4123 * AFE reconfiguration and AFE will be opend once USB is connected again
4124 */
4125 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4126 (val == AUDIO_DEVICE_NONE) &&
4127 !audio_extn_usb_connected(parms)) {
4128 val = AUDIO_DEVICE_OUT_SPEAKER;
4129 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304130 /* To avoid a2dp to sco overlapping / BT device improper state
4131 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304132 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304133 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004134 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004135 if (val &
4136 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304137 //combo usecase just by pass a2dp
4138 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304139 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304140 } else {
4141 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4142 /* update device to a2dp and don't route as BT returned error
4143 * However it is still possible a2dp routing called because
4144 * of current active device disconnection (like wired headset)
4145 */
4146 out->devices = val;
4147 pthread_mutex_unlock(&out->lock);
4148 pthread_mutex_unlock(&adev->lock);
4149 goto error;
4150 }
4151 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304152 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004153
4154 audio_devices_t new_dev = val;
4155
4156 // Workaround: If routing to an non existing usb device, fail gracefully
4157 // The routing request will otherwise block during 10 second
4158 int card;
4159 if (audio_is_usb_out_device(new_dev) &&
4160 (card = get_alive_usb_card(parms)) >= 0) {
4161
4162 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4163 pthread_mutex_unlock(&adev->lock);
4164 pthread_mutex_unlock(&out->lock);
4165 ret = -ENOSYS;
4166 goto routing_fail;
4167 }
4168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004169 /*
4170 * select_devices() call below switches all the usecases on the same
4171 * backend to the new device. Refer to check_usecases_codec_backend() in
4172 * the select_devices(). But how do we undo this?
4173 *
4174 * For example, music playback is active on headset (deep-buffer usecase)
4175 * and if we go to ringtones and select a ringtone, low-latency usecase
4176 * will be started on headset+speaker. As we can't enable headset+speaker
4177 * and headset devices at the same time, select_devices() switches the music
4178 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4179 * So when the ringtone playback is completed, how do we undo the same?
4180 *
4181 * We are relying on the out_set_parameters() call on deep-buffer output,
4182 * once the ringtone playback is ended.
4183 * NOTE: We should not check if the current devices are same as new devices.
4184 * Because select_devices() must be called to switch back the music
4185 * playback to headset.
4186 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004187 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004188 audio_devices_t new_dev = val;
4189 bool same_dev = out->devices == new_dev;
4190 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004191
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004192 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004193 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004194 if (adev->mode == AUDIO_MODE_IN_CALL) {
4195 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004196 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4197 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4198 audio_extn_usb_set_service_interval(true /*playback*/,
4199 service_interval,
4200 &reconfig);
4201 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4202 }
4203 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004204 }
4205 } else {
4206 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004207 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004208 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004209 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004210
4211 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004212 if (!same_dev) {
4213 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304214 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4215 adev->perf_lock_opts,
4216 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004217 if (adev->adm_on_routing_change)
4218 adev->adm_on_routing_change(adev->adm_data,
4219 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004220 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304221 if (!bypass_a2dp) {
4222 select_devices(adev, out->usecase);
4223 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004224 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4225 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4226 else
4227 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304228 select_devices(adev, out->usecase);
4229 out->devices = new_dev;
4230 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004231
4232 if (!same_dev) {
4233 // on device switch force swap, lower functions will make sure
4234 // to check if swap is allowed or not.
4235 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304236 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004237 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304238 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4239 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004240 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304241 pthread_mutex_lock(&out->compr_mute_lock);
4242 out->a2dp_compress_mute = false;
4243 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4244 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004245 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4246 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304247 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004248 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004249 }
4250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004252 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004253
4254 /*handles device and call state changes*/
4255 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004257 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004258
4259 if (out == adev->primary_output) {
4260 pthread_mutex_lock(&adev->lock);
4261 audio_extn_set_parameters(adev, parms);
4262 pthread_mutex_unlock(&adev->lock);
4263 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004264 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004265 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004266 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004267
4268 audio_extn_dts_create_state_notifier_node(out->usecase);
4269 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4270 popcount(out->channel_mask),
4271 out->playback_started);
4272
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004273 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004274 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004275
Surendar Karkaf51b5842018-04-26 11:28:38 +05304276 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4277 sizeof(value));
4278 if (err >= 0) {
4279 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4280 audio_extn_send_dual_mono_mixing_coefficients(out);
4281 }
4282
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304283 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4284 if (err >= 0) {
4285 strlcpy(out->profile, value, sizeof(out->profile));
4286 ALOGV("updating stream profile with value '%s'", out->profile);
4287 lock_output_stream(out);
4288 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4289 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004290 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304291 out->sample_rate, out->bit_width,
4292 out->channel_mask, out->profile,
4293 &out->app_type_cfg);
4294 pthread_mutex_unlock(&out->lock);
4295 }
4296
Alexy Joseph98988832017-01-13 14:56:59 -08004297 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004298 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4299 // and vendor.audio.hal.output.suspend.supported is set to true
4300 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004301 //check suspend parameter only for low latency and if the property
4302 //is enabled
4303 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4304 ALOGI("%s: got suspend_playback %s", __func__, value);
4305 lock_output_stream(out);
4306 if (!strncmp(value, "false", 5)) {
4307 //suspend_playback=false is supposed to set QOS value back to 75%
4308 //the mixer control sent with value Enable will achieve that
4309 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4310 } else if (!strncmp (value, "true", 4)) {
4311 //suspend_playback=true is supposed to remove QOS value
4312 //resetting the mixer control will set the default value
4313 //for the mixer control which is Disable and this removes the QOS vote
4314 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4315 } else {
4316 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4317 " got %s", __func__, value);
4318 ret = -1;
4319 }
4320
4321 if (ret != 0) {
4322 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4323 __func__, out->pm_qos_mixer_path, ret);
4324 }
4325
4326 pthread_mutex_unlock(&out->lock);
4327 }
4328 }
4329 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304331error:
Eric Laurent994a6932013-07-17 11:51:42 -07004332 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 return ret;
4334}
4335
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004336static bool stream_get_parameter_channels(struct str_parms *query,
4337 struct str_parms *reply,
4338 audio_channel_mask_t *supported_channel_masks) {
4339 int ret = -1;
4340 char value[512];
4341 bool first = true;
4342 size_t i, j;
4343
4344 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4345 ret = 0;
4346 value[0] = '\0';
4347 i = 0;
4348 while (supported_channel_masks[i] != 0) {
4349 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4350 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4351 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304352 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004353
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304354 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004355 first = false;
4356 break;
4357 }
4358 }
4359 i++;
4360 }
4361 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4362 }
4363 return ret == 0;
4364}
4365
4366static bool stream_get_parameter_formats(struct str_parms *query,
4367 struct str_parms *reply,
4368 audio_format_t *supported_formats) {
4369 int ret = -1;
4370 char value[256];
4371 size_t i, j;
4372 bool first = true;
4373
4374 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4375 ret = 0;
4376 value[0] = '\0';
4377 i = 0;
4378 while (supported_formats[i] != 0) {
4379 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4380 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4381 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304382 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004383 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304384 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004385 first = false;
4386 break;
4387 }
4388 }
4389 i++;
4390 }
4391 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4392 }
4393 return ret == 0;
4394}
4395
4396static bool stream_get_parameter_rates(struct str_parms *query,
4397 struct str_parms *reply,
4398 uint32_t *supported_sample_rates) {
4399
4400 int i;
4401 char value[256];
4402 int ret = -1;
4403 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4404 ret = 0;
4405 value[0] = '\0';
4406 i=0;
4407 int cursor = 0;
4408 while (supported_sample_rates[i]) {
4409 int avail = sizeof(value) - cursor;
4410 ret = snprintf(value + cursor, avail, "%s%d",
4411 cursor > 0 ? "|" : "",
4412 supported_sample_rates[i]);
4413 if (ret < 0 || ret >= avail) {
4414 // if cursor is at the last element of the array
4415 // overwrite with \0 is duplicate work as
4416 // snprintf already put a \0 in place.
4417 // else
4418 // we had space to write the '|' at value[cursor]
4419 // (which will be overwritten) or no space to fill
4420 // the first element (=> cursor == 0)
4421 value[cursor] = '\0';
4422 break;
4423 }
4424 cursor += ret;
4425 ++i;
4426 }
4427 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4428 value);
4429 }
4430 return ret >= 0;
4431}
4432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4434{
4435 struct stream_out *out = (struct stream_out *)stream;
4436 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004437 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438 char value[256];
4439 struct str_parms *reply = str_parms_create();
4440 size_t i, j;
4441 int ret;
4442 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004443
4444 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004445 if (reply) {
4446 str_parms_destroy(reply);
4447 }
4448 if (query) {
4449 str_parms_destroy(query);
4450 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004451 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4452 return NULL;
4453 }
4454
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004455 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4457 if (ret >= 0) {
4458 value[0] = '\0';
4459 i = 0;
4460 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004461 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4462 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004464 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004466 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467 first = false;
4468 break;
4469 }
4470 }
4471 i++;
4472 }
4473 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4474 str = str_parms_to_str(reply);
4475 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004476 voice_extn_out_get_parameters(out, query, reply);
4477 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004479
Alexy Joseph62142aa2015-11-16 15:10:34 -08004480
4481 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4482 if (ret >= 0) {
4483 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304484 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4485 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004486 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304487 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004488 } else {
4489 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304490 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004491 }
4492 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004493 if (str)
4494 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004495 str = str_parms_to_str(reply);
4496 }
4497
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004498 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4499 if (ret >= 0) {
4500 value[0] = '\0';
4501 i = 0;
4502 first = true;
4503 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004504 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4505 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004506 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004507 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004508 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004509 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004510 first = false;
4511 break;
4512 }
4513 }
4514 i++;
4515 }
4516 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004517 if (str)
4518 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004519 str = str_parms_to_str(reply);
4520 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004521
4522 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4523 if (ret >= 0) {
4524 value[0] = '\0';
4525 i = 0;
4526 first = true;
4527 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004528 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4529 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004530 if (!first) {
4531 strlcat(value, "|", sizeof(value));
4532 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004533 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004534 first = false;
4535 break;
4536 }
4537 }
4538 i++;
4539 }
4540 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4541 if (str)
4542 free(str);
4543 str = str_parms_to_str(reply);
4544 }
4545
Alexy Joseph98988832017-01-13 14:56:59 -08004546 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4547 //only low latency track supports suspend_resume
4548 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004549 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004550 if (str)
4551 free(str);
4552 str = str_parms_to_str(reply);
4553 }
4554
4555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 str_parms_destroy(query);
4557 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004558 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559 return str;
4560}
4561
4562static uint32_t out_get_latency(const struct audio_stream_out *stream)
4563{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004564 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004566 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567
Alexy Josephaa54c872014-12-03 02:46:47 -08004568 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304569 lock_output_stream(out);
4570 latency = audio_extn_utils_compress_get_dsp_latency(out);
4571 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004572 } else if ((out->realtime) ||
4573 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004574 // since the buffer won't be filled up faster than realtime,
4575 // return a smaller number
4576 if (out->config.rate)
4577 period_ms = (out->af_period_multiplier * out->config.period_size *
4578 1000) / (out->config.rate);
4579 else
4580 period_ms = 0;
4581 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004582 } else {
4583 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004584 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004585 }
4586
yidongh0515e042017-07-06 15:00:34 +08004587 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004588 latency += audio_extn_a2dp_get_encoder_latency();
4589
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304590 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004591 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592}
4593
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304594static float AmpToDb(float amplification)
4595{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304596 float db = DSD_VOLUME_MIN_DB;
4597 if (amplification > 0) {
4598 db = 20 * log10(amplification);
4599 if(db < DSD_VOLUME_MIN_DB)
4600 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304601 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304602 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304603}
4604
Arun Mirpuri5d170872019-03-26 13:21:31 -07004605static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4606 float right)
4607{
4608 struct stream_out *out = (struct stream_out *)stream;
4609 long volume = 0;
4610 char mixer_ctl_name[128] = "";
4611 struct audio_device *adev = out->dev;
4612 struct mixer_ctl *ctl = NULL;
4613 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4614 PCM_PLAYBACK);
4615
4616 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4617 "Playback %d Volume", pcm_device_id);
4618 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4619 if (!ctl) {
4620 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4621 __func__, mixer_ctl_name);
4622 return -EINVAL;
4623 }
4624 if (left != right)
4625 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4626 __func__, left, right);
4627 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4628 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4629 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4630 __func__, mixer_ctl_name, volume);
4631 return -EINVAL;
4632 }
4633 return 0;
4634}
4635
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304636static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4637 float right)
4638{
4639 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304640 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304641 char mixer_ctl_name[128];
4642 struct audio_device *adev = out->dev;
4643 struct mixer_ctl *ctl;
4644 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4645 PCM_PLAYBACK);
4646
4647 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4648 "Compress Playback %d Volume", pcm_device_id);
4649 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4650 if (!ctl) {
4651 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4652 __func__, mixer_ctl_name);
4653 return -EINVAL;
4654 }
4655 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4656 __func__, mixer_ctl_name, left, right);
4657 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4658 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4659 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4660
4661 return 0;
4662}
4663
Zhou Song2b8f28f2017-09-11 10:51:38 +08004664static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4665 float right)
4666{
4667 struct stream_out *out = (struct stream_out *)stream;
4668 char mixer_ctl_name[] = "App Type Gain";
4669 struct audio_device *adev = out->dev;
4670 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304671 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004672
4673 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4674 if (!ctl) {
4675 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4676 __func__, mixer_ctl_name);
4677 return -EINVAL;
4678 }
4679
4680 set_values[0] = 0; //0: Rx Session 1:Tx Session
4681 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304682 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4683 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004684
4685 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4686 return 0;
4687}
4688
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304689static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4690 float right)
4691{
4692 struct stream_out *out = (struct stream_out *)stream;
4693 /* Volume control for pcm playback */
4694 if (left != right) {
4695 return -EINVAL;
4696 } else {
4697 char mixer_ctl_name[128];
4698 struct audio_device *adev = out->dev;
4699 struct mixer_ctl *ctl;
4700 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4701 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4702 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4703 if (!ctl) {
4704 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4705 return -EINVAL;
4706 }
4707
4708 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4709 int ret = mixer_ctl_set_value(ctl, 0, volume);
4710 if (ret < 0) {
4711 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4712 return -EINVAL;
4713 }
4714
4715 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4716
4717 return 0;
4718 }
4719}
4720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721static int out_set_volume(struct audio_stream_out *stream, float left,
4722 float right)
4723{
Eric Laurenta9024de2013-04-04 09:19:12 -07004724 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004725 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304726 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004727
Arun Mirpuri5d170872019-03-26 13:21:31 -07004728 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004729 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4730 /* only take left channel into account: the API is for stereo anyway */
4731 out->muted = (left == 0.0f);
4732 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004733 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304734 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004735 /*
4736 * Set mute or umute on HDMI passthrough stream.
4737 * Only take left channel into account.
4738 * Mute is 0 and unmute 1
4739 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304740 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304741 } else if (out->format == AUDIO_FORMAT_DSD){
4742 char mixer_ctl_name[128] = "DSD Volume";
4743 struct audio_device *adev = out->dev;
4744 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4745
4746 if (!ctl) {
4747 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4748 __func__, mixer_ctl_name);
4749 return -EINVAL;
4750 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304751 volume[0] = (long)(AmpToDb(left));
4752 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304753 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4754 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004755 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304756 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004757 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304758 if (!out->a2dp_compress_mute)
4759 ret = out_set_compr_volume(stream, left, right);
4760 out->volume_l = left;
4761 out->volume_r = right;
4762 pthread_mutex_unlock(&out->compr_mute_lock);
4763 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004764 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004765 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004766 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4767 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4768 if (!out->standby) {
4769 audio_extn_utils_send_app_type_gain(out->dev,
4770 out->app_type_cfg.app_type,
4771 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004772 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004773 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004774 out->volume_l = left;
4775 out->volume_r = right;
4776 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004777 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4778 ALOGV("%s: MMAP set volume called", __func__);
4779 if (!out->standby)
4780 ret = out_set_mmap_volume(stream, left, right);
4781 out->volume_l = left;
4782 out->volume_r = right;
4783 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304784 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304785 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4786 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304787 /* Volume control for pcm playback */
4788 if (!out->standby)
4789 ret = out_set_pcm_volume(stream, left, right);
4790 else
4791 out->apply_volume = true;
4792
4793 out->volume_l = left;
4794 out->volume_r = right;
4795 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004796 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 return -ENOSYS;
4799}
4800
Zhou Songc9672822017-08-16 16:01:39 +08004801static void update_frames_written(struct stream_out *out, size_t bytes)
4802{
4803 size_t bpf = 0;
4804
4805 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4806 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4807 bpf = 1;
4808 else if (!is_offload_usecase(out->usecase))
4809 bpf = audio_bytes_per_sample(out->format) *
4810 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004811
4812 pthread_mutex_lock(&out->position_query_lock);
4813 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004814 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004815 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4816 }
4817 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004818}
4819
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004820int split_and_write_audio_haptic_data(struct stream_out *out,
4821 const void *buffer, size_t bytes_to_write)
4822{
4823 struct audio_device *adev = out->dev;
4824
4825 int ret = 0;
4826 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4827 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4828 size_t frame_size = channel_count * bytes_per_sample;
4829 size_t frame_count = bytes_to_write / frame_size;
4830
4831 bool force_haptic_path =
4832 property_get_bool("vendor.audio.test_haptic", false);
4833
4834 // extract Haptics data from Audio buffer
4835 bool alloc_haptic_buffer = false;
4836 int haptic_channel_count = adev->haptics_config.channels;
4837 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4838 size_t audio_frame_size = frame_size - haptic_frame_size;
4839 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4840
4841 if (adev->haptic_buffer == NULL) {
4842 alloc_haptic_buffer = true;
4843 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4844 free(adev->haptic_buffer);
4845 adev->haptic_buffer_size = 0;
4846 alloc_haptic_buffer = true;
4847 }
4848
4849 if (alloc_haptic_buffer) {
4850 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4851 adev->haptic_buffer_size = total_haptic_buffer_size;
4852 }
4853
4854 size_t src_index = 0, aud_index = 0, hap_index = 0;
4855 uint8_t *audio_buffer = (uint8_t *)buffer;
4856 uint8_t *haptic_buffer = adev->haptic_buffer;
4857
4858 // This is required for testing only. This works for stereo data only.
4859 // One channel is fed to audio stream and other to haptic stream for testing.
4860 if (force_haptic_path)
4861 audio_frame_size = haptic_frame_size = bytes_per_sample;
4862
4863 for (size_t i = 0; i < frame_count; i++) {
4864 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4865 audio_frame_size);
4866 aud_index += audio_frame_size;
4867 src_index += audio_frame_size;
4868
4869 if (adev->haptic_pcm)
4870 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4871 haptic_frame_size);
4872 hap_index += haptic_frame_size;
4873 src_index += haptic_frame_size;
4874
4875 // This is required for testing only.
4876 // Discard haptic channel data.
4877 if (force_haptic_path)
4878 src_index += haptic_frame_size;
4879 }
4880
4881 // write to audio pipeline
4882 ret = pcm_write(out->pcm, (void *)audio_buffer,
4883 frame_count * audio_frame_size);
4884
4885 // write to haptics pipeline
4886 if (adev->haptic_pcm)
4887 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4888 frame_count * haptic_frame_size);
4889
4890 return ret;
4891}
4892
Aalique Grahame22e49102018-12-18 14:23:57 -08004893#ifdef NO_AUDIO_OUT
4894static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4895 const void *buffer __unused, size_t bytes)
4896{
4897 struct stream_out *out = (struct stream_out *)stream;
4898
4899 /* No Output device supported other than BT for playback.
4900 * Sleep for the amount of buffer duration
4901 */
4902 lock_output_stream(out);
4903 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4904 (const struct audio_stream_out *)&out->stream) /
4905 out_get_sample_rate(&out->stream.common));
4906 pthread_mutex_unlock(&out->lock);
4907 return bytes;
4908}
4909#endif
4910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4912 size_t bytes)
4913{
4914 struct stream_out *out = (struct stream_out *)stream;
4915 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004916 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304917 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004918 const size_t frame_size = audio_stream_out_frame_size(stream);
4919 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05304920 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921
Haynes Mathew George380745d2017-10-04 15:27:45 -07004922 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004923 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304924
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304925 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004926
Dhananjay Kumarac341582017-02-23 23:42:25 +05304927 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304928 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304929 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4930 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004931 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304932 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304933 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304934 ALOGD(" %s: sound card is not active/SSR state", __func__);
4935 ret= -EIO;
4936 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304937 }
4938 }
4939
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304940 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304941 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304942 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304943 goto exit;
4944 }
4945
Haynes Mathew George16081042017-05-31 17:16:49 -07004946 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4947 ret = -EINVAL;
4948 goto exit;
4949 }
4950
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304951 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4952 !out->is_iec61937_info_available) {
4953
4954 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4955 out->is_iec61937_info_available = true;
4956 } else if (audio_extn_passthru_is_enabled()) {
4957 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304958 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304959
4960 if((out->format == AUDIO_FORMAT_DTS) ||
4961 (out->format == AUDIO_FORMAT_DTS_HD)) {
4962 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4963 buffer, bytes);
4964 if (ret) {
4965 if (ret != -ENOSYS) {
4966 out->is_iec61937_info_available = false;
4967 ALOGD("iec61937 transmission info not yet updated retry");
4968 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304969 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304970 /* if stream has started and after that there is
4971 * stream config change (iec transmission config)
4972 * then trigger select_device to update backend configuration.
4973 */
4974 out->stream_config_changed = true;
4975 pthread_mutex_lock(&adev->lock);
4976 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304977 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4978 ret = -EINVAL;
4979 goto exit;
4980 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304981 pthread_mutex_unlock(&adev->lock);
4982 out->stream_config_changed = false;
4983 out->is_iec61937_info_available = true;
4984 }
4985 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304986
Garmond Leung317cbf12017-09-13 16:20:50 -07004987 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304988 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4989 (out->is_iec61937_info_available == true)) {
4990 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4991 ret = -EINVAL;
4992 goto exit;
4993 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304994 }
4995 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304996
4997 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004998 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004999 if (!(out->devices &
5000 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305001 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305002 ret = -EIO;
5003 goto exit;
5004 }
5005 }
5006 }
5007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005009 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005010 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005011 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5012 ret = voice_extn_compress_voip_start_output_stream(out);
5013 else
5014 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005015 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005016 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005018 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019 goto exit;
5020 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305021 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005022 if (last_known_cal_step != -1) {
5023 ALOGD("%s: retry previous failed cal level set", __func__);
5024 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305025 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005026 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305027
5028 if ((out->is_iec61937_info_available == true) &&
5029 (audio_extn_passthru_is_passthrough_stream(out))&&
5030 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5031 ret = -EINVAL;
5032 goto exit;
5033 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305034 if (out->set_dual_mono)
5035 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037
Ashish Jain81eb2a82015-05-13 10:52:34 +05305038 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005039 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305040 adev->is_channel_status_set = true;
5041 }
5042
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305043 if ((adev->use_old_pspd_mix_ctrl == true) &&
5044 (out->pspd_coeff_sent == false)) {
5045 /*
5046 * Need to resend pspd coefficients after stream started for
5047 * older kernel version as it does not save the coefficients
5048 * and also stream has to be started for coeff to apply.
5049 */
5050 usecase = get_usecase_from_list(adev, out->usecase);
5051 if (usecase != NULL) {
5052 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5053 out->pspd_coeff_sent = true;
5054 }
5055 }
5056
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005057 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005058 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005059 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005060 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005061 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5062 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305063 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5064 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005065 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305066 out->send_next_track_params = false;
5067 out->is_compr_metadata_avail = false;
5068 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005069 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305070 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305071 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005072
Ashish Jain83a6cc22016-06-28 14:34:17 +05305073 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305074 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305075 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305076 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005077 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305078 return -EINVAL;
5079 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305080 audio_format_t dst_format = out->hal_op_format;
5081 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305082
Dieter Luecking5d57def2018-09-07 14:23:37 +02005083 /* prevent division-by-zero */
5084 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5085 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5086 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5087 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305088 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005089 ATRACE_END();
5090 return -EINVAL;
5091 }
5092
Ashish Jainf1eaa582016-05-23 20:54:24 +05305093 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5094 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5095
Ashish Jain83a6cc22016-06-28 14:34:17 +05305096 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305097 dst_format,
5098 buffer,
5099 src_format,
5100 frames);
5101
Ashish Jain83a6cc22016-06-28 14:34:17 +05305102 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305103 bytes_to_write);
5104
5105 /*Convert written bytes in audio flinger format*/
5106 if (ret > 0)
5107 ret = ((ret * format_to_bitwidth_table[out->format]) /
5108 format_to_bitwidth_table[dst_format]);
5109 }
5110 } else
5111 ret = compress_write(out->compr, buffer, bytes);
5112
Zhou Songc9672822017-08-16 16:01:39 +08005113 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5114 update_frames_written(out, bytes);
5115
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305116 if (ret < 0)
5117 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005118 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305119 /*msg to cb thread only if non blocking write is enabled*/
5120 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305121 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005122 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305123 } else if (-ENETRESET == ret) {
5124 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305125 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305126 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305127 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005128 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305129 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005130 }
Ashish Jain5106d362016-05-11 19:23:33 +05305131
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305132 /* Call compr start only when non-zero bytes of data is there to be rendered */
5133 if (!out->playback_started && ret > 0) {
5134 int status = compress_start(out->compr);
5135 if (status < 0) {
5136 ret = status;
5137 ALOGE("%s: compr start failed with err %d", __func__, errno);
5138 goto exit;
5139 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005140 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005141 out->playback_started = 1;
5142 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005143
5144 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5145 popcount(out->channel_mask),
5146 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005147 }
5148 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005149 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005150 return ret;
5151 } else {
5152 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005153 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005154 if (out->muted)
5155 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005156 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5157 __func__, frames, frame_size, bytes_to_write);
5158
Aalique Grahame22e49102018-12-18 14:23:57 -08005159 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005160 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005161 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5162 int16_t *src = (int16_t *)buffer;
5163 int16_t *dst = (int16_t *)buffer;
5164
5165 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5166 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005167 "out_write called for %s use case with wrong properties",
5168 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005169
5170 /*
5171 * FIXME: this can be removed once audio flinger mixer supports
5172 * mono output
5173 */
5174
5175 /*
5176 * Code below goes over each frame in the buffer and adds both
5177 * L and R samples and then divides by 2 to convert to mono
5178 */
5179 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5180 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5181 }
5182 bytes_to_write /= 2;
5183 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005184
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305185 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005186
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005187 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005188
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005189 if (out->config.rate)
5190 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5191 out->config.rate;
5192
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005193 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005194 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5195
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005196 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005197 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005198 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305199 out->convert_buffer != NULL) {
5200
5201 memcpy_by_audio_format(out->convert_buffer,
5202 out->hal_op_format,
5203 buffer,
5204 out->hal_ip_format,
5205 out->config.period_size * out->config.channels);
5206
5207 ret = pcm_write(out->pcm, out->convert_buffer,
5208 (out->config.period_size *
5209 out->config.channels *
5210 format_to_bitwidth_table[out->hal_op_format]));
5211 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305212 /*
5213 * To avoid underrun in DSP when the application is not pumping
5214 * data at required rate, check for the no. of bytes and ignore
5215 * pcm_write if it is less than actual buffer size.
5216 * It is a work around to a change in compress VOIP driver.
5217 */
5218 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5219 bytes < (out->config.period_size * out->config.channels *
5220 audio_bytes_per_sample(out->format))) {
5221 size_t voip_buf_size =
5222 out->config.period_size * out->config.channels *
5223 audio_bytes_per_sample(out->format);
5224 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5225 __func__, bytes, voip_buf_size);
5226 usleep(((uint64_t)voip_buf_size - bytes) *
5227 1000000 / audio_stream_out_frame_size(stream) /
5228 out_get_sample_rate(&out->stream.common));
5229 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005230 } else {
5231 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5232 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5233 else
5234 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5235 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305236 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005237
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005238 release_out_focus(out);
5239
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305240 if (ret < 0)
5241 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005242 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305243 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 }
5246
5247exit:
Zhou Songc9672822017-08-16 16:01:39 +08005248 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305249 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305250 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252 pthread_mutex_unlock(&out->lock);
5253
5254 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005255 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005256 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305257 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305258 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305259 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305260 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305261 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305262 out->standby = true;
5263 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305264 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005265 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5266 /* prevent division-by-zero */
5267 uint32_t stream_size = audio_stream_out_frame_size(stream);
5268 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005269
Dieter Luecking5d57def2018-09-07 14:23:37 +02005270 if ((stream_size == 0) || (srate == 0)) {
5271 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5272 ATRACE_END();
5273 return -EINVAL;
5274 }
5275 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5276 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005277 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305278 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005279 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005280 return ret;
5281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005282 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005283 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005284 return bytes;
5285}
5286
5287static int out_get_render_position(const struct audio_stream_out *stream,
5288 uint32_t *dsp_frames)
5289{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005290 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005291
5292 if (dsp_frames == NULL)
5293 return -EINVAL;
5294
5295 *dsp_frames = 0;
5296 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005297 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305298
5299 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5300 * this operation and adev_close_output_stream(where out gets reset).
5301 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305302 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005303 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305304 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005305 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305306 return 0;
5307 }
5308
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005309 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305310 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305311 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005312 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305313 if (ret < 0)
5314 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005315 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305316 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005317 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305318 if (-ENETRESET == ret) {
5319 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305320 out->card_status = CARD_STATUS_OFFLINE;
5321 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305322 } else if(ret < 0) {
5323 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305324 ret = -EINVAL;
5325 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305326 /*
5327 * Handle corner case where compress session is closed during SSR
5328 * and timestamp is queried
5329 */
5330 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305331 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305332 } else if (out->prev_card_status_offline) {
5333 ALOGE("ERROR: previously sound card was offline,return error");
5334 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305335 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305336 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005337 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305338 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305339 pthread_mutex_unlock(&out->lock);
5340 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005341 } else if (audio_is_linear_pcm(out->format)) {
5342 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005343 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005344 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005345 } else
5346 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347}
5348
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005349static int out_add_audio_effect(const struct audio_stream *stream __unused,
5350 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351{
5352 return 0;
5353}
5354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005355static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5356 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005357{
5358 return 0;
5359}
5360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005361static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5362 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305364 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005365}
5366
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005367static int out_get_presentation_position(const struct audio_stream_out *stream,
5368 uint64_t *frames, struct timespec *timestamp)
5369{
5370 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305371 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005372 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005373
Ashish Jain5106d362016-05-11 19:23:33 +05305374 /* below piece of code is not guarded against any lock because audioFliner serializes
5375 * this operation and adev_close_output_stream( where out gets reset).
5376 */
5377 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305378 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005379 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305380 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5381 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5382 return 0;
5383 }
5384
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005385 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005386
Ashish Jain5106d362016-05-11 19:23:33 +05305387 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5388 ret = compress_get_tstamp(out->compr, &dsp_frames,
5389 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005390 // Adjustment accounts for A2dp encoder latency with offload usecases
5391 // Note: Encoder latency is returned in ms.
5392 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5393 unsigned long offset =
5394 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5395 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5396 }
Ashish Jain5106d362016-05-11 19:23:33 +05305397 ALOGVV("%s rendered frames %ld sample_rate %d",
5398 __func__, dsp_frames, out->sample_rate);
5399 *frames = dsp_frames;
5400 if (ret < 0)
5401 ret = -errno;
5402 if (-ENETRESET == ret) {
5403 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305404 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305405 ret = -EINVAL;
5406 } else
5407 ret = 0;
5408 /* this is the best we can do */
5409 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005410 } else {
5411 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005412 unsigned int avail;
5413 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5414 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5415 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5416 // This adjustment accounts for buffering after app processor.
5417 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005418 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005419 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005420
Weiyin Jiangd4633762018-03-16 12:05:03 +08005421 // Adjustment accounts for A2dp encoder latency with non offload usecases
5422 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5423 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5424 signed_frames -=
5425 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5426 }
5427
5428 // It would be unusual for this value to be negative, but check just in case ...
5429 if (signed_frames >= 0) {
5430 *frames = signed_frames;
5431 ret = 0;
5432 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005433 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305434 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305435 *frames = out->written;
5436 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305437 if (is_offload_usecase(out->usecase))
5438 ret = -EINVAL;
5439 else
5440 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005441 }
5442 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005443 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005444 return ret;
5445}
5446
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005447static int out_set_callback(struct audio_stream_out *stream,
5448 stream_callback_t callback, void *cookie)
5449{
5450 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005451 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005452
5453 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005454 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005455 out->client_callback = callback;
5456 out->client_cookie = cookie;
5457 if (out->adsp_hdlr_stream_handle) {
5458 ret = audio_extn_adsp_hdlr_stream_set_callback(
5459 out->adsp_hdlr_stream_handle,
5460 callback,
5461 cookie);
5462 if (ret)
5463 ALOGW("%s:adsp hdlr callback registration failed %d",
5464 __func__, ret);
5465 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005466 pthread_mutex_unlock(&out->lock);
5467 return 0;
5468}
5469
5470static int out_pause(struct audio_stream_out* stream)
5471{
5472 struct stream_out *out = (struct stream_out *)stream;
5473 int status = -ENOSYS;
5474 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005475 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005476 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005477 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005478 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305479 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305480 status = compress_pause(out->compr);
5481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005482 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005483
Mingming Yin21854652016-04-13 11:54:02 -07005484 if (audio_extn_passthru_is_active()) {
5485 ALOGV("offload use case, pause passthru");
5486 audio_extn_passthru_on_pause(out);
5487 }
5488
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305489 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005490 audio_extn_dts_notify_playback_state(out->usecase, 0,
5491 out->sample_rate, popcount(out->channel_mask),
5492 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005493 }
5494 pthread_mutex_unlock(&out->lock);
5495 }
5496 return status;
5497}
5498
5499static int out_resume(struct audio_stream_out* stream)
5500{
5501 struct stream_out *out = (struct stream_out *)stream;
5502 int status = -ENOSYS;
5503 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005504 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005505 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005506 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005507 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005508 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305509 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305510 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005511 }
5512 if (!status) {
5513 out->offload_state = OFFLOAD_STATE_PLAYING;
5514 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305515 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005516 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5517 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005518 }
5519 pthread_mutex_unlock(&out->lock);
5520 }
5521 return status;
5522}
5523
5524static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5525{
5526 struct stream_out *out = (struct stream_out *)stream;
5527 int status = -ENOSYS;
5528 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005529 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005530 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005531 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5532 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5533 else
5534 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5535 pthread_mutex_unlock(&out->lock);
5536 }
5537 return status;
5538}
5539
5540static int out_flush(struct audio_stream_out* stream)
5541{
5542 struct stream_out *out = (struct stream_out *)stream;
5543 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005544 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005545 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005546 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005547 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5548 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005549 } else {
5550 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5551 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005552 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005553 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005554 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005555 return 0;
5556 }
5557 return -ENOSYS;
5558}
5559
Haynes Mathew George16081042017-05-31 17:16:49 -07005560static int out_stop(const struct audio_stream_out* stream)
5561{
5562 struct stream_out *out = (struct stream_out *)stream;
5563 struct audio_device *adev = out->dev;
5564 int ret = -ENOSYS;
5565
5566 ALOGV("%s", __func__);
5567 pthread_mutex_lock(&adev->lock);
5568 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5569 out->playback_started && out->pcm != NULL) {
5570 pcm_stop(out->pcm);
5571 ret = stop_output_stream(out);
5572 out->playback_started = false;
5573 }
5574 pthread_mutex_unlock(&adev->lock);
5575 return ret;
5576}
5577
5578static int out_start(const struct audio_stream_out* stream)
5579{
5580 struct stream_out *out = (struct stream_out *)stream;
5581 struct audio_device *adev = out->dev;
5582 int ret = -ENOSYS;
5583
5584 ALOGV("%s", __func__);
5585 pthread_mutex_lock(&adev->lock);
5586 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5587 !out->playback_started && out->pcm != NULL) {
5588 ret = start_output_stream(out);
5589 if (ret == 0) {
5590 out->playback_started = true;
5591 }
5592 }
5593 pthread_mutex_unlock(&adev->lock);
5594 return ret;
5595}
5596
5597/*
5598 * Modify config->period_count based on min_size_frames
5599 */
5600static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5601{
5602 int periodCountRequested = (min_size_frames + config->period_size - 1)
5603 / config->period_size;
5604 int periodCount = MMAP_PERIOD_COUNT_MIN;
5605
5606 ALOGV("%s original config.period_size = %d config.period_count = %d",
5607 __func__, config->period_size, config->period_count);
5608
5609 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5610 periodCount *= 2;
5611 }
5612 config->period_count = periodCount;
5613
5614 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5615}
5616
5617static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5618 int32_t min_size_frames,
5619 struct audio_mmap_buffer_info *info)
5620{
5621 struct stream_out *out = (struct stream_out *)stream;
5622 struct audio_device *adev = out->dev;
5623 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005624 unsigned int offset1 = 0;
5625 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005626 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005627 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005628 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005629
Arun Mirpuri5d170872019-03-26 13:21:31 -07005630 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305631 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005632 pthread_mutex_lock(&adev->lock);
5633
Sharad Sanglec6f32552018-05-04 16:15:38 +05305634 if (CARD_STATUS_OFFLINE == out->card_status ||
5635 CARD_STATUS_OFFLINE == adev->card_status) {
5636 ALOGW("out->card_status or adev->card_status offline, try again");
5637 ret = -EIO;
5638 goto exit;
5639 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005640 if (info == NULL || min_size_frames == 0) {
5641 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5642 ret = -EINVAL;
5643 goto exit;
5644 }
5645 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5646 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5647 ret = -ENOSYS;
5648 goto exit;
5649 }
5650 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5651 if (out->pcm_device_id < 0) {
5652 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5653 __func__, out->pcm_device_id, out->usecase);
5654 ret = -EINVAL;
5655 goto exit;
5656 }
5657
5658 adjust_mmap_period_count(&out->config, min_size_frames);
5659
Arun Mirpuri5d170872019-03-26 13:21:31 -07005660 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005661 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5662 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5663 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305664 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305665 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5666 out->card_status = CARD_STATUS_OFFLINE;
5667 adev->card_status = CARD_STATUS_OFFLINE;
5668 ret = -EIO;
5669 goto exit;
5670 }
5671
Haynes Mathew George16081042017-05-31 17:16:49 -07005672 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5673 step = "open";
5674 ret = -ENODEV;
5675 goto exit;
5676 }
5677 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5678 if (ret < 0) {
5679 step = "begin";
5680 goto exit;
5681 }
5682 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005683 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005684 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005685 ret = platform_get_mmap_data_fd(adev->platform,
5686 out->pcm_device_id, 0 /*playback*/,
5687 &info->shared_memory_fd,
5688 &mmap_size);
5689 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005690 // Fall back to non exclusive mode
5691 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5692 } else {
5693 if (mmap_size < buffer_size) {
5694 step = "mmap";
5695 goto exit;
5696 }
5697 // FIXME: indicate exclusive mode support by returning a negative buffer size
5698 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005699 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005700 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005701 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005702
5703 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5704 if (ret < 0) {
5705 step = "commit";
5706 goto exit;
5707 }
5708
5709 out->standby = false;
5710 ret = 0;
5711
Arun Mirpuri5d170872019-03-26 13:21:31 -07005712 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005713 __func__, info->shared_memory_address, info->buffer_size_frames);
5714
5715exit:
5716 if (ret != 0) {
5717 if (out->pcm == NULL) {
5718 ALOGE("%s: %s - %d", __func__, step, ret);
5719 } else {
5720 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5721 pcm_close(out->pcm);
5722 out->pcm = NULL;
5723 }
5724 }
5725 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305726 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005727 return ret;
5728}
5729
5730static int out_get_mmap_position(const struct audio_stream_out *stream,
5731 struct audio_mmap_position *position)
5732{
5733 struct stream_out *out = (struct stream_out *)stream;
5734 ALOGVV("%s", __func__);
5735 if (position == NULL) {
5736 return -EINVAL;
5737 }
5738 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005739 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005740 return -ENOSYS;
5741 }
5742 if (out->pcm == NULL) {
5743 return -ENOSYS;
5744 }
5745
5746 struct timespec ts = { 0, 0 };
5747 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5748 if (ret < 0) {
5749 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5750 return ret;
5751 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005752 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005753 return 0;
5754}
5755
5756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757/** audio_stream_in implementation **/
5758static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5759{
5760 struct stream_in *in = (struct stream_in *)stream;
5761
5762 return in->config.rate;
5763}
5764
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005765static int in_set_sample_rate(struct audio_stream *stream __unused,
5766 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005767{
5768 return -ENOSYS;
5769}
5770
5771static size_t in_get_buffer_size(const struct audio_stream *stream)
5772{
5773 struct stream_in *in = (struct stream_in *)stream;
5774
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005775 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5776 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005777 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5778 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 -07005779 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5780 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305781 else if(audio_extn_cin_attached_usecase(in->usecase))
5782 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005783
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005784 return in->config.period_size * in->af_period_multiplier *
5785 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005786}
5787
5788static uint32_t in_get_channels(const struct audio_stream *stream)
5789{
5790 struct stream_in *in = (struct stream_in *)stream;
5791
5792 return in->channel_mask;
5793}
5794
5795static audio_format_t in_get_format(const struct audio_stream *stream)
5796{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005797 struct stream_in *in = (struct stream_in *)stream;
5798
5799 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005800}
5801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005802static int in_set_format(struct audio_stream *stream __unused,
5803 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804{
5805 return -ENOSYS;
5806}
5807
5808static int in_standby(struct audio_stream *stream)
5809{
5810 struct stream_in *in = (struct stream_in *)stream;
5811 struct audio_device *adev = in->dev;
5812 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305813 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5814 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005815 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305816
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005817 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005818 if (!in->standby && in->is_st_session) {
5819 ALOGD("%s: sound trigger pcm stop lab", __func__);
5820 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005821 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005822 in->standby = 1;
5823 }
5824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005826 if (adev->adm_deregister_stream)
5827 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5828
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005829 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005830 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005831 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005832 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005833 voice_extn_compress_voip_close_input_stream(stream);
5834 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005835 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5836 do_stop = in->capture_started;
5837 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005838 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305839 if (audio_extn_cin_attached_usecase(in->usecase))
5840 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005841 }
5842
Arun Mirpuri5d170872019-03-26 13:21:31 -07005843 if (in->pcm) {
5844 ATRACE_BEGIN("pcm_in_close");
5845 pcm_close(in->pcm);
5846 ATRACE_END();
5847 in->pcm = NULL;
5848 }
5849
5850 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005851 adev->enable_voicerx = false;
5852 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005853 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005854 }
Quinn Malef6050362019-01-30 15:55:40 -08005855
5856 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5857 adev->num_va_sessions--;
5858
Eric Laurent150dbfe2013-02-27 14:31:02 -08005859 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005860 }
5861 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005862 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005863 return status;
5864}
5865
Aalique Grahame22e49102018-12-18 14:23:57 -08005866static int in_dump(const struct audio_stream *stream,
5867 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868{
Aalique Grahame22e49102018-12-18 14:23:57 -08005869 struct stream_in *in = (struct stream_in *)stream;
5870
5871 // We try to get the lock for consistency,
5872 // but it isn't necessary for these variables.
5873 // If we're not in standby, we may be blocked on a read.
5874 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5875 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5876 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5877 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5878
5879 if (locked) {
5880 pthread_mutex_unlock(&in->lock);
5881 }
5882
5883 // dump error info
5884 (void)error_log_dump(
5885 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887 return 0;
5888}
5889
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305890static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5891{
5892 if (!stream || !parms)
5893 return;
5894
5895 struct stream_in *in = (struct stream_in *)stream;
5896 struct audio_device *adev = in->dev;
5897
5898 card_status_t status;
5899 int card;
5900 if (parse_snd_card_status(parms, &card, &status) < 0)
5901 return;
5902
5903 pthread_mutex_lock(&adev->lock);
5904 bool valid_cb = (card == adev->snd_card);
5905 pthread_mutex_unlock(&adev->lock);
5906
5907 if (!valid_cb)
5908 return;
5909
5910 lock_input_stream(in);
5911 if (in->card_status != status)
5912 in->card_status = status;
5913 pthread_mutex_unlock(&in->lock);
5914
5915 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5916 use_case_table[in->usecase],
5917 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5918
5919 // a better solution would be to report error back to AF and let
5920 // it put the stream to standby
5921 if (status == CARD_STATUS_OFFLINE)
5922 in_standby(&in->stream.common);
5923
5924 return;
5925}
5926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005927static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5928{
5929 struct stream_in *in = (struct stream_in *)stream;
5930 struct audio_device *adev = in->dev;
5931 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005932 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005933 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005934
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305935 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005936 parms = str_parms_create_str(kvpairs);
5937
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305938 if (!parms)
5939 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005940 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005941 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005942
5943 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5944 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005945 val = atoi(value);
5946 /* no audio source uses val == 0 */
5947 if ((in->source != val) && (val != 0)) {
5948 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005949 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5950 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5951 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005952 (in->config.rate == 8000 || in->config.rate == 16000 ||
5953 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005954 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005955 err = voice_extn_compress_voip_open_input_stream(in);
5956 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005957 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005958 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005959 }
5960 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005961 }
5962 }
5963
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005964 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5965 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005966 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005967 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5968
5969 // Workaround: If routing to an non existing usb device, fail gracefully
5970 // The routing request will otherwise block during 10 second
5971 int card;
5972 if (audio_is_usb_in_device(val) &&
5973 (card = get_alive_usb_card(parms)) >= 0) {
5974
5975 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5976 ret = -ENOSYS;
5977 } else {
5978
5979 in->device = val;
5980 /* If recording is in progress, change the tx device to new device */
5981 if (!in->standby && !in->is_st_session) {
5982 ALOGV("update input routing change");
5983 // inform adm before actual routing to prevent glitches.
5984 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005985 adev->adm_on_routing_change(adev->adm_data,
5986 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005987 ret = select_devices(adev, in->usecase);
5988 }
5989 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005990 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005991 }
5992 }
5993
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305994 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5995 if (err >= 0) {
5996 strlcpy(in->profile, value, sizeof(in->profile));
5997 ALOGV("updating stream profile with value '%s'", in->profile);
5998 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5999 &adev->streams_input_cfg_list,
6000 in->device, in->flags, in->format,
6001 in->sample_rate, in->bit_width,
6002 in->profile, &in->app_type_cfg);
6003 }
6004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006005 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006006 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006007
6008 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306009error:
Eric Laurent994a6932013-07-17 11:51:42 -07006010 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006011 return ret;
6012}
6013
6014static char* in_get_parameters(const struct audio_stream *stream,
6015 const char *keys)
6016{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006017 struct stream_in *in = (struct stream_in *)stream;
6018 struct str_parms *query = str_parms_create_str(keys);
6019 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006020 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006021
6022 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006023 if (reply) {
6024 str_parms_destroy(reply);
6025 }
6026 if (query) {
6027 str_parms_destroy(query);
6028 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006029 ALOGE("in_get_parameters: failed to create query or reply");
6030 return NULL;
6031 }
6032
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006033 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006034
6035 voice_extn_in_get_parameters(in, query, reply);
6036
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006037 stream_get_parameter_channels(query, reply,
6038 &in->supported_channel_masks[0]);
6039 stream_get_parameter_formats(query, reply,
6040 &in->supported_formats[0]);
6041 stream_get_parameter_rates(query, reply,
6042 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006043 str = str_parms_to_str(reply);
6044 str_parms_destroy(query);
6045 str_parms_destroy(reply);
6046
6047 ALOGV("%s: exit: returns - %s", __func__, str);
6048 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006049}
6050
Aalique Grahame22e49102018-12-18 14:23:57 -08006051static int in_set_gain(struct audio_stream_in *stream,
6052 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006053{
Aalique Grahame22e49102018-12-18 14:23:57 -08006054 struct stream_in *in = (struct stream_in *)stream;
6055 char mixer_ctl_name[128];
6056 struct mixer_ctl *ctl;
6057 int ctl_value;
6058
6059 ALOGV("%s: gain %f", __func__, gain);
6060
6061 if (stream == NULL)
6062 return -EINVAL;
6063
6064 /* in_set_gain() only used to silence MMAP capture for now */
6065 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6066 return -ENOSYS;
6067
6068 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6069
6070 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6071 if (!ctl) {
6072 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6073 __func__, mixer_ctl_name);
6074 return -ENOSYS;
6075 }
6076
6077 if (gain < RECORD_GAIN_MIN)
6078 gain = RECORD_GAIN_MIN;
6079 else if (gain > RECORD_GAIN_MAX)
6080 gain = RECORD_GAIN_MAX;
6081 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6082
6083 mixer_ctl_set_value(ctl, 0, ctl_value);
6084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006085 return 0;
6086}
6087
6088static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6089 size_t bytes)
6090{
6091 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306092
6093 if (in == NULL) {
6094 ALOGE("%s: stream_in ptr is NULL", __func__);
6095 return -EINVAL;
6096 }
6097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006098 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306099 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306100 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006101
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006102 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306103
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006104 if (in->is_st_session) {
6105 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6106 /* Read from sound trigger HAL */
6107 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006108 if (in->standby) {
6109 adev->num_va_sessions++;
6110 in->standby = 0;
6111 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006112 pthread_mutex_unlock(&in->lock);
6113 return bytes;
6114 }
6115
Haynes Mathew George16081042017-05-31 17:16:49 -07006116 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6117 ret = -ENOSYS;
6118 goto exit;
6119 }
6120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006121 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006122 pthread_mutex_lock(&adev->lock);
6123 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6124 ret = voice_extn_compress_voip_start_input_stream(in);
6125 else
6126 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006127 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6128 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006129 pthread_mutex_unlock(&adev->lock);
6130 if (ret != 0) {
6131 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132 }
6133 in->standby = 0;
6134 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006135
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006136 // what's the duration requested by the client?
6137 long ns = 0;
6138
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306139 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006140 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6141 in->config.rate;
6142
6143 request_in_focus(in, ns);
6144 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006145
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306146 if (audio_extn_cin_attached_usecase(in->usecase)) {
6147 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6148 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306149 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006150 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306151 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006152 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006153 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006154 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006155 } else if (audio_extn_ffv_get_stream() == in) {
6156 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306157 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006158 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306159 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6160 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6161 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6162 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306163 ret = -EINVAL;
6164 goto exit;
6165 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306166 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306167 ret = -errno;
6168 }
6169 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306170 /* bytes read is always set to bytes for non compress usecases */
6171 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006172 }
6173
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006174 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006176 /*
Quinn Malef6050362019-01-30 15:55:40 -08006177 * Instead of writing zeroes here, we could trust the hardware to always
6178 * provide zeroes when muted. This is also muted with voice recognition
6179 * usecases so that other clients do not have access to voice recognition
6180 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181 */
Quinn Malef6050362019-01-30 15:55:40 -08006182 if ((ret == 0 && voice_get_mic_mute(adev) &&
6183 !voice_is_in_call_rec_stream(in) &&
6184 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6185 (adev->num_va_sessions &&
6186 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6187 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6188 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006189 memset(buffer, 0, bytes);
6190
6191exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006192 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306193 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006194 pthread_mutex_unlock(&in->lock);
6195
6196 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306197 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306198 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306199 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306200 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306201 in->standby = true;
6202 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306203 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6204 bytes_read = bytes;
6205 memset(buffer, 0, bytes);
6206 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006207 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006208 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306209 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306210 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306212 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006213}
6214
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006215static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216{
6217 return 0;
6218}
6219
Aalique Grahame22e49102018-12-18 14:23:57 -08006220static int in_get_capture_position(const struct audio_stream_in *stream,
6221 int64_t *frames, int64_t *time)
6222{
6223 if (stream == NULL || frames == NULL || time == NULL) {
6224 return -EINVAL;
6225 }
6226 struct stream_in *in = (struct stream_in *)stream;
6227 int ret = -ENOSYS;
6228
6229 lock_input_stream(in);
6230 // note: ST sessions do not close the alsa pcm driver synchronously
6231 // on standby. Therefore, we may return an error even though the
6232 // pcm stream is still opened.
6233 if (in->standby) {
6234 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6235 "%s stream in standby but pcm not NULL for non ST session", __func__);
6236 goto exit;
6237 }
6238 if (in->pcm) {
6239 struct timespec timestamp;
6240 unsigned int avail;
6241 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6242 *frames = in->frames_read + avail;
6243 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6244 ret = 0;
6245 }
6246 }
6247exit:
6248 pthread_mutex_unlock(&in->lock);
6249 return ret;
6250}
6251
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006252static int add_remove_audio_effect(const struct audio_stream *stream,
6253 effect_handle_t effect,
6254 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006256 struct stream_in *in = (struct stream_in *)stream;
6257 int status = 0;
6258 effect_descriptor_t desc;
6259
6260 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006261 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6262
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006263 if (status != 0)
6264 return status;
6265
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006266 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006267 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006268 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006269 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006270 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006271 in->enable_aec != enable &&
6272 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6273 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006274 if (!enable)
6275 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6276 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6277 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6278 in->dev->enable_voicerx = enable;
6279 struct audio_usecase *usecase;
6280 struct listnode *node;
6281 list_for_each(node, &in->dev->usecase_list) {
6282 usecase = node_to_item(node, struct audio_usecase, list);
6283 if (usecase->type == PCM_PLAYBACK)
6284 select_devices(in->dev, usecase->id);
6285 }
6286 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006287 if (!in->standby) {
6288 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6289 select_devices(in->dev, in->usecase);
6290 }
6291
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006292 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006293 if (in->enable_ns != enable &&
6294 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6295 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006296 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006297 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6298 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006299 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6300 select_devices(in->dev, in->usecase);
6301 } else
6302 select_devices(in->dev, in->usecase);
6303 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006304 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006305 pthread_mutex_unlock(&in->dev->lock);
6306 pthread_mutex_unlock(&in->lock);
6307
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006308 return 0;
6309}
6310
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006311static int in_add_audio_effect(const struct audio_stream *stream,
6312 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006313{
Eric Laurent994a6932013-07-17 11:51:42 -07006314 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006315 return add_remove_audio_effect(stream, effect, true);
6316}
6317
6318static int in_remove_audio_effect(const struct audio_stream *stream,
6319 effect_handle_t effect)
6320{
Eric Laurent994a6932013-07-17 11:51:42 -07006321 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006322 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006323}
6324
Derek Chenf939fb72018-11-13 13:34:41 -08006325streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6326 audio_io_handle_t input)
6327{
6328 struct listnode *node;
6329
6330 list_for_each(node, &dev->active_inputs_list) {
6331 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6332 streams_input_ctxt_t,
6333 list);
6334 if (in_ctxt->input->capture_handle == input) {
6335 return in_ctxt;
6336 }
6337 }
6338 return NULL;
6339}
6340
6341streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6342 audio_io_handle_t output)
6343{
6344 struct listnode *node;
6345
6346 list_for_each(node, &dev->active_outputs_list) {
6347 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6348 streams_output_ctxt_t,
6349 list);
6350 if (out_ctxt->output->handle == output) {
6351 return out_ctxt;
6352 }
6353 }
6354 return NULL;
6355}
6356
Haynes Mathew George16081042017-05-31 17:16:49 -07006357static int in_stop(const struct audio_stream_in* stream)
6358{
6359 struct stream_in *in = (struct stream_in *)stream;
6360 struct audio_device *adev = in->dev;
6361
6362 int ret = -ENOSYS;
6363 ALOGV("%s", __func__);
6364 pthread_mutex_lock(&adev->lock);
6365 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6366 in->capture_started && in->pcm != NULL) {
6367 pcm_stop(in->pcm);
6368 ret = stop_input_stream(in);
6369 in->capture_started = false;
6370 }
6371 pthread_mutex_unlock(&adev->lock);
6372 return ret;
6373}
6374
6375static int in_start(const struct audio_stream_in* stream)
6376{
6377 struct stream_in *in = (struct stream_in *)stream;
6378 struct audio_device *adev = in->dev;
6379 int ret = -ENOSYS;
6380
6381 ALOGV("%s in %p", __func__, in);
6382 pthread_mutex_lock(&adev->lock);
6383 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6384 !in->capture_started && in->pcm != NULL) {
6385 if (!in->capture_started) {
6386 ret = start_input_stream(in);
6387 if (ret == 0) {
6388 in->capture_started = true;
6389 }
6390 }
6391 }
6392 pthread_mutex_unlock(&adev->lock);
6393 return ret;
6394}
6395
6396static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6397 int32_t min_size_frames,
6398 struct audio_mmap_buffer_info *info)
6399{
6400 struct stream_in *in = (struct stream_in *)stream;
6401 struct audio_device *adev = in->dev;
6402 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006403 unsigned int offset1 = 0;
6404 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006405 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006406 uint32_t mmap_size = 0;
6407 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006408
6409 pthread_mutex_lock(&adev->lock);
6410 ALOGV("%s in %p", __func__, in);
6411
Sharad Sanglec6f32552018-05-04 16:15:38 +05306412 if (CARD_STATUS_OFFLINE == in->card_status||
6413 CARD_STATUS_OFFLINE == adev->card_status) {
6414 ALOGW("in->card_status or adev->card_status offline, try again");
6415 ret = -EIO;
6416 goto exit;
6417 }
6418
Haynes Mathew George16081042017-05-31 17:16:49 -07006419 if (info == NULL || min_size_frames == 0) {
6420 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6421 ret = -EINVAL;
6422 goto exit;
6423 }
6424 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6425 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6426 ALOGV("%s in %p", __func__, in);
6427 ret = -ENOSYS;
6428 goto exit;
6429 }
6430 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6431 if (in->pcm_device_id < 0) {
6432 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6433 __func__, in->pcm_device_id, in->usecase);
6434 ret = -EINVAL;
6435 goto exit;
6436 }
6437
6438 adjust_mmap_period_count(&in->config, min_size_frames);
6439
6440 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6441 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6442 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6443 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306444 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306445 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6446 in->card_status = CARD_STATUS_OFFLINE;
6447 adev->card_status = CARD_STATUS_OFFLINE;
6448 ret = -EIO;
6449 goto exit;
6450 }
6451
Haynes Mathew George16081042017-05-31 17:16:49 -07006452 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6453 step = "open";
6454 ret = -ENODEV;
6455 goto exit;
6456 }
6457
6458 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6459 if (ret < 0) {
6460 step = "begin";
6461 goto exit;
6462 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006463
Arun Mirpuri5d170872019-03-26 13:21:31 -07006464 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6465 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6466 info->burst_size_frames = in->config.period_size;
6467 ret = platform_get_mmap_data_fd(adev->platform,
6468 in->pcm_device_id, 1 /*capture*/,
6469 &info->shared_memory_fd,
6470 &mmap_size);
6471 if (ret < 0) {
6472 // Fall back to non exclusive mode
6473 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6474 } else {
6475 if (mmap_size < buffer_size) {
6476 step = "mmap";
6477 goto exit;
6478 }
6479 // FIXME: indicate exclusive mode support by returning a negative buffer size
6480 info->buffer_size_frames *= -1;
6481 }
6482
6483 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006484
6485 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6486 if (ret < 0) {
6487 step = "commit";
6488 goto exit;
6489 }
6490
6491 in->standby = false;
6492 ret = 0;
6493
6494 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6495 __func__, info->shared_memory_address, info->buffer_size_frames);
6496
6497exit:
6498 if (ret != 0) {
6499 if (in->pcm == NULL) {
6500 ALOGE("%s: %s - %d", __func__, step, ret);
6501 } else {
6502 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6503 pcm_close(in->pcm);
6504 in->pcm = NULL;
6505 }
6506 }
6507 pthread_mutex_unlock(&adev->lock);
6508 return ret;
6509}
6510
6511static int in_get_mmap_position(const struct audio_stream_in *stream,
6512 struct audio_mmap_position *position)
6513{
6514 struct stream_in *in = (struct stream_in *)stream;
6515 ALOGVV("%s", __func__);
6516 if (position == NULL) {
6517 return -EINVAL;
6518 }
6519 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6520 return -ENOSYS;
6521 }
6522 if (in->pcm == NULL) {
6523 return -ENOSYS;
6524 }
6525 struct timespec ts = { 0, 0 };
6526 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6527 if (ret < 0) {
6528 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6529 return ret;
6530 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306531 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006532 return 0;
6533}
6534
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306535static int in_get_active_microphones(const struct audio_stream_in *stream,
6536 struct audio_microphone_characteristic_t *mic_array,
6537 size_t *mic_count) {
6538 struct stream_in *in = (struct stream_in *)stream;
6539 struct audio_device *adev = in->dev;
6540 ALOGVV("%s", __func__);
6541
6542 lock_input_stream(in);
6543 pthread_mutex_lock(&adev->lock);
6544 int ret = platform_get_active_microphones(adev->platform,
6545 audio_channel_count_from_in_mask(in->channel_mask),
6546 in->usecase, mic_array, mic_count);
6547 pthread_mutex_unlock(&adev->lock);
6548 pthread_mutex_unlock(&in->lock);
6549
6550 return ret;
6551}
6552
6553static int adev_get_microphones(const struct audio_hw_device *dev,
6554 struct audio_microphone_characteristic_t *mic_array,
6555 size_t *mic_count) {
6556 struct audio_device *adev = (struct audio_device *)dev;
6557 ALOGVV("%s", __func__);
6558
6559 pthread_mutex_lock(&adev->lock);
6560 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6561 pthread_mutex_unlock(&adev->lock);
6562
6563 return ret;
6564}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306565int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006566 audio_io_handle_t handle,
6567 audio_devices_t devices,
6568 audio_output_flags_t flags,
6569 struct audio_config *config,
6570 struct audio_stream_out **stream_out,
6571 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006572{
6573 struct audio_device *adev = (struct audio_device *)dev;
6574 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306575 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006576 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006577 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306578 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006579 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6580 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6581 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6582 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006583 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006584 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006585 bool force_haptic_path =
6586 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006587
kunleizdff872d2018-08-20 14:40:33 +08006588 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006589 is_usb_dev = false;
6590 devices = AUDIO_DEVICE_OUT_SPEAKER;
6591 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6592 __func__, devices);
6593 }
6594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006595 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006597 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6598
Mingming Yin3a941d42016-02-17 18:08:05 -08006599 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6600 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306601 devices, flags, &out->stream);
6602
6603
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006604 if (!out) {
6605 return -ENOMEM;
6606 }
6607
Haynes Mathew George204045b2015-02-25 20:32:03 -08006608 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006609 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306610 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006611 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006612 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006614 if (devices == AUDIO_DEVICE_NONE)
6615 devices = AUDIO_DEVICE_OUT_SPEAKER;
6616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006617 out->flags = flags;
6618 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006619 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006620 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006621 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306622 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306623 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6624 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6625 else
6626 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006627 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006628 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006629 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306630 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306631 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306632 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006633 out->hal_output_suspend_supported = 0;
6634 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306635 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306636 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306637 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006638
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306639 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306640 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006641 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6642
Aalique Grahame22e49102018-12-18 14:23:57 -08006643 if (direct_dev &&
6644 (audio_is_linear_pcm(out->format) ||
6645 config->format == AUDIO_FORMAT_DEFAULT) &&
6646 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6647 audio_format_t req_format = config->format;
6648 audio_channel_mask_t req_channel_mask = config->channel_mask;
6649 uint32_t req_sample_rate = config->sample_rate;
6650
6651 pthread_mutex_lock(&adev->lock);
6652 if (is_hdmi) {
6653 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6654 ret = read_hdmi_sink_caps(out);
6655 if (config->sample_rate == 0)
6656 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6657 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6658 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6659 if (config->format == AUDIO_FORMAT_DEFAULT)
6660 config->format = AUDIO_FORMAT_PCM_16_BIT;
6661 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006662 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6663 &config->format,
6664 &out->supported_formats[0],
6665 MAX_SUPPORTED_FORMATS,
6666 &config->channel_mask,
6667 &out->supported_channel_masks[0],
6668 MAX_SUPPORTED_CHANNEL_MASKS,
6669 &config->sample_rate,
6670 &out->supported_sample_rates[0],
6671 MAX_SUPPORTED_SAMPLE_RATES);
6672 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006673 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006674
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006675 pthread_mutex_unlock(&adev->lock);
6676 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006677 if (ret == -ENOSYS) {
6678 /* ignore and go with default */
6679 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006680 }
6681 // For MMAP NO IRQ, allow conversions in ADSP
6682 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6683 goto error_open;
6684 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006685 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006686 goto error_open;
6687 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006688
6689 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6690 config->sample_rate = req_sample_rate;
6691 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6692 config->channel_mask = req_channel_mask;
6693 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6694 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006695 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006696
6697 out->sample_rate = config->sample_rate;
6698 out->channel_mask = config->channel_mask;
6699 out->format = config->format;
6700 if (is_hdmi) {
6701 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6702 out->config = pcm_config_hdmi_multi;
6703 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6704 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6705 out->config = pcm_config_mmap_playback;
6706 out->stream.start = out_start;
6707 out->stream.stop = out_stop;
6708 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6709 out->stream.get_mmap_position = out_get_mmap_position;
6710 } else {
6711 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6712 out->config = pcm_config_hifi;
6713 }
6714
6715 out->config.rate = out->sample_rate;
6716 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6717 if (is_hdmi) {
6718 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6719 audio_bytes_per_sample(out->format));
6720 }
6721 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006722 }
6723
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006724 /* Check for VOIP usecase */
6725 if(out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) {
6726 if (!voice_extn_is_compress_voip_supported()) {
6727 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6728 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006729 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006730 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6731 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006732
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006733 out->config = default_pcm_config_voip_copp;
6734 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6735 out->config.rate = out->sample_rate;
6736 }
6737 } else {
6738 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6739 voice_extn_compress_voip_is_active(out->dev)) &&
6740 (voice_extn_compress_voip_is_config_supported(config))) {
6741 ret = voice_extn_compress_voip_open_output_stream(out);
6742 if (ret != 0) {
6743 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6744 __func__, ret);
6745 goto error_open;
6746 }
6747 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006748 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006749 } else if (audio_is_linear_pcm(out->format) &&
6750 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6751 out->channel_mask = config->channel_mask;
6752 out->sample_rate = config->sample_rate;
6753 out->format = config->format;
6754 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6755 // does this change?
6756 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6757 out->config.rate = config->sample_rate;
6758 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6759 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6760 audio_bytes_per_sample(config->format));
6761 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006762 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306763 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306764 pthread_mutex_lock(&adev->lock);
6765 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6766 pthread_mutex_unlock(&adev->lock);
6767
6768 // reject offload during card offline to allow
6769 // fallback to s/w paths
6770 if (offline) {
6771 ret = -ENODEV;
6772 goto error_open;
6773 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006774
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006775 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6776 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6777 ALOGE("%s: Unsupported Offload information", __func__);
6778 ret = -EINVAL;
6779 goto error_open;
6780 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006781
Atul Khare3fa6e542017-08-09 00:56:17 +05306782 if (config->offload_info.format == 0)
6783 config->offload_info.format = config->format;
6784 if (config->offload_info.sample_rate == 0)
6785 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006786
Mingming Yin90310102013-11-13 16:57:00 -08006787 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306788 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006789 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006790 ret = -EINVAL;
6791 goto error_open;
6792 }
6793
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006794 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6795 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6796 (audio_extn_passthru_is_passthrough_stream(out)) &&
6797 !((config->sample_rate == 48000) ||
6798 (config->sample_rate == 96000) ||
6799 (config->sample_rate == 192000))) {
6800 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6801 __func__, config->sample_rate, config->offload_info.format);
6802 ret = -EINVAL;
6803 goto error_open;
6804 }
6805
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006806 out->compr_config.codec = (struct snd_codec *)
6807 calloc(1, sizeof(struct snd_codec));
6808
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006809 if (!out->compr_config.codec) {
6810 ret = -ENOMEM;
6811 goto error_open;
6812 }
6813
Dhananjay Kumarac341582017-02-23 23:42:25 +05306814 out->stream.pause = out_pause;
6815 out->stream.resume = out_resume;
6816 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306817 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306818 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006819 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306820 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006821 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306822 } else {
6823 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6824 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006825 }
vivek mehta446c3962015-09-14 10:57:35 -07006826
6827 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006828 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6829 config->format == 0 && config->sample_rate == 0 &&
6830 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006831 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006832 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6833 } else {
6834 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6835 ret = -EEXIST;
6836 goto error_open;
6837 }
vivek mehta446c3962015-09-14 10:57:35 -07006838 }
6839
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006840 if (config->offload_info.channel_mask)
6841 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006842 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006843 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006844 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006845 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306846 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006847 ret = -EINVAL;
6848 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006849 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006850
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006851 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006852 out->sample_rate = config->offload_info.sample_rate;
6853
Mingming Yin3ee55c62014-08-04 14:23:35 -07006854 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006855
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306856 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306857 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306858 audio_extn_dolby_send_ddp_endp_params(adev);
6859 audio_extn_dolby_set_dmid(adev);
6860 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006861
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006862 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006863 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006864 out->compr_config.codec->bit_rate =
6865 config->offload_info.bit_rate;
6866 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306867 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006868 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306869 /* Update bit width only for non passthrough usecases.
6870 * For passthrough usecases, the output will always be opened @16 bit
6871 */
6872 if (!audio_extn_passthru_is_passthrough_stream(out))
6873 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306874
6875 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6876 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6877 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6878
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006879 /*TODO: Do we need to change it for passthrough */
6880 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006881
Manish Dewangana6fc5442015-08-24 20:30:31 +05306882 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6883 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306884 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306885 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306886 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6887 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306888
6889 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6890 AUDIO_FORMAT_PCM) {
6891
6892 /*Based on platform support, configure appropriate alsa format for corresponding
6893 *hal input format.
6894 */
6895 out->compr_config.codec->format = hal_format_to_alsa(
6896 config->offload_info.format);
6897
Ashish Jain83a6cc22016-06-28 14:34:17 +05306898 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306899 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306900 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306901
Dhananjay Kumarac341582017-02-23 23:42:25 +05306902 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306903 *hal input format and alsa format might differ based on platform support.
6904 */
6905 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306906 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306907
6908 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6909
6910 /* Check if alsa session is configured with the same format as HAL input format,
6911 * if not then derive correct fragment size needed to accomodate the
6912 * conversion of HAL input format to alsa format.
6913 */
6914 audio_extn_utils_update_direct_pcm_fragment_size(out);
6915
6916 /*if hal input and output fragment size is different this indicates HAL input format is
6917 *not same as the alsa format
6918 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306919 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306920 /*Allocate a buffer to convert input data to the alsa configured format.
6921 *size of convert buffer is equal to the size required to hold one fragment size
6922 *worth of pcm data, this is because flinger does not write more than fragment_size
6923 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306924 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6925 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306926 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6927 ret = -ENOMEM;
6928 goto error_open;
6929 }
6930 }
6931 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6932 out->compr_config.fragment_size =
6933 audio_extn_passthru_get_buffer_size(&config->offload_info);
6934 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6935 } else {
6936 out->compr_config.fragment_size =
6937 platform_get_compress_offload_buffer_size(&config->offload_info);
6938 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6939 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006940
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306941 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6942 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6943 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006944 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306945 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006946
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306947 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6948 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6949 }
6950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006951 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6952 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006953
Manish Dewangan69426c82017-01-30 17:35:36 +05306954 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6955 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6956 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6957 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6958 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6959 } else {
6960 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6961 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006962
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306963 memset(&out->channel_map_param, 0,
6964 sizeof(struct audio_out_channel_map_param));
6965
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006966 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306967 out->send_next_track_params = false;
6968 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006969 out->offload_state = OFFLOAD_STATE_IDLE;
6970 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006971 out->writeAt.tv_sec = 0;
6972 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006973
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006974 audio_extn_dts_create_state_notifier_node(out->usecase);
6975
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006976 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6977 __func__, config->offload_info.version,
6978 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306979
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306980 /* Check if DSD audio format is supported in codec
6981 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306982 */
6983
6984 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306985 (!platform_check_codec_dsd_support(adev->platform) ||
6986 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306987 ret = -EINVAL;
6988 goto error_open;
6989 }
6990
Ashish Jain5106d362016-05-11 19:23:33 +05306991 /* Disable gapless if any of the following is true
6992 * passthrough playback
6993 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306994 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306995 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306996 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306997 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006998 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306999 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307000 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307001 check_and_set_gapless_mode(adev, false);
7002 } else
7003 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007004
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307005 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007006 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7007 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307008 if (config->format == AUDIO_FORMAT_DSD) {
7009 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7010 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7011 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007012
7013 create_offload_callback_thread(out);
7014
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007015 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007016 switch (config->sample_rate) {
7017 case 0:
7018 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7019 break;
7020 case 8000:
7021 case 16000:
7022 case 48000:
7023 out->sample_rate = config->sample_rate;
7024 break;
7025 default:
7026 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7027 config->sample_rate);
7028 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7029 ret = -EINVAL;
7030 goto error_open;
7031 }
7032 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7033 switch (config->channel_mask) {
7034 case AUDIO_CHANNEL_NONE:
7035 case AUDIO_CHANNEL_OUT_STEREO:
7036 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7037 break;
7038 default:
7039 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7040 config->channel_mask);
7041 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7042 ret = -EINVAL;
7043 goto error_open;
7044 }
7045 switch (config->format) {
7046 case AUDIO_FORMAT_DEFAULT:
7047 case AUDIO_FORMAT_PCM_16_BIT:
7048 out->format = AUDIO_FORMAT_PCM_16_BIT;
7049 break;
7050 default:
7051 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7052 config->format);
7053 config->format = AUDIO_FORMAT_PCM_16_BIT;
7054 ret = -EINVAL;
7055 goto error_open;
7056 }
7057
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307058 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007059 if (ret != 0) {
7060 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007061 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007062 goto error_open;
7063 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007064 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007065 switch (config->sample_rate) {
7066 case 0:
7067 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7068 break;
7069 case 8000:
7070 case 16000:
7071 case 48000:
7072 out->sample_rate = config->sample_rate;
7073 break;
7074 default:
7075 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7076 config->sample_rate);
7077 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7078 ret = -EINVAL;
7079 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007080 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007081 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7082 switch (config->channel_mask) {
7083 case AUDIO_CHANNEL_NONE:
7084 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7085 break;
7086 case AUDIO_CHANNEL_OUT_STEREO:
7087 out->channel_mask = config->channel_mask;
7088 break;
7089 default:
7090 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7091 config->channel_mask);
7092 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7093 ret = -EINVAL;
7094 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007095 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007096 switch (config->format) {
7097 case AUDIO_FORMAT_DEFAULT:
7098 out->format = AUDIO_FORMAT_PCM_16_BIT;
7099 break;
7100 case AUDIO_FORMAT_PCM_16_BIT:
7101 out->format = config->format;
7102 break;
7103 default:
7104 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7105 config->format);
7106 config->format = AUDIO_FORMAT_PCM_16_BIT;
7107 ret = -EINVAL;
7108 break;
7109 }
7110 if (ret != 0)
7111 goto error_open;
7112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007113 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7114 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007115 out->config.rate = out->sample_rate;
7116 out->config.channels =
7117 audio_channel_count_from_out_mask(out->channel_mask);
7118 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007119 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007120 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307121 unsigned int channels = 0;
7122 /*Update config params to default if not set by the caller*/
7123 if (config->sample_rate == 0)
7124 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7125 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7126 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7127 if (config->format == AUDIO_FORMAT_DEFAULT)
7128 config->format = AUDIO_FORMAT_PCM_16_BIT;
7129
7130 channels = audio_channel_count_from_out_mask(out->channel_mask);
7131
Varun Balaraje49253e2017-07-06 19:48:56 +05307132 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7133 out->usecase = get_interactive_usecase(adev);
7134 out->config = pcm_config_low_latency;
7135 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307136 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007137 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7138 out->flags);
7139 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007140 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7141 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7142 out->config = pcm_config_mmap_playback;
7143 out->stream.start = out_start;
7144 out->stream.stop = out_stop;
7145 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7146 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307147 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7148 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007149 out->hal_output_suspend_supported =
7150 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7151 out->dynamic_pm_qos_config_supported =
7152 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7153 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007154 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7155 } else {
7156 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7157 //the mixer path will be a string similar to "low-latency-playback resume"
7158 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7159 strlcat(out->pm_qos_mixer_path,
7160 " resume", MAX_MIXER_PATH_LEN);
7161 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7162 out->pm_qos_mixer_path);
7163 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307164 out->config = pcm_config_low_latency;
7165 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7166 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7167 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307168 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7169 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7170 if (out->config.period_size <= 0) {
7171 ALOGE("Invalid configuration period size is not valid");
7172 ret = -EINVAL;
7173 goto error_open;
7174 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007175 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7176 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7177 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007178 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7179 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7180 out->config = pcm_config_haptics_audio;
7181 if (force_haptic_path)
7182 adev->haptics_config = pcm_config_haptics_audio;
7183 else
7184 adev->haptics_config = pcm_config_haptics;
7185
7186 out->config.channels =
7187 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7188
7189 if (force_haptic_path) {
7190 out->config.channels = 1;
7191 adev->haptics_config.channels = 1;
7192 } else
7193 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307194 } else {
7195 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007196 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7197 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307198 }
7199 out->hal_ip_format = format = out->format;
7200 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7201 out->hal_op_format = pcm_format_to_hal(out->config.format);
7202 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7203 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007204 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307205 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307206 if (out->hal_ip_format != out->hal_op_format) {
7207 uint32_t buffer_size = out->config.period_size *
7208 format_to_bitwidth_table[out->hal_op_format] *
7209 out->config.channels;
7210 out->convert_buffer = calloc(1, buffer_size);
7211 if (out->convert_buffer == NULL){
7212 ALOGE("Allocation failed for convert buffer for size %d",
7213 out->compr_config.fragment_size);
7214 ret = -ENOMEM;
7215 goto error_open;
7216 }
7217 ALOGD("Convert buffer allocated of size %d", buffer_size);
7218 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007219 }
7220
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007221 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7222 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307223
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007224 /* TODO remove this hardcoding and check why width is zero*/
7225 if (out->bit_width == 0)
7226 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307227 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007228 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007229 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307230 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307231 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007232 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007233 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7234 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007235 if(adev->primary_output == NULL)
7236 adev->primary_output = out;
7237 else {
7238 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007239 ret = -EEXIST;
7240 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007241 }
7242 }
7243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 /* Check if this usecase is already existing */
7245 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007246 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7247 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007248 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007250 ret = -EEXIST;
7251 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007252 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007254 pthread_mutex_unlock(&adev->lock);
7255
7256 out->stream.common.get_sample_rate = out_get_sample_rate;
7257 out->stream.common.set_sample_rate = out_set_sample_rate;
7258 out->stream.common.get_buffer_size = out_get_buffer_size;
7259 out->stream.common.get_channels = out_get_channels;
7260 out->stream.common.get_format = out_get_format;
7261 out->stream.common.set_format = out_set_format;
7262 out->stream.common.standby = out_standby;
7263 out->stream.common.dump = out_dump;
7264 out->stream.common.set_parameters = out_set_parameters;
7265 out->stream.common.get_parameters = out_get_parameters;
7266 out->stream.common.add_audio_effect = out_add_audio_effect;
7267 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7268 out->stream.get_latency = out_get_latency;
7269 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007270#ifdef NO_AUDIO_OUT
7271 out->stream.write = out_write_for_no_output;
7272#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007273 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007274#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007275 out->stream.get_render_position = out_get_render_position;
7276 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007277 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007278
Haynes Mathew George16081042017-05-31 17:16:49 -07007279 if (out->realtime)
7280 out->af_period_multiplier = af_period_multiplier;
7281 else
7282 out->af_period_multiplier = 1;
7283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007284 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007285 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007286 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007287
7288 config->format = out->stream.common.get_format(&out->stream.common);
7289 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7290 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307291 register_format(out->format, out->supported_formats);
7292 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7293 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007294
Aalique Grahame22e49102018-12-18 14:23:57 -08007295 out->error_log = error_log_create(
7296 ERROR_LOG_ENTRIES,
7297 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7298
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307299 /*
7300 By locking output stream before registering, we allow the callback
7301 to update stream's state only after stream's initial state is set to
7302 adev state.
7303 */
7304 lock_output_stream(out);
7305 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7306 pthread_mutex_lock(&adev->lock);
7307 out->card_status = adev->card_status;
7308 pthread_mutex_unlock(&adev->lock);
7309 pthread_mutex_unlock(&out->lock);
7310
Aalique Grahame22e49102018-12-18 14:23:57 -08007311 stream_app_type_cfg_init(&out->app_type_cfg);
7312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007313 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307314 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007315 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007316
7317 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7318 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7319 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007320 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307321 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007322 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007323 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307324 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007325 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7326 out->usecase, PCM_PLAYBACK);
7327 hdlr_stream_cfg.flags = out->flags;
7328 hdlr_stream_cfg.type = PCM_PLAYBACK;
7329 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7330 &hdlr_stream_cfg);
7331 if (ret) {
7332 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7333 out->adsp_hdlr_stream_handle = NULL;
7334 }
7335 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307336 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007337 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007338 if (ret < 0) {
7339 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7340 out->ip_hdlr_handle = NULL;
7341 }
7342 }
Derek Chenf939fb72018-11-13 13:34:41 -08007343
7344 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7345 calloc(1, sizeof(streams_output_ctxt_t));
7346 if (out_ctxt == NULL) {
7347 ALOGE("%s fail to allocate output ctxt", __func__);
7348 ret = -ENOMEM;
7349 goto error_open;
7350 }
7351 out_ctxt->output = out;
7352
7353 pthread_mutex_lock(&adev->lock);
7354 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7355 pthread_mutex_unlock(&adev->lock);
7356
Eric Laurent994a6932013-07-17 11:51:42 -07007357 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007358 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007359
7360error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307361 if (out->convert_buffer)
7362 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007363 free(out);
7364 *stream_out = NULL;
7365 ALOGD("%s: exit: ret %d", __func__, ret);
7366 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367}
7368
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307369void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007370 struct audio_stream_out *stream)
7371{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007372 struct stream_out *out = (struct stream_out *)stream;
7373 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007374 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007375
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007376 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307377
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307378 // must deregister from sndmonitor first to prevent races
7379 // between the callback and close_stream
7380 audio_extn_snd_mon_unregister_listener(out);
7381
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007382 /* close adsp hdrl session before standby */
7383 if (out->adsp_hdlr_stream_handle) {
7384 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7385 if (ret)
7386 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7387 out->adsp_hdlr_stream_handle = NULL;
7388 }
7389
Manish Dewangan21a850a2017-08-14 12:03:55 +05307390 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007391 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7392 out->ip_hdlr_handle = NULL;
7393 }
7394
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007395 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307396 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007397 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307398 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307399 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007400 if(ret != 0)
7401 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7402 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007403 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007404 out_standby(&stream->common);
7405
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007406 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007407 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007408 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007409 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007410 if (out->compr_config.codec != NULL)
7411 free(out->compr_config.codec);
7412 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007413
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307414 out->a2dp_compress_mute = false;
7415
Varun Balaraje49253e2017-07-06 19:48:56 +05307416 if (is_interactive_usecase(out->usecase))
7417 free_interactive_usecase(adev, out->usecase);
7418
Ashish Jain83a6cc22016-06-28 14:34:17 +05307419 if (out->convert_buffer != NULL) {
7420 free(out->convert_buffer);
7421 out->convert_buffer = NULL;
7422 }
7423
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007424 if (adev->voice_tx_output == out)
7425 adev->voice_tx_output = NULL;
7426
Aalique Grahame22e49102018-12-18 14:23:57 -08007427 error_log_destroy(out->error_log);
7428 out->error_log = NULL;
7429
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307430 if (adev->primary_output == out)
7431 adev->primary_output = NULL;
7432
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007433 pthread_cond_destroy(&out->cond);
7434 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007435
7436 pthread_mutex_lock(&adev->lock);
7437 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7438 if (out_ctxt != NULL) {
7439 list_remove(&out_ctxt->list);
7440 free(out_ctxt);
7441 } else {
7442 ALOGW("%s, output stream already closed", __func__);
7443 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007444 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007445 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007446 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007447}
7448
7449static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7450{
7451 struct audio_device *adev = (struct audio_device *)dev;
7452 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007453 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007454 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007455 int ret;
7456 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007457 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007458
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007459 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007460 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007461
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307462 if (!parms)
7463 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307464
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307465 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7466 if (ret >= 0) {
7467 /* When set to false, HAL should disable EC and NS */
7468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7469 adev->bt_sco_on = true;
7470 else
7471 adev->bt_sco_on = false;
7472 }
7473
Naresh Tanniru4c630392014-05-12 01:05:52 +05307474 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007475 status = voice_set_parameters(adev, parms);
7476 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007477 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007478
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007479 status = platform_set_parameters(adev->platform, parms);
7480 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007481 goto done;
7482
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007483 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7484 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007485 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007486 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7487 adev->bluetooth_nrec = true;
7488 else
7489 adev->bluetooth_nrec = false;
7490 }
7491
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007492 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7493 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7495 adev->screen_off = false;
7496 else
7497 adev->screen_off = true;
7498 }
7499
Aalique Grahame22e49102018-12-18 14:23:57 -08007500#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007501 ret = str_parms_get_int(parms, "rotation", &val);
7502 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007503 bool reverse_speakers = false;
7504 switch(val) {
7505 // FIXME: note that the code below assumes that the speakers are in the correct placement
7506 // relative to the user when the device is rotated 90deg from its default rotation. This
7507 // assumption is device-specific, not platform-specific like this code.
7508 case 270:
7509 reverse_speakers = true;
7510 break;
7511 case 0:
7512 case 90:
7513 case 180:
7514 break;
7515 default:
7516 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007517 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007518 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007519 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007520 // check and set swap
7521 // - check if orientation changed and speaker active
7522 // - set rotation and cache the rotation value
7523 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007524 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007525 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007526#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007527
Mingming Yin514a8bc2014-07-29 15:22:21 -07007528 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7529 if (ret >= 0) {
7530 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7531 adev->bt_wb_speech_enabled = true;
7532 else
7533 adev->bt_wb_speech_enabled = false;
7534 }
7535
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007536 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7537 if (ret >= 0) {
7538 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307539 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007540 if (audio_is_output_device(val) &&
7541 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007542 ALOGV("cache new ext disp type and edid");
7543 ret = platform_get_ext_disp_type(adev->platform);
7544 if (ret < 0) {
7545 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307546 } else {
7547 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007548 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307549 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007550 /*
7551 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7552 * Per AudioPolicyManager, USB device is higher priority than WFD.
7553 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7554 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7555 * starting voice call on USB
7556 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007557 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307558 if (ret >= 0)
7559 audio_extn_usb_add_device(device, atoi(value));
7560
Zhou Song6f862822017-11-06 17:27:57 +08007561 if (!audio_extn_usb_is_tunnel_supported()) {
7562 ALOGV("detected USB connect .. disable proxy");
7563 adev->allow_afe_proxy_usage = false;
7564 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007565 }
7566 }
7567
7568 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7569 if (ret >= 0) {
7570 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307571 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007572 /*
7573 * The HDMI / Displayport disconnect handling has been moved to
7574 * audio extension to ensure that its parameters are not
7575 * invalidated prior to updating sysfs of the disconnect event
7576 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7577 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307578 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007579 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307580 if (ret >= 0)
7581 audio_extn_usb_remove_device(device, atoi(value));
7582
Zhou Song6f862822017-11-06 17:27:57 +08007583 if (!audio_extn_usb_is_tunnel_supported()) {
7584 ALOGV("detected USB disconnect .. enable proxy");
7585 adev->allow_afe_proxy_usage = true;
7586 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007587 }
7588 }
7589
Aalique Grahame22e49102018-12-18 14:23:57 -08007590 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007591 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007592
7593 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007594 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307595 struct audio_usecase *usecase;
7596 struct listnode *node;
7597 list_for_each(node, &adev->usecase_list) {
7598 usecase = node_to_item(node, struct audio_usecase, list);
7599 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007600 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307601 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007602
7603 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307604 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007605 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307606 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307607 //force device switch to re configure encoder
7608 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307609 audio_extn_a2dp_set_handoff_mode(false);
7610 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307611 break;
7612 }
7613 }
7614 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007615
7616 //handle vr audio setparam
7617 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7618 value, sizeof(value));
7619 if (ret >= 0) {
7620 ALOGI("Setting vr mode to be %s", value);
7621 if (!strncmp(value, "true", 4)) {
7622 adev->vr_audio_mode_enabled = true;
7623 ALOGI("Setting vr mode to true");
7624 } else if (!strncmp(value, "false", 5)) {
7625 adev->vr_audio_mode_enabled = false;
7626 ALOGI("Setting vr mode to false");
7627 } else {
7628 ALOGI("wrong vr mode set");
7629 }
7630 }
7631
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307632 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007633done:
7634 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007635 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307636error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007637 ALOGV("%s: exit with code(%d)", __func__, status);
7638 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007639}
7640
7641static char* adev_get_parameters(const struct audio_hw_device *dev,
7642 const char *keys)
7643{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307644 ALOGD("%s:%s", __func__, keys);
7645
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007646 struct audio_device *adev = (struct audio_device *)dev;
7647 struct str_parms *reply = str_parms_create();
7648 struct str_parms *query = str_parms_create_str(keys);
7649 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307650 char value[256] = {0};
7651 int ret = 0;
7652
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007653 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007654 if (reply) {
7655 str_parms_destroy(reply);
7656 }
7657 if (query) {
7658 str_parms_destroy(query);
7659 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007660 ALOGE("adev_get_parameters: failed to create query or reply");
7661 return NULL;
7662 }
7663
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007664 //handle vr audio getparam
7665
7666 ret = str_parms_get_str(query,
7667 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7668 value, sizeof(value));
7669
7670 if (ret >= 0) {
7671 bool vr_audio_enabled = false;
7672 pthread_mutex_lock(&adev->lock);
7673 vr_audio_enabled = adev->vr_audio_mode_enabled;
7674 pthread_mutex_unlock(&adev->lock);
7675
7676 ALOGI("getting vr mode to %d", vr_audio_enabled);
7677
7678 if (vr_audio_enabled) {
7679 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7680 "true");
7681 goto exit;
7682 } else {
7683 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7684 "false");
7685 goto exit;
7686 }
7687 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007688
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007689 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007690 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007691 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007692 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007693 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307694 pthread_mutex_unlock(&adev->lock);
7695
Naresh Tannirud7205b62014-06-20 02:54:48 +05307696exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007697 str = str_parms_to_str(reply);
7698 str_parms_destroy(query);
7699 str_parms_destroy(reply);
7700
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307701 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007702 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007703}
7704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007705static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007706{
7707 return 0;
7708}
7709
7710static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7711{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007712 int ret;
7713 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007714
7715 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7716
Haynes Mathew George5191a852013-09-11 14:19:36 -07007717 pthread_mutex_lock(&adev->lock);
7718 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007719 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007720 pthread_mutex_unlock(&adev->lock);
7721 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007722}
7723
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007724static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7725 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007726{
7727 return -ENOSYS;
7728}
7729
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007730static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7731 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007732{
7733 return -ENOSYS;
7734}
7735
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007736static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7737 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007738{
7739 return -ENOSYS;
7740}
7741
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007742static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7743 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007744{
7745 return -ENOSYS;
7746}
7747
7748static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7749{
7750 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007751 struct listnode *node;
7752 struct audio_usecase *usecase = NULL;
7753 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007754 pthread_mutex_lock(&adev->lock);
7755 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007756 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007757 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007758 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007759 list_for_each(node, &adev->usecase_list) {
7760 usecase = node_to_item(node, struct audio_usecase, list);
7761 if (usecase->type == VOICE_CALL)
7762 break;
7763 }
7764 if (usecase &&
7765 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7766 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7767 true);
7768 if (ret != 0) {
7769 /* default service interval was successfully updated,
7770 reopen USB backend with new service interval */
7771 check_usecases_codec_backend(adev,
7772 usecase,
7773 usecase->out_snd_device);
7774 }
7775 }
7776
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007777 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007778 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007779 adev->current_call_output = NULL;
7780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007781 }
7782 pthread_mutex_unlock(&adev->lock);
7783 return 0;
7784}
7785
7786static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7787{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007788 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007789 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007790
7791 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007792 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007793 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007794
Derek Chend2530072014-11-24 12:39:14 -08007795 if (adev->ext_hw_plugin)
7796 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007797
7798 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007799 pthread_mutex_unlock(&adev->lock);
7800
7801 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007802}
7803
7804static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7805{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007806 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007807 return 0;
7808}
7809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007810static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007811 const struct audio_config *config)
7812{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007813 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007814
Aalique Grahame22e49102018-12-18 14:23:57 -08007815 /* Don't know if USB HIFI in this context so use true to be conservative */
7816 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7817 true /*is_usb_hifi */) != 0)
7818 return 0;
7819
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007820 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7821 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007822}
7823
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007824static bool adev_input_allow_hifi_record(struct audio_device *adev,
7825 audio_devices_t devices,
7826 audio_input_flags_t flags,
7827 audio_source_t source) {
7828 const bool allowed = true;
7829
7830 if (!audio_is_usb_in_device(devices))
7831 return !allowed;
7832
7833 switch (flags) {
7834 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007835 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007836 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7837 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007838 default:
7839 return !allowed;
7840 }
7841
7842 switch (source) {
7843 case AUDIO_SOURCE_DEFAULT:
7844 case AUDIO_SOURCE_MIC:
7845 case AUDIO_SOURCE_UNPROCESSED:
7846 break;
7847 default:
7848 return !allowed;
7849 }
7850
7851 switch (adev->mode) {
7852 case 0:
7853 break;
7854 default:
7855 return !allowed;
7856 }
7857
7858 return allowed;
7859}
7860
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007861static int adev_update_voice_comm_input_stream(struct stream_in *in,
7862 struct audio_config *config)
7863{
7864 bool valid_rate = (config->sample_rate == 8000 ||
7865 config->sample_rate == 16000 ||
7866 config->sample_rate == 32000 ||
7867 config->sample_rate == 48000);
7868 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7869
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007870 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08007871 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007872 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7873 in->config = default_pcm_config_voip_copp;
7874 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7875 DEFAULT_VOIP_BUF_DURATION_MS,
7876 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007877 } else {
7878 ALOGW("%s No valid input in voip, use defaults"
7879 "sample rate %u, channel mask 0x%X",
7880 __func__, config->sample_rate, in->channel_mask);
7881 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007882 in->config.rate = config->sample_rate;
7883 in->sample_rate = config->sample_rate;
7884 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007885 //XXX needed for voice_extn_compress_voip_open_input_stream
7886 in->config.rate = config->sample_rate;
7887 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7888 voice_extn_compress_voip_is_active(in->dev)) &&
7889 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7890 valid_rate && valid_ch) {
7891 voice_extn_compress_voip_open_input_stream(in);
7892 // update rate entries to match config from AF
7893 in->config.rate = config->sample_rate;
7894 in->sample_rate = config->sample_rate;
7895 } else {
7896 ALOGW("%s compress voip not active, use defaults", __func__);
7897 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007898 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007899 return 0;
7900}
7901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007902static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007903 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007904 audio_devices_t devices,
7905 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007906 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307907 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007908 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007909 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007910{
7911 struct audio_device *adev = (struct audio_device *)dev;
7912 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007913 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007914 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007915 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307916 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007917 bool is_usb_dev = audio_is_usb_in_device(devices);
7918 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7919 devices,
7920 flags,
7921 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307922
kunleizdff872d2018-08-20 14:40:33 +08007923 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007924 is_usb_dev = false;
7925 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7926 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7927 __func__, devices);
7928 }
7929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007930 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007931
7932 if (!(is_usb_dev && may_use_hifi_record)) {
7933 if (config->sample_rate == 0)
7934 config->sample_rate = 48000;
7935 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7936 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7937 if (config->format == AUDIO_FORMAT_DEFAULT)
7938 config->format = AUDIO_FORMAT_PCM_16_BIT;
7939
7940 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7941
Aalique Grahame22e49102018-12-18 14:23:57 -08007942 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7943 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007944 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307945 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007946
7947 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007948
7949 if (!in) {
7950 ALOGE("failed to allocate input stream");
7951 return -ENOMEM;
7952 }
7953
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307954 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307955 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7956 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007957 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007958 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007960 in->stream.common.get_sample_rate = in_get_sample_rate;
7961 in->stream.common.set_sample_rate = in_set_sample_rate;
7962 in->stream.common.get_buffer_size = in_get_buffer_size;
7963 in->stream.common.get_channels = in_get_channels;
7964 in->stream.common.get_format = in_get_format;
7965 in->stream.common.set_format = in_set_format;
7966 in->stream.common.standby = in_standby;
7967 in->stream.common.dump = in_dump;
7968 in->stream.common.set_parameters = in_set_parameters;
7969 in->stream.common.get_parameters = in_get_parameters;
7970 in->stream.common.add_audio_effect = in_add_audio_effect;
7971 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7972 in->stream.set_gain = in_set_gain;
7973 in->stream.read = in_read;
7974 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08007975 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307976 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007977
7978 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007979 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007980 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007981 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007982 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007983 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007984 in->bit_width = 16;
7985 in->af_period_multiplier = 1;
7986
Aalique Grahame22e49102018-12-18 14:23:57 -08007987 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
7988 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
7989 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
7990 /* Force channel config requested to mono if incall
7991 record is being requested for only uplink/downlink */
7992 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
7993 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7994 ret = -EINVAL;
7995 goto err_open;
7996 }
7997 }
7998
Haynes Mathew George46740472017-10-27 18:40:12 -07007999 /* Update config params with the requested sample rate and channels */
8000 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
8001 (adev->mode != AUDIO_MODE_IN_CALL)) {
8002 ret = -EINVAL;
8003 goto err_open;
8004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008005
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008006 if (is_usb_dev && may_use_hifi_record) {
8007 /* HiFi record selects an appropriate format, channel, rate combo
8008 depending on sink capabilities*/
8009 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8010 &config->format,
8011 &in->supported_formats[0],
8012 MAX_SUPPORTED_FORMATS,
8013 &config->channel_mask,
8014 &in->supported_channel_masks[0],
8015 MAX_SUPPORTED_CHANNEL_MASKS,
8016 &config->sample_rate,
8017 &in->supported_sample_rates[0],
8018 MAX_SUPPORTED_SAMPLE_RATES);
8019 if (ret != 0) {
8020 ret = -EINVAL;
8021 goto err_open;
8022 }
8023 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008024 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308025 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308026 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8027 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8028 in->config.format = PCM_FORMAT_S32_LE;
8029 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308030 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8031 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8032 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8033 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8034 bool ret_error = false;
8035 in->bit_width = 24;
8036 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8037 from HAL is 24_packed and 8_24
8038 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8039 24_packed return error indicating supported format is 24_packed
8040 *> In case of any other source requesting 24 bit or float return error
8041 indicating format supported is 16 bit only.
8042
8043 on error flinger will retry with supported format passed
8044 */
8045 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8046 (source != AUDIO_SOURCE_CAMCORDER)) {
8047 config->format = AUDIO_FORMAT_PCM_16_BIT;
8048 if (config->sample_rate > 48000)
8049 config->sample_rate = 48000;
8050 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008051 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8052 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308053 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8054 ret_error = true;
8055 }
8056
8057 if (ret_error) {
8058 ret = -EINVAL;
8059 goto err_open;
8060 }
8061 }
8062
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008063 in->channel_mask = config->channel_mask;
8064 in->format = config->format;
8065
8066 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308067
8068 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8069 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8070 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8071 else {
8072 ret = -EINVAL;
8073 goto err_open;
8074 }
8075 }
8076
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008077 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8078 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8079 is_low_latency = true;
8080#if LOW_LATENCY_CAPTURE_USE_CASE
8081 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8082#endif
8083 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008084 if (!in->realtime) {
8085 in->config = pcm_config_audio_capture;
8086 frame_size = audio_stream_in_frame_size(&in->stream);
8087 buffer_size = get_input_buffer_size(config->sample_rate,
8088 config->format,
8089 channel_count,
8090 is_low_latency);
8091 in->config.period_size = buffer_size / frame_size;
8092 in->config.rate = config->sample_rate;
8093 in->af_period_multiplier = 1;
8094 } else {
8095 // period size is left untouched for rt mode playback
8096 in->config = pcm_config_audio_capture_rt;
8097 in->af_period_multiplier = af_period_multiplier;
8098 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008099 }
8100
8101 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8102 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8103 in->realtime = 0;
8104 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8105 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008106 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08008107 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008108 in->stream.start = in_start;
8109 in->stream.stop = in_stop;
8110 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8111 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008112 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008113 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8114 } else if (in->realtime) {
8115 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008116 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008117 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008118 in->sample_rate = in->config.rate;
8119 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008120 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008121 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8122 in->config = pcm_config_audio_capture;
8123 frame_size = audio_stream_in_frame_size(&in->stream);
8124 buffer_size = get_input_buffer_size(config->sample_rate,
8125 config->format,
8126 channel_count,
8127 false /*is_low_latency*/);
8128 in->config.period_size = buffer_size / frame_size;
8129 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008130 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008131 switch (config->format) {
8132 case AUDIO_FORMAT_PCM_32_BIT:
8133 in->bit_width = 32;
8134 break;
8135 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8136 case AUDIO_FORMAT_PCM_8_24_BIT:
8137 in->bit_width = 24;
8138 break;
8139 default:
8140 in->bit_width = 16;
8141 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008142 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008143 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008144 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308145 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008146 if (config->sample_rate == 0)
8147 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8148 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8149 config->sample_rate != 8000) {
8150 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8151 ret = -EINVAL;
8152 goto err_open;
8153 }
8154 if (config->format == AUDIO_FORMAT_DEFAULT)
8155 config->format = AUDIO_FORMAT_PCM_16_BIT;
8156 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8157 config->format = AUDIO_FORMAT_PCM_16_BIT;
8158 ret = -EINVAL;
8159 goto err_open;
8160 }
8161
8162 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8163 in->config = pcm_config_afe_proxy_record;
8164 in->config.channels = channel_count;
8165 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308166 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008167 in->af_period_multiplier = 1;
8168 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8169 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8170 (config->sample_rate == 8000 ||
8171 config->sample_rate == 16000 ||
8172 config->sample_rate == 32000 ||
8173 config->sample_rate == 48000) &&
8174 channel_count == 1) {
8175 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8176 in->config = pcm_config_audio_capture;
8177 frame_size = audio_stream_in_frame_size(&in->stream);
8178 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8179 config->sample_rate,
8180 config->format,
8181 channel_count, false /*is_low_latency*/);
8182 in->config.period_size = buffer_size / frame_size;
8183 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8184 in->config.rate = config->sample_rate;
8185 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008186 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308187 int ret_val;
8188 pthread_mutex_lock(&adev->lock);
8189 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8190 in, config, &channel_mask_updated);
8191 pthread_mutex_unlock(&adev->lock);
8192
8193 if (!ret_val) {
8194 if (channel_mask_updated == true) {
8195 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8196 __func__, config->channel_mask);
8197 ret = -EINVAL;
8198 goto err_open;
8199 }
8200 ALOGD("%s: created multi-channel session succesfully",__func__);
8201 } else if (audio_extn_compr_cap_enabled() &&
8202 audio_extn_compr_cap_format_supported(config->format) &&
8203 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8204 audio_extn_compr_cap_init(in);
8205 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05308206 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05308207 ret = audio_extn_cin_configure_input_stream(in);
8208 if (ret)
8209 goto err_open;
8210 } else {
8211 in->config = pcm_config_audio_capture;
8212 in->config.rate = config->sample_rate;
8213 in->config.format = pcm_format_from_audio_format(config->format);
8214 in->config.channels = channel_count;
8215 in->sample_rate = config->sample_rate;
8216 in->format = config->format;
8217 frame_size = audio_stream_in_frame_size(&in->stream);
8218 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008219 config->format,
8220 channel_count,
8221 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008222 /* prevent division-by-zero */
8223 if (frame_size == 0) {
8224 ALOGE("%s: Error frame_size==0", __func__);
8225 ret = -EINVAL;
8226 goto err_open;
8227 }
8228
Revathi Uddarajud2634032017-12-07 14:42:34 +05308229 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008230 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008231
Revathi Uddarajud2634032017-12-07 14:42:34 +05308232 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8233 /* optionally use VOIP usecase depending on config(s) */
8234 ret = adev_update_voice_comm_input_stream(in, config);
8235 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008236
Revathi Uddarajud2634032017-12-07 14:42:34 +05308237 if (ret) {
8238 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8239 goto err_open;
8240 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008241 }
kunleiz28c73e72019-03-27 17:24:04 +08008242#ifdef CONCURRENT_CAPTURE_ENABLED
8243 /* Acquire lock to avoid two concurrent use cases initialized to
8244 same pcm record use case */
8245
8246 pthread_mutex_lock(&adev->lock);
8247 if (in->usecase == USECASE_AUDIO_RECORD) {
8248 if (!(adev->pcm_record_uc_state)) {
8249 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8250 adev->pcm_record_uc_state = 1;
8251 } else {
8252 /* Assign compress record use case for second record */
8253 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8254 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8255 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8256 }
8257 }
8258 pthread_mutex_unlock(&adev->lock);
8259#endif
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008260 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308261 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8262 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008263 devices, flags, in->format,
8264 in->sample_rate, in->bit_width,
8265 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308266 register_format(in->format, in->supported_formats);
8267 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8268 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308269
Aalique Grahame22e49102018-12-18 14:23:57 -08008270 in->error_log = error_log_create(
8271 ERROR_LOG_ENTRIES,
8272 1000000000 /* aggregate consecutive identical errors within one second */);
8273
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008274 /* This stream could be for sound trigger lab,
8275 get sound trigger pcm if present */
8276 audio_extn_sound_trigger_check_and_get_session(in);
8277
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308278 lock_input_stream(in);
8279 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8280 pthread_mutex_lock(&adev->lock);
8281 in->card_status = adev->card_status;
8282 pthread_mutex_unlock(&adev->lock);
8283 pthread_mutex_unlock(&in->lock);
8284
Aalique Grahame22e49102018-12-18 14:23:57 -08008285 stream_app_type_cfg_init(&in->app_type_cfg);
8286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008287 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008288
8289 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8290 calloc(1, sizeof(streams_input_ctxt_t));
8291 if (in_ctxt == NULL) {
8292 ALOGE("%s fail to allocate input ctxt", __func__);
8293 ret = -ENOMEM;
8294 goto err_open;
8295 }
8296 in_ctxt->input = in;
8297
8298 pthread_mutex_lock(&adev->lock);
8299 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8300 pthread_mutex_unlock(&adev->lock);
8301
Eric Laurent994a6932013-07-17 11:51:42 -07008302 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008303 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008304
8305err_open:
8306 free(in);
8307 *stream_in = NULL;
8308 return ret;
8309}
8310
8311static void adev_close_input_stream(struct audio_hw_device *dev,
8312 struct audio_stream_in *stream)
8313{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008314 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008315 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008316 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308317
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308318 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008319
kunleiz70e57612018-12-28 17:50:23 +08008320 /* must deregister from sndmonitor first to prevent races
8321 * between the callback and close_stream
8322 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308323 audio_extn_snd_mon_unregister_listener(stream);
8324
kunleiz70e57612018-12-28 17:50:23 +08008325 /* Disable echo reference if there are no active input, hfp call
8326 * and sound trigger while closing input stream
8327 */
8328 if (!adev->active_input &&
8329 !audio_extn_hfp_is_active(adev) &&
8330 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008331 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008332 else
8333 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308334
Aalique Grahame22e49102018-12-18 14:23:57 -08008335 error_log_destroy(in->error_log);
8336 in->error_log = NULL;
8337
Pallavid7c7a272018-01-16 11:22:55 +05308338 if (in == NULL) {
8339 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8340 return;
8341 }
8342
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008343 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308344 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008345 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308346 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008347 if (ret != 0)
8348 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8349 __func__, ret);
8350 } else
8351 in_standby(&stream->common);
8352
Revathi Uddarajud2634032017-12-07 14:42:34 +05308353 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308354 if (in->usecase == USECASE_AUDIO_RECORD) {
8355 adev->pcm_record_uc_state = 0;
8356 }
8357
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008358 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008359 audio_extn_ssr_deinit();
8360 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008361
Garmond Leunge2433c32017-09-28 21:51:22 -07008362 if (audio_extn_ffv_get_stream() == in) {
8363 audio_extn_ffv_stream_deinit();
8364 }
8365
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308366 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008367 audio_extn_compr_cap_format_supported(in->config.format))
8368 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308369
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308370 if (audio_extn_cin_attached_usecase(in->usecase))
8371 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008372
Mingming Yinfd7607b2016-01-22 12:48:44 -08008373 if (in->is_st_session) {
8374 ALOGV("%s: sound trigger pcm stop lab", __func__);
8375 audio_extn_sound_trigger_stop_lab(in);
8376 }
Derek Chenf939fb72018-11-13 13:34:41 -08008377 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8378 if (in_ctxt != NULL) {
8379 list_remove(&in_ctxt->list);
8380 free(in_ctxt);
8381 } else {
8382 ALOGW("%s, input stream already closed", __func__);
8383 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008384 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308385 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008386 return;
8387}
8388
Aalique Grahame22e49102018-12-18 14:23:57 -08008389/* verifies input and output devices and their capabilities.
8390 *
8391 * This verification is required when enabling extended bit-depth or
8392 * sampling rates, as not all qcom products support it.
8393 *
8394 * Suitable for calling only on initialization such as adev_open().
8395 * It fills the audio_device use_case_table[] array.
8396 *
8397 * Has a side-effect that it needs to configure audio routing / devices
8398 * in order to power up the devices and read the device parameters.
8399 * It does not acquire any hw device lock. Should restore the devices
8400 * back to "normal state" upon completion.
8401 */
8402static int adev_verify_devices(struct audio_device *adev)
8403{
8404 /* enumeration is a bit difficult because one really wants to pull
8405 * the use_case, device id, etc from the hidden pcm_device_table[].
8406 * In this case there are the following use cases and device ids.
8407 *
8408 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8409 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8410 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8411 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8412 * [USECASE_AUDIO_RECORD] = {0, 0},
8413 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8414 * [USECASE_VOICE_CALL] = {2, 2},
8415 *
8416 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8417 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8418 */
8419
8420 /* should be the usecases enabled in adev_open_input_stream() */
8421 static const int test_in_usecases[] = {
8422 USECASE_AUDIO_RECORD,
8423 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8424 };
8425 /* should be the usecases enabled in adev_open_output_stream()*/
8426 static const int test_out_usecases[] = {
8427 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8428 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8429 };
8430 static const usecase_type_t usecase_type_by_dir[] = {
8431 PCM_PLAYBACK,
8432 PCM_CAPTURE,
8433 };
8434 static const unsigned flags_by_dir[] = {
8435 PCM_OUT,
8436 PCM_IN,
8437 };
8438
8439 size_t i;
8440 unsigned dir;
8441 const unsigned card_id = adev->snd_card;
8442
8443 for (dir = 0; dir < 2; ++dir) {
8444 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8445 const unsigned flags_dir = flags_by_dir[dir];
8446 const size_t testsize =
8447 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8448 const int *testcases =
8449 dir ? test_in_usecases : test_out_usecases;
8450 const audio_devices_t audio_device =
8451 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8452
8453 for (i = 0; i < testsize; ++i) {
8454 const audio_usecase_t audio_usecase = testcases[i];
8455 int device_id;
8456 struct pcm_params **pparams;
8457 struct stream_out out;
8458 struct stream_in in;
8459 struct audio_usecase uc_info;
8460 int retval;
8461
8462 pparams = &adev->use_case_table[audio_usecase];
8463 pcm_params_free(*pparams); /* can accept null input */
8464 *pparams = NULL;
8465
8466 /* find the device ID for the use case (signed, for error) */
8467 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8468 if (device_id < 0)
8469 continue;
8470
8471 /* prepare structures for device probing */
8472 memset(&uc_info, 0, sizeof(uc_info));
8473 uc_info.id = audio_usecase;
8474 uc_info.type = usecase_type;
8475 if (dir) {
8476 adev->active_input = &in;
8477 memset(&in, 0, sizeof(in));
8478 in.device = audio_device;
8479 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8480 uc_info.stream.in = &in;
8481 } else {
8482 adev->active_input = NULL;
8483 }
8484 memset(&out, 0, sizeof(out));
8485 out.devices = audio_device; /* only field needed in select_devices */
8486 uc_info.stream.out = &out;
8487 uc_info.devices = audio_device;
8488 uc_info.in_snd_device = SND_DEVICE_NONE;
8489 uc_info.out_snd_device = SND_DEVICE_NONE;
8490 list_add_tail(&adev->usecase_list, &uc_info.list);
8491
8492 /* select device - similar to start_(in/out)put_stream() */
8493 retval = select_devices(adev, audio_usecase);
8494 if (retval >= 0) {
8495 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8496#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008497 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008498 if (*pparams) {
8499 ALOGV("%s: (%s) card %d device %d", __func__,
8500 dir ? "input" : "output", card_id, device_id);
8501 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8502 } else {
8503 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8504 }
8505#endif
8506 }
8507
8508 /* deselect device - similar to stop_(in/out)put_stream() */
8509 /* 1. Get and set stream specific mixer controls */
8510 retval = disable_audio_route(adev, &uc_info);
8511 /* 2. Disable the rx device */
8512 retval = disable_snd_device(adev,
8513 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8514 list_remove(&uc_info.list);
8515 }
8516 }
8517 adev->active_input = NULL; /* restore adev state */
8518 return 0;
8519}
8520
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308521int adev_create_audio_patch(struct audio_hw_device *dev,
8522 unsigned int num_sources,
8523 const struct audio_port_config *sources,
8524 unsigned int num_sinks,
8525 const struct audio_port_config *sinks,
8526 audio_patch_handle_t *handle)
8527{
Derek Chenf939fb72018-11-13 13:34:41 -08008528 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308529
Derek Chenf939fb72018-11-13 13:34:41 -08008530 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8531 num_sources,
8532 sources,
8533 num_sinks,
8534 sinks,
8535 handle);
8536 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8537 num_sources,
8538 sources,
8539 num_sinks,
8540 sinks,
8541 handle);
8542 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308543}
8544
8545int adev_release_audio_patch(struct audio_hw_device *dev,
8546 audio_patch_handle_t handle)
8547{
Derek Chenf939fb72018-11-13 13:34:41 -08008548 int ret;
8549
8550 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8551 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8552 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308553}
8554
8555int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8556{
8557 return audio_extn_hw_loopback_get_audio_port(dev, config);
8558}
8559
8560int adev_set_audio_port_config(struct audio_hw_device *dev,
8561 const struct audio_port_config *config)
8562{
8563 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8564}
8565
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008566static int adev_dump(const audio_hw_device_t *device __unused,
8567 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008568{
8569 return 0;
8570}
8571
8572static int adev_close(hw_device_t *device)
8573{
Aalique Grahame22e49102018-12-18 14:23:57 -08008574 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008575 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008576
8577 if (!adev)
8578 return 0;
8579
8580 pthread_mutex_lock(&adev_init_lock);
8581
8582 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308583 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008584 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008585 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008586 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008587 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308588 audio_extn_utils_release_streams_cfg_lists(
8589 &adev->streams_output_cfg_list,
8590 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308591 if (audio_extn_qaf_is_enabled())
8592 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008593 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008594 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008595 free(adev->snd_dev_ref_cnt);
8596 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008597 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8598 pcm_params_free(adev->use_case_table[i]);
8599 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008600 if (adev->adm_deinit)
8601 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308602 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008603 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308604 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308605 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008606 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308607 if (adev->device_cfg_params) {
8608 free(adev->device_cfg_params);
8609 adev->device_cfg_params = NULL;
8610 }
Derek Chend2530072014-11-24 12:39:14 -08008611 if(adev->ext_hw_plugin)
8612 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008613 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008614 free(device);
8615 adev = NULL;
8616 }
8617 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308618 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008619 return 0;
8620}
8621
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008622/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8623 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8624 * just that it _might_ work.
8625 */
8626static int period_size_is_plausible_for_low_latency(int period_size)
8627{
8628 switch (period_size) {
8629 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008630 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008631 case 240:
8632 case 320:
8633 case 480:
8634 return 1;
8635 default:
8636 return 0;
8637 }
8638}
8639
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308640static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8641{
8642 bool is_snd_card_status = false;
8643 bool is_ext_device_status = false;
8644 char value[32];
8645 int card = -1;
8646 card_status_t status;
8647
8648 if (cookie != adev || !parms)
8649 return;
8650
8651 if (!parse_snd_card_status(parms, &card, &status)) {
8652 is_snd_card_status = true;
8653 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8654 is_ext_device_status = true;
8655 } else {
8656 // not a valid event
8657 return;
8658 }
8659
8660 pthread_mutex_lock(&adev->lock);
8661 if (card == adev->snd_card || is_ext_device_status) {
8662 if (is_snd_card_status && adev->card_status != status) {
8663 adev->card_status = status;
8664 platform_snd_card_update(adev->platform, status);
8665 audio_extn_fm_set_parameters(adev, parms);
8666 } else if (is_ext_device_status) {
8667 platform_set_parameters(adev->platform, parms);
8668 }
8669 }
8670 pthread_mutex_unlock(&adev->lock);
8671 return;
8672}
8673
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308674/* out and adev lock held */
8675static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8676{
8677 struct audio_usecase *uc_info;
8678 float left_p;
8679 float right_p;
8680 audio_devices_t devices;
8681
8682 uc_info = get_usecase_from_list(adev, out->usecase);
8683 if (uc_info == NULL) {
8684 ALOGE("%s: Could not find the usecase (%d) in the list",
8685 __func__, out->usecase);
8686 return -EINVAL;
8687 }
8688
8689 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8690 out->usecase, use_case_table[out->usecase]);
8691
8692 if (restore) {
8693 // restore A2DP device for active usecases and unmute if required
8694 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8695 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8696 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8697 select_devices(adev, uc_info->id);
8698 pthread_mutex_lock(&out->compr_mute_lock);
8699 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8700 (out->a2dp_compress_mute)) {
8701 out->a2dp_compress_mute = false;
8702 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8703 }
8704 pthread_mutex_unlock(&out->compr_mute_lock);
8705 }
8706 } else {
8707 // mute compress stream if suspended
8708 pthread_mutex_lock(&out->compr_mute_lock);
8709 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8710 (!out->a2dp_compress_mute)) {
8711 if (!out->standby) {
8712 ALOGD("%s: selecting speaker and muting stream", __func__);
8713 devices = out->devices;
8714 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8715 left_p = out->volume_l;
8716 right_p = out->volume_r;
8717 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8718 compress_pause(out->compr);
8719 out_set_compr_volume(&out->stream, (float)0, (float)0);
8720 out->a2dp_compress_mute = true;
8721 select_devices(adev, out->usecase);
8722 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8723 compress_resume(out->compr);
8724 out->devices = devices;
8725 out->volume_l = left_p;
8726 out->volume_r = right_p;
8727 }
8728 }
8729 pthread_mutex_unlock(&out->compr_mute_lock);
8730 }
8731 ALOGV("%s: exit", __func__);
8732 return 0;
8733}
8734
8735int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8736{
8737 int ret = 0;
8738
8739 lock_output_stream(out);
8740 pthread_mutex_lock(&adev->lock);
8741
8742 ret = check_a2dp_restore_l(adev, out, restore);
8743
8744 pthread_mutex_unlock(&adev->lock);
8745 pthread_mutex_unlock(&out->lock);
8746 return ret;
8747}
8748
Haynes Mathew George01156f92018-04-13 15:29:54 -07008749void adev_on_battery_status_changed(bool charging)
8750{
8751 pthread_mutex_lock(&adev->lock);
8752 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8753 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008754 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008755 pthread_mutex_unlock(&adev->lock);
8756}
8757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008758static int adev_open(const hw_module_t *module, const char *name,
8759 hw_device_t **device)
8760{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308761 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008762 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308763 char mixer_ctl_name[128] = {0};
8764 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308765
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008766 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008767 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8768
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008769 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008770 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008771 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008772 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008773 ALOGD("%s: returning existing instance of adev", __func__);
8774 ALOGD("%s: exit", __func__);
8775 pthread_mutex_unlock(&adev_init_lock);
8776 return 0;
8777 }
8778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779 adev = calloc(1, sizeof(struct audio_device));
8780
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008781 if (!adev) {
8782 pthread_mutex_unlock(&adev_init_lock);
8783 return -ENOMEM;
8784 }
8785
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008786 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8787
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008788 // register audio ext hidl at the earliest
8789 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308790#ifdef DYNAMIC_LOG_ENABLED
8791 register_for_dynamic_logging("hal");
8792#endif
8793
Derek Chenf939fb72018-11-13 13:34:41 -08008794 /* default audio HAL major version */
8795 uint32_t maj_version = 2;
8796 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8797 maj_version = atoi(value);
8798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008799 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008800 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008801 adev->device.common.module = (struct hw_module_t *)module;
8802 adev->device.common.close = adev_close;
8803
8804 adev->device.init_check = adev_init_check;
8805 adev->device.set_voice_volume = adev_set_voice_volume;
8806 adev->device.set_master_volume = adev_set_master_volume;
8807 adev->device.get_master_volume = adev_get_master_volume;
8808 adev->device.set_master_mute = adev_set_master_mute;
8809 adev->device.get_master_mute = adev_get_master_mute;
8810 adev->device.set_mode = adev_set_mode;
8811 adev->device.set_mic_mute = adev_set_mic_mute;
8812 adev->device.get_mic_mute = adev_get_mic_mute;
8813 adev->device.set_parameters = adev_set_parameters;
8814 adev->device.get_parameters = adev_get_parameters;
8815 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8816 adev->device.open_output_stream = adev_open_output_stream;
8817 adev->device.close_output_stream = adev_close_output_stream;
8818 adev->device.open_input_stream = adev_open_input_stream;
8819 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308820 adev->device.create_audio_patch = adev_create_audio_patch;
8821 adev->device.release_audio_patch = adev_release_audio_patch;
8822 adev->device.get_audio_port = adev_get_audio_port;
8823 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308825 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008826
8827 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008828 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008829 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008830 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008831 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008832 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008833 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008834 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308835 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008836 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008837 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008838 /* Init audio feature manager */
8839 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008840 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008841 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08008842 list_init(&adev->active_inputs_list);
8843 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008844 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008845 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308846 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308847 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308848 adev->perf_lock_opts[0] = 0x101;
8849 adev->perf_lock_opts[1] = 0x20E;
8850 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008851 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07008852 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308853 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008855 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008856 adev->platform = platform_init(adev);
8857 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008858 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008859 free(adev->snd_dev_ref_cnt);
8860 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008861 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008862 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8863 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008864 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008865 return -EINVAL;
8866 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008867
Aalique Grahame22e49102018-12-18 14:23:57 -08008868 adev->extspk = audio_extn_extspk_init(adev);
8869
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308870 if (audio_extn_qaf_is_enabled()) {
8871 ret = audio_extn_qaf_init(adev);
8872 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008873 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308874 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008875 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308876 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8877 *device = NULL;
8878 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308879 return ret;
8880 }
8881
8882 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8883 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8884 }
8885
Derek Chenae7b0342019-02-08 15:17:04 -08008886 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08008887 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8888
Eric Laurentc4aef752013-09-12 17:45:53 -07008889 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8890 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8891 if (adev->visualizer_lib == NULL) {
8892 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8893 } else {
8894 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8895 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008896 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008897 "visualizer_hal_start_output");
8898 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008899 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008900 "visualizer_hal_stop_output");
8901 }
8902 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308903 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008904 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008905 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008906 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308907 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008908 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008909
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008910 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8911 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8912 if (adev->offload_effects_lib == NULL) {
8913 ALOGE("%s: DLOPEN failed for %s", __func__,
8914 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8915 } else {
8916 ALOGV("%s: DLOPEN successful for %s", __func__,
8917 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8918 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308919 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008920 "offload_effects_bundle_hal_start_output");
8921 adev->offload_effects_stop_output =
8922 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8923 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008924 adev->offload_effects_set_hpx_state =
8925 (int (*)(bool))dlsym(adev->offload_effects_lib,
8926 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308927 adev->offload_effects_get_parameters =
8928 (void (*)(struct str_parms *, struct str_parms *))
8929 dlsym(adev->offload_effects_lib,
8930 "offload_effects_bundle_get_parameters");
8931 adev->offload_effects_set_parameters =
8932 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8933 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008934 }
8935 }
8936
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008937 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8938 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8939 if (adev->adm_lib == NULL) {
8940 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8941 } else {
8942 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8943 adev->adm_init = (adm_init_t)
8944 dlsym(adev->adm_lib, "adm_init");
8945 adev->adm_deinit = (adm_deinit_t)
8946 dlsym(adev->adm_lib, "adm_deinit");
8947 adev->adm_register_input_stream = (adm_register_input_stream_t)
8948 dlsym(adev->adm_lib, "adm_register_input_stream");
8949 adev->adm_register_output_stream = (adm_register_output_stream_t)
8950 dlsym(adev->adm_lib, "adm_register_output_stream");
8951 adev->adm_deregister_stream = (adm_deregister_stream_t)
8952 dlsym(adev->adm_lib, "adm_deregister_stream");
8953 adev->adm_request_focus = (adm_request_focus_t)
8954 dlsym(adev->adm_lib, "adm_request_focus");
8955 adev->adm_abandon_focus = (adm_abandon_focus_t)
8956 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008957 adev->adm_set_config = (adm_set_config_t)
8958 dlsym(adev->adm_lib, "adm_set_config");
8959 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8960 dlsym(adev->adm_lib, "adm_request_focus_v2");
8961 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8962 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8963 adev->adm_on_routing_change = (adm_on_routing_change_t)
8964 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008965 }
8966 }
8967
Aalique Grahame22e49102018-12-18 14:23:57 -08008968 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008969 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008970 //initialize this to false for now,
8971 //this will be set to true through set param
8972 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008973
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008974 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008975 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08008976
8977 if (k_enable_extended_precision)
8978 adev_verify_devices(adev);
8979
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008980 adev->dsp_bit_width_enforce_mode =
8981 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008982
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308983 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8984 &adev->streams_output_cfg_list,
8985 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008986
Kiran Kandi910e1862013-10-29 13:29:42 -07008987 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008988
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008989 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08008990 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
8991 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008992 trial = atoi(value);
8993 if (period_size_is_plausible_for_low_latency(trial)) {
8994 pcm_config_low_latency.period_size = trial;
8995 pcm_config_low_latency.start_threshold = trial / 4;
8996 pcm_config_low_latency.avail_min = trial / 4;
8997 configured_low_latency_capture_period_size = trial;
8998 }
8999 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009000 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9001 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009002 trial = atoi(value);
9003 if (period_size_is_plausible_for_low_latency(trial)) {
9004 configured_low_latency_capture_period_size = trial;
9005 }
9006 }
9007
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009008 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9009
Aalique Grahame22e49102018-12-18 14:23:57 -08009010 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9011 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009012 af_period_multiplier = atoi(value);
9013 if (af_period_multiplier < 0)
9014 af_period_multiplier = 2;
9015 else if (af_period_multiplier > 4)
9016 af_period_multiplier = 4;
9017
9018 ALOGV("new period_multiplier = %d", af_period_multiplier);
9019 }
9020
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009021 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009022
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009023 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009024 pthread_mutex_unlock(&adev_init_lock);
9025
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009026 if (adev->adm_init)
9027 adev->adm_data = adev->adm_init();
9028
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309029 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309030 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009031 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309032
9033 audio_extn_snd_mon_init();
9034 pthread_mutex_lock(&adev->lock);
9035 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9036 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009037 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9038 /*
9039 * if the battery state callback happens before charging can be queried,
9040 * it will be guarded with the adev->lock held in the cb function and so
9041 * the callback value will reflect the latest state
9042 */
9043 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309044 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009045 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
9046 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309047 /* Allocate memory for Device config params */
9048 adev->device_cfg_params = (struct audio_device_config_param*)
9049 calloc(platform_get_max_codec_backend(),
9050 sizeof(struct audio_device_config_param));
9051 if (adev->device_cfg_params == NULL)
9052 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309053
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309054 /*
9055 * Check if new PSPD matrix mixer control is supported. If not
9056 * supported, then set flag so that old mixer ctrl is sent while
9057 * sending pspd coefficients on older kernel version. Query mixer
9058 * control for default pcm id and channel value one.
9059 */
9060 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9061 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9062
9063 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9064 if (!ctl) {
9065 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9066 __func__, mixer_ctl_name);
9067 adev->use_old_pspd_mix_ctrl = true;
9068 }
9069
Eric Laurent994a6932013-07-17 11:51:42 -07009070 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009071 return 0;
9072}
9073
9074static struct hw_module_methods_t hal_module_methods = {
9075 .open = adev_open,
9076};
9077
9078struct audio_module HAL_MODULE_INFO_SYM = {
9079 .common = {
9080 .tag = HARDWARE_MODULE_TAG,
9081 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9082 .hal_api_version = HARDWARE_HAL_API_VERSION,
9083 .id = AUDIO_HARDWARE_MODULE_ID,
9084 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009085 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009086 .methods = &hal_module_methods,
9087 },
9088};