blob: e33f248ed2991cde73127d17104a8479bd58495e [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 }
1072
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001073 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001074 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001075 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301076 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1077 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1078 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1079 if (parms) {
1080 audio_extn_fm_set_parameters(adev, parms);
1081 str_parms_destroy(parms);
1082 }
1083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 ALOGV("%s: exit", __func__);
1085 return 0;
1086}
1087
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001088int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001089 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001092 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001093
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301094 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001095 return -EINVAL;
1096
1097 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301098 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001099 snd_device = usecase->in_snd_device;
1100 else
1101 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001102 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001103 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001104 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001105 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001106 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301107 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 ALOGV("%s: exit", __func__);
1109 return 0;
1110}
1111
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001112int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301115 int i, num_devices = 0;
1116 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001117 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1118
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001119 if (snd_device < SND_DEVICE_MIN ||
1120 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001121 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001122 return -EINVAL;
1123 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124
1125 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001126
1127 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1128 ALOGE("%s: Invalid sound device returned", __func__);
1129 return -EINVAL;
1130 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001132 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001133 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 return 0;
1135 }
1136
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301137
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001138 if (audio_extn_spkr_prot_is_enabled())
1139 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001140
Aalique Grahame22e49102018-12-18 14:23:57 -08001141 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1142
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001143 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1144 audio_extn_spkr_prot_is_enabled()) {
1145 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001146 adev->snd_dev_ref_cnt[snd_device]--;
1147 return -EINVAL;
1148 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001149 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001150 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001151 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001152 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001153 return -EINVAL;
1154 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001155 } else if (platform_split_snd_device(adev->platform,
1156 snd_device,
1157 &num_devices,
1158 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301159 for (i = 0; i < num_devices; i++) {
1160 enable_snd_device(adev, new_snd_devices[i]);
1161 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001162 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001163 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001164 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301165
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301166
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301167 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1168 (audio_extn_a2dp_start_playback() < 0)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02001169 ALOGE(" fail to configure A2dp Source control path ");
1170 return -EINVAL;
1171 }
1172
1173 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1174 (audio_extn_a2dp_start_capture() < 0)) {
1175 ALOGE(" fail to configure A2dp Sink control path ");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301176 return -EINVAL;
1177 }
1178
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001179 /* due to the possibility of calibration overwrite between listen
1180 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001181 audio_extn_sound_trigger_update_device_status(snd_device,
1182 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301183 audio_extn_listen_update_device_status(snd_device,
1184 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001185 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001186 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001187 audio_extn_sound_trigger_update_device_status(snd_device,
1188 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301189 audio_extn_listen_update_device_status(snd_device,
1190 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001191 return -EINVAL;
1192 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001193 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001194 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301195
1196 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1197 !adev->native_playback_enabled &&
1198 audio_is_true_native_stream_active(adev)) {
1199 ALOGD("%s: %d: napb: enabling native mode in hardware",
1200 __func__, __LINE__);
1201 audio_route_apply_and_update_path(adev->audio_route,
1202 "true-native-mode");
1203 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301204 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301205 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1206 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001207 (audio_extn_ffv_get_stream() == adev->active_input)) {
1208 ALOGD("%s: init ec ref loopback", __func__);
1209 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 return 0;
1213}
1214
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001215int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001216 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301218 int i, num_devices = 0;
1219 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001220 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1221
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001222 if (snd_device < SND_DEVICE_MIN ||
1223 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001224 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001225 return -EINVAL;
1226 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1228 ALOGE("%s: device ref cnt is already 0", __func__);
1229 return -EINVAL;
1230 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001231
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001232 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001233
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001234 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1235 ALOGE("%s: Invalid sound device returned", __func__);
1236 return -EINVAL;
1237 }
1238
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001239 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001240 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301241
Aalique Grahame22e49102018-12-18 14:23:57 -08001242 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1243
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001244 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1245 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001246 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001247
1248 // when speaker device is disabled, reset swap.
1249 // will be renabled on usecase start
1250 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001251 } else if (platform_split_snd_device(adev->platform,
1252 snd_device,
1253 &num_devices,
1254 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301255 for (i = 0; i < num_devices; i++) {
1256 disable_snd_device(adev, new_snd_devices[i]);
1257 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001258 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001259 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001260 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001261 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001262
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301263 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1264 audio_extn_a2dp_stop_playback();
1265
Florian Pfister1a84f312018-07-19 14:38:18 +02001266 if (SND_DEVICE_IN_BT_A2DP == snd_device)
1267 audio_extn_a2dp_stop_capture();
1268
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001269 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301270 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301271 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1272 adev->native_playback_enabled) {
1273 ALOGD("%s: %d: napb: disabling native mode in hardware",
1274 __func__, __LINE__);
1275 audio_route_reset_and_update_path(adev->audio_route,
1276 "true-native-mode");
1277 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301278 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1279 adev->asrc_mode_enabled) {
1280 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301281 disable_asrc_mode(adev);
1282 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301283 }
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301284 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1285 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001286 (audio_extn_ffv_get_stream() == adev->active_input)) {
1287 ALOGD("%s: deinit ec ref loopback", __func__);
1288 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1289 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001290 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001291 audio_extn_sound_trigger_update_device_status(snd_device,
1292 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301293 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001294 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 return 0;
1298}
1299
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001300/*
1301 legend:
1302 uc - existing usecase
1303 new_uc - new usecase
1304 d1, d11, d2 - SND_DEVICE enums
1305 a1, a2 - corresponding ANDROID device enums
1306 B1, B2 - backend strings
1307
1308case 1
1309 uc->dev d1 (a1) B1
1310 new_uc->dev d1 (a1), d2 (a2) B1, B2
1311
1312 resolution: disable and enable uc->dev on d1
1313
1314case 2
1315 uc->dev d1 (a1) B1
1316 new_uc->dev d11 (a1) B1
1317
1318 resolution: need to switch uc since d1 and d11 are related
1319 (e.g. speaker and voice-speaker)
1320 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1321
1322case 3
1323 uc->dev d1 (a1) B1
1324 new_uc->dev d2 (a2) B2
1325
1326 resolution: no need to switch uc
1327
1328case 4
1329 uc->dev d1 (a1) B1
1330 new_uc->dev d2 (a2) B1
1331
1332 resolution: disable enable uc-dev on d2 since backends match
1333 we cannot enable two streams on two different devices if they
1334 share the same backend. e.g. if offload is on speaker device using
1335 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1336 using the same backend, offload must also be switched to voice-handset.
1337
1338case 5
1339 uc->dev d1 (a1) B1
1340 new_uc->dev d1 (a1), d2 (a2) B1
1341
1342 resolution: disable enable uc-dev on d2 since backends match
1343 we cannot enable two streams on two different devices if they
1344 share the same backend.
1345
1346case 6
1347 uc->dev d1 (a1) B1
1348 new_uc->dev d2 (a1) B2
1349
1350 resolution: no need to switch
1351
1352case 7
1353 uc->dev d1 (a1), d2 (a2) B1, B2
1354 new_uc->dev d1 (a1) B1
1355
1356 resolution: no need to switch
1357
Zhou Song4ba65882018-07-09 14:48:07 +08001358case 8
1359 uc->dev d1 (a1) B1
1360 new_uc->dev d11 (a1), d2 (a2) B1, B2
1361 resolution: compared to case 1, for this case, d1 and d11 are related
1362 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001363*/
1364static snd_device_t derive_playback_snd_device(void * platform,
1365 struct audio_usecase *uc,
1366 struct audio_usecase *new_uc,
1367 snd_device_t new_snd_device)
1368{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301369 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001370
1371 snd_device_t d1 = uc->out_snd_device;
1372 snd_device_t d2 = new_snd_device;
1373
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301374 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301375 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301376 a1 = uc->stream.inout->out_config.devices;
1377 a2 = new_uc->stream.inout->out_config.devices;
1378 break;
1379 default :
1380 a1 = uc->stream.out->devices;
1381 a2 = new_uc->stream.out->devices;
1382 break;
1383 }
1384
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001385 // Treat as a special case when a1 and a2 are not disjoint
1386 if ((a1 != a2) && (a1 & a2)) {
1387 snd_device_t d3[2];
1388 int num_devices = 0;
1389 int ret = platform_split_snd_device(platform,
1390 popcount(a1) > 1 ? d1 : d2,
1391 &num_devices,
1392 d3);
1393 if (ret < 0) {
1394 if (ret != -ENOSYS) {
1395 ALOGW("%s failed to split snd_device %d",
1396 __func__,
1397 popcount(a1) > 1 ? d1 : d2);
1398 }
1399 goto end;
1400 }
1401
1402 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1403 // But if it does happen, we need to give priority to d2 if
1404 // the combo devices active on the existing usecase share a backend.
1405 // This is because we cannot have a usecase active on a combo device
1406 // and a new usecase requests one device in this combo pair.
1407 if (platform_check_backends_match(d3[0], d3[1])) {
1408 return d2; // case 5
1409 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001410 // check if d1 is related to any of d3's
1411 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001412 return d1; // case 1
1413 else
1414 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001415 }
1416 } else {
1417 if (platform_check_backends_match(d1, d2)) {
1418 return d2; // case 2, 4
1419 } else {
1420 return d1; // case 6, 3
1421 }
1422 }
1423
1424end:
1425 return d2; // return whatever was calculated before.
1426}
1427
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001428static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301429 struct audio_usecase *uc_info,
1430 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431{
1432 struct listnode *node;
1433 struct audio_usecase *usecase;
1434 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301435 snd_device_t uc_derive_snd_device;
1436 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001437 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001438 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301439 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 /*
1441 * This function is to make sure that all the usecases that are active on
1442 * the hardware codec backend are always routed to any one device that is
1443 * handled by the hardware codec.
1444 * For example, if low-latency and deep-buffer usecases are currently active
1445 * on speaker and out_set_parameters(headset) is received on low-latency
1446 * output, then we have to make sure deep-buffer is also switched to headset,
1447 * because of the limitation that both the devices cannot be enabled
1448 * at the same time as they share the same backend.
1449 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001450 /*
1451 * This call is to check if we need to force routing for a particular stream
1452 * If there is a backend configuration change for the device when a
1453 * new stream starts, then ADM needs to be closed and re-opened with the new
1454 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001455 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001456 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001457 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1458 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301459 /* For a2dp device reconfigure all active sessions
1460 * with new AFE encoder format based on a2dp state
1461 */
1462 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1463 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1464 audio_extn_a2dp_is_force_device_switch()) {
1465 force_routing = true;
1466 force_restart_session = true;
1467 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301468 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1469
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001471 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001472 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1474 switch_device[i] = false;
1475
1476 list_for_each(node, &adev->usecase_list) {
1477 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001478
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301479 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1480 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301481 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301482 platform_get_snd_device_name(usecase->out_snd_device),
1483 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301484 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1485 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1486 usecase, uc_info, snd_device);
1487 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1488 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1489 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1490 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001491 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301492 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1493 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1494 ((force_restart_session) ||
1495 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301496 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1497 __func__, use_case_table[usecase->id],
1498 platform_get_snd_device_name(usecase->out_snd_device));
1499 disable_audio_route(adev, usecase);
1500 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301501 /* Enable existing usecase on derived playback device */
1502 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301503 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301504 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 }
1506 }
1507
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301508 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1509 num_uc_to_switch);
1510
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001511 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001512 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301514 /* Make sure the previous devices to be disabled first and then enable the
1515 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 list_for_each(node, &adev->usecase_list) {
1517 usecase = node_to_item(node, struct audio_usecase, list);
1518 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001519 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 }
1521 }
1522
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001523 list_for_each(node, &adev->usecase_list) {
1524 usecase = node_to_item(node, struct audio_usecase, list);
1525 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301526 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001527 }
1528 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 /* Re-route all the usecases on the shared backend other than the
1531 specified usecase to new snd devices */
1532 list_for_each(node, &adev->usecase_list) {
1533 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301534 /* Update the out_snd_device only before enabling the audio route */
1535 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301536 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301537 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301538 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301539 use_case_table[usecase->id],
1540 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001541 /* Update voc calibration before enabling VoIP route */
1542 if (usecase->type == VOIP_CALL)
1543 status = platform_switch_voice_call_device_post(adev->platform,
1544 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001545 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301546 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001547 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1548 out_set_voip_volume(&usecase->stream.out->stream,
1549 usecase->stream.out->volume_l,
1550 usecase->stream.out->volume_r);
1551 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301552 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 }
1554 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 }
1556}
1557
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301558static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001559 struct audio_usecase *uc_info,
1560 snd_device_t snd_device)
1561{
1562 struct listnode *node;
1563 struct audio_usecase *usecase;
1564 bool switch_device[AUDIO_USECASE_MAX];
1565 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301566 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001567 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001568
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301569 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1570 snd_device);
1571 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301572
1573 /*
1574 * Make sure out devices is checked against out codec backend device and
1575 * also in devices against in codec backend. Checking out device against in
1576 * codec backend or vice versa causes issues.
1577 */
1578 if (uc_info->type == PCM_CAPTURE)
1579 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001580 /*
1581 * This function is to make sure that all the active capture usecases
1582 * are always routed to the same input sound device.
1583 * For example, if audio-record and voice-call usecases are currently
1584 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1585 * is received for voice call then we have to make sure that audio-record
1586 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1587 * because of the limitation that two devices cannot be enabled
1588 * at the same time if they share the same backend.
1589 */
1590 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1591 switch_device[i] = false;
1592
1593 list_for_each(node, &adev->usecase_list) {
1594 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301595 /*
1596 * TODO: Enhance below condition to handle BT sco/USB multi recording
1597 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001598 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001599 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301600 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301601 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301602 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301603 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001604 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001605 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1606 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001607 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001608 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001609 switch_device[usecase->id] = true;
1610 num_uc_to_switch++;
1611 }
1612 }
1613
1614 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001615 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001616
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301617 /* Make sure the previous devices to be disabled first and then enable the
1618 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001619 list_for_each(node, &adev->usecase_list) {
1620 usecase = node_to_item(node, struct audio_usecase, list);
1621 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001622 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001623 }
1624 }
1625
1626 list_for_each(node, &adev->usecase_list) {
1627 usecase = node_to_item(node, struct audio_usecase, list);
1628 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001629 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001630 }
1631 }
1632
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001633 /* Re-route all the usecases on the shared backend other than the
1634 specified usecase to new snd devices */
1635 list_for_each(node, &adev->usecase_list) {
1636 usecase = node_to_item(node, struct audio_usecase, list);
1637 /* Update the in_snd_device only before enabling the audio route */
1638 if (switch_device[usecase->id] ) {
1639 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001640 if (usecase->type != VOICE_CALL) {
1641 /* Update voc calibration before enabling VoIP route */
1642 if (usecase->type == VOIP_CALL)
1643 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001644 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001645 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301646 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001647 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001648 }
1649 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001650 }
1651}
1652
Mingming Yin3a941d42016-02-17 18:08:05 -08001653static void reset_hdmi_sink_caps(struct stream_out *out) {
1654 int i = 0;
1655
1656 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1657 out->supported_channel_masks[i] = 0;
1658 }
1659 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1660 out->supported_formats[i] = 0;
1661 }
1662 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1663 out->supported_sample_rates[i] = 0;
1664 }
1665}
1666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001668static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669{
Mingming Yin3a941d42016-02-17 18:08:05 -08001670 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001671 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672
Mingming Yin3a941d42016-02-17 18:08:05 -08001673 reset_hdmi_sink_caps(out);
1674
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001675 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001676 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001677 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001678 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001679 }
1680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001683 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001684 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001685 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1686 case 6:
1687 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1688 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1689 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1690 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1691 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1692 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 break;
1694 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001695 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001696 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 break;
1698 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001699
1700 // check channel format caps
1701 i = 0;
1702 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1703 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1704 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1705 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1706 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1707 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1708 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1709 }
1710
Ben Romberger1aaaf862017-04-06 17:49:46 -07001711 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1712 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1713 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1714 }
1715
Mingming Yin3a941d42016-02-17 18:08:05 -08001716 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1717 ALOGV(":%s HDMI supports DTS format", __func__);
1718 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1719 }
1720
1721 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1722 ALOGV(":%s HDMI supports DTS HD format", __func__);
1723 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1724 }
1725
Naresh Tanniru928f0862017-04-07 16:44:23 -07001726 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1727 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1728 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1729 }
1730
Mingming Yin3a941d42016-02-17 18:08:05 -08001731
1732 // check sample rate caps
1733 i = 0;
1734 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1735 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1736 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1737 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1738 }
1739 }
1740
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001741 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742}
1743
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001744static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1745 uint32_t *supported_sample_rates __unused,
1746 uint32_t max_rates __unused)
1747{
1748 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1749 supported_sample_rates,
1750 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301751 ssize_t i = 0;
1752
1753 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001754 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1755 supported_sample_rates[i]);
1756 }
1757 return count;
1758}
1759
1760static inline int read_usb_sup_channel_masks(bool is_playback,
1761 audio_channel_mask_t *supported_channel_masks,
1762 uint32_t max_masks)
1763{
1764 int channels = audio_extn_usb_get_max_channels(is_playback);
1765 int channel_count;
1766 uint32_t num_masks = 0;
1767 if (channels > MAX_HIFI_CHANNEL_COUNT)
1768 channels = MAX_HIFI_CHANNEL_COUNT;
1769
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301770 channel_count = DEFAULT_CHANNEL_COUNT;
1771
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001772 if (is_playback) {
1773 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001774 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301775 // above 2 but we want indexed masks here.
1776 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001777 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001778 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1779 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301780 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001781 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301782
1783 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1784 (num_masks < max_masks)); channel_count--) {
1785 supported_channel_masks[num_masks++] =
1786 audio_channel_mask_for_index_assignment_from_count(channel_count);
1787 }
1788
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001789 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1790 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1791 return num_masks;
1792}
1793
1794static inline int read_usb_sup_formats(bool is_playback __unused,
1795 audio_format_t *supported_formats,
1796 uint32_t max_formats __unused)
1797{
1798 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1799 switch (bitwidth) {
1800 case 24:
1801 // XXX : usb.c returns 24 for s24 and s24_le?
1802 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1803 break;
1804 case 32:
1805 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1806 break;
1807 case 16:
1808 default :
1809 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1810 break;
1811 }
1812 ALOGV("%s: %s supported format %d", __func__,
1813 is_playback ? "P" : "C", bitwidth);
1814 return 1;
1815}
1816
1817static inline int read_usb_sup_params_and_compare(bool is_playback,
1818 audio_format_t *format,
1819 audio_format_t *supported_formats,
1820 uint32_t max_formats,
1821 audio_channel_mask_t *mask,
1822 audio_channel_mask_t *supported_channel_masks,
1823 uint32_t max_masks,
1824 uint32_t *rate,
1825 uint32_t *supported_sample_rates,
1826 uint32_t max_rates) {
1827 int ret = 0;
1828 int num_formats;
1829 int num_masks;
1830 int num_rates;
1831 int i;
1832
1833 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1834 max_formats);
1835 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1836 max_masks);
1837
1838 num_rates = read_usb_sup_sample_rates(is_playback,
1839 supported_sample_rates, max_rates);
1840
1841#define LUT(table, len, what, dflt) \
1842 for (i=0; i<len && (table[i] != what); i++); \
1843 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1844
1845 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1846 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1847 LUT(supported_sample_rates, num_rates, *rate, 0);
1848
1849#undef LUT
1850 return ret < 0 ? -EINVAL : 0; // HACK TBD
1851}
1852
Alexy Josephb1379942016-01-29 15:49:38 -08001853audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001854 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001855{
1856 struct audio_usecase *usecase;
1857 struct listnode *node;
1858
1859 list_for_each(node, &adev->usecase_list) {
1860 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001861 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001862 ALOGV("%s: usecase id %d", __func__, usecase->id);
1863 return usecase->id;
1864 }
1865 }
1866 return USECASE_INVALID;
1867}
1868
Alexy Josephb1379942016-01-29 15:49:38 -08001869struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001870 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001871{
1872 struct audio_usecase *usecase;
1873 struct listnode *node;
1874
1875 list_for_each(node, &adev->usecase_list) {
1876 usecase = node_to_item(node, struct audio_usecase, list);
1877 if (usecase->id == uc_id)
1878 return usecase;
1879 }
1880 return NULL;
1881}
1882
Dhananjay Kumard4833242016-10-06 22:09:12 +05301883struct stream_in *get_next_active_input(const struct audio_device *adev)
1884{
1885 struct audio_usecase *usecase;
1886 struct listnode *node;
1887
1888 list_for_each_reverse(node, &adev->usecase_list) {
1889 usecase = node_to_item(node, struct audio_usecase, list);
1890 if (usecase->type == PCM_CAPTURE)
1891 return usecase->stream.in;
1892 }
1893 return NULL;
1894}
1895
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301896/*
1897 * is a true native playback active
1898 */
1899bool audio_is_true_native_stream_active(struct audio_device *adev)
1900{
1901 bool active = false;
1902 int i = 0;
1903 struct listnode *node;
1904
1905 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1906 ALOGV("%s:napb: not in true mode or non hdphones device",
1907 __func__);
1908 active = false;
1909 goto exit;
1910 }
1911
1912 list_for_each(node, &adev->usecase_list) {
1913 struct audio_usecase *uc;
1914 uc = node_to_item(node, struct audio_usecase, list);
1915 struct stream_out *curr_out =
1916 (struct stream_out*) uc->stream.out;
1917
1918 if (curr_out && PCM_PLAYBACK == uc->type) {
1919 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1920 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1921 uc->id, curr_out->sample_rate,
1922 curr_out->bit_width,
1923 platform_get_snd_device_name(uc->out_snd_device));
1924
1925 if (is_offload_usecase(uc->id) &&
1926 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1927 active = true;
1928 ALOGD("%s:napb:native stream detected", __func__);
1929 }
1930 }
1931 }
1932exit:
1933 return active;
1934}
1935
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001936uint32_t adev_get_dsp_bit_width_enforce_mode()
1937{
1938 if (adev == NULL) {
1939 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1940 return 0;
1941 }
1942 return adev->dsp_bit_width_enforce_mode;
1943}
1944
1945static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1946{
1947 char value[PROPERTY_VALUE_MAX];
1948 int trial;
1949 uint32_t dsp_bit_width_enforce_mode = 0;
1950
1951 if (!mixer) {
1952 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1953 __func__);
1954 return 0;
1955 }
1956
1957 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1958 value, NULL) > 0) {
1959 trial = atoi(value);
1960 switch (trial) {
1961 case 16:
1962 dsp_bit_width_enforce_mode = 16;
1963 break;
1964 case 24:
1965 dsp_bit_width_enforce_mode = 24;
1966 break;
1967 case 32:
1968 dsp_bit_width_enforce_mode = 32;
1969 break;
1970 default:
1971 dsp_bit_width_enforce_mode = 0;
1972 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1973 break;
1974 }
1975 }
1976
1977 return dsp_bit_width_enforce_mode;
1978}
1979
1980static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1981 uint32_t enforce_mode,
1982 bool enable)
1983{
1984 struct mixer_ctl *ctl = NULL;
1985 const char *mixer_ctl_name = "ASM Bit Width";
1986 uint32_t asm_bit_width_mode = 0;
1987
1988 if (enforce_mode == 0) {
1989 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1990 return;
1991 }
1992
1993 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1994 if (!ctl) {
1995 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1996 __func__, mixer_ctl_name);
1997 return;
1998 }
1999
2000 if (enable)
2001 asm_bit_width_mode = enforce_mode;
2002 else
2003 asm_bit_width_mode = 0;
2004
2005 ALOGV("%s DSP bit width feature status is %d width=%d",
2006 __func__, enable, asm_bit_width_mode);
2007 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2008 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2009 asm_bit_width_mode);
2010
2011 return;
2012}
2013
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302014/*
2015 * if native DSD playback active
2016 */
2017bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2018{
2019 bool active = false;
2020 struct listnode *node = NULL;
2021 struct audio_usecase *uc = NULL;
2022 struct stream_out *curr_out = NULL;
2023
2024 list_for_each(node, &adev->usecase_list) {
2025 uc = node_to_item(node, struct audio_usecase, list);
2026 curr_out = (struct stream_out*) uc->stream.out;
2027
2028 if (curr_out && PCM_PLAYBACK == uc->type &&
2029 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2030 active = true;
2031 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302032 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302033 }
2034 }
2035 return active;
2036}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302037
2038static bool force_device_switch(struct audio_usecase *usecase)
2039{
2040 bool ret = false;
2041 bool is_it_true_mode = false;
2042
Zhou Song30f2c3e2018-02-08 14:02:15 +08002043 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302044 usecase->type == TRANSCODE_LOOPBACK_RX ||
2045 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002046 return false;
2047 }
2048
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002049 if(usecase->stream.out == NULL) {
2050 ALOGE("%s: stream.out is NULL", __func__);
2051 return false;
2052 }
2053
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302054 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002055 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2056 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2057 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302058 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2059 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2060 (!is_it_true_mode && adev->native_playback_enabled)){
2061 ret = true;
2062 ALOGD("napb: time to toggle native mode");
2063 }
2064 }
2065
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302066 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302067 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2068 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002069 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302070 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302071 ALOGD("Force a2dp device switch to update new encoder config");
2072 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002073 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302074
Florian Pfister1a84f312018-07-19 14:38:18 +02002075 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302076 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2077 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002078 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302079 return ret;
2080}
2081
Aalique Grahame22e49102018-12-18 14:23:57 -08002082static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2083{
2084 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2085}
2086
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302087bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2088{
2089 bool ret=false;
2090 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2091 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2092 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2093 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2094 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2095 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2096 ret = true;
2097
2098 return ret;
2099}
2100
2101bool is_a2dp_device(snd_device_t out_snd_device)
2102{
2103 bool ret=false;
2104 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2105 ret = true;
2106
2107 return ret;
2108}
2109
2110bool is_bt_soc_on(struct audio_device *adev)
2111{
2112 struct mixer_ctl *ctl;
2113 char *mixer_ctl_name = "BT SOC status";
2114 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2115 bool bt_soc_status = true;
2116 if (!ctl) {
2117 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2118 __func__, mixer_ctl_name);
2119 /*This is to ensure we dont break targets which dont have the kernel change*/
2120 return true;
2121 }
2122 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2123 ALOGD("BT SOC status: %d",bt_soc_status);
2124 return bt_soc_status;
2125}
2126
2127int out_standby_l(struct audio_stream *stream);
2128
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002129int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002131 snd_device_t out_snd_device = SND_DEVICE_NONE;
2132 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002133 struct audio_usecase *usecase = NULL;
2134 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002135 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002136 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302137 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002138 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002139 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302141 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2142
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002143 usecase = get_usecase_from_list(adev, uc_id);
2144 if (usecase == NULL) {
2145 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2146 return -EINVAL;
2147 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002149 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002150 (usecase->type == VOIP_CALL) ||
2151 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302152 if(usecase->stream.out == NULL) {
2153 ALOGE("%s: stream.out is NULL", __func__);
2154 return -EINVAL;
2155 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002156 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002157 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002158 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002159 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302160 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302161 if (usecase->stream.inout == NULL) {
2162 ALOGE("%s: stream.inout is NULL", __func__);
2163 return -EINVAL;
2164 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302165 stream_out.devices = usecase->stream.inout->out_config.devices;
2166 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2167 stream_out.format = usecase->stream.inout->out_config.format;
2168 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2169 out_snd_device = platform_get_output_snd_device(adev->platform,
2170 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302171 usecase->devices = out_snd_device;
2172 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2173 if (usecase->stream.inout == NULL) {
2174 ALOGE("%s: stream.inout is NULL", __func__);
2175 return -EINVAL;
2176 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302177 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302178 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002179 } else {
2180 /*
2181 * If the voice call is active, use the sound devices of voice call usecase
2182 * so that it would not result any device switch. All the usecases will
2183 * be switched to new device when select_devices() is called for voice call
2184 * usecase. This is to avoid switching devices for voice call when
2185 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002186 * choose voice call device only if the use case device is
2187 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002188 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002189 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002190 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002191 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002192 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2193 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302194 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2195 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002196 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 in_snd_device = vc_usecase->in_snd_device;
2198 out_snd_device = vc_usecase->out_snd_device;
2199 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002200 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002201 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002202 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002203 if ((voip_usecase != NULL) &&
2204 (usecase->type == PCM_PLAYBACK) &&
2205 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002206 out_snd_device_backend_match = platform_check_backends_match(
2207 voip_usecase->out_snd_device,
2208 platform_get_output_snd_device(
2209 adev->platform,
2210 usecase->stream.out));
2211 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002212 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002213 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2214 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002215 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002216 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002217 in_snd_device = voip_usecase->in_snd_device;
2218 out_snd_device = voip_usecase->out_snd_device;
2219 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002220 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002221 hfp_ucid = audio_extn_hfp_get_usecase();
2222 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002223 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002224 in_snd_device = hfp_usecase->in_snd_device;
2225 out_snd_device = hfp_usecase->out_snd_device;
2226 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002227 }
2228 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302229 if (usecase->stream.out == NULL) {
2230 ALOGE("%s: stream.out is NULL", __func__);
2231 return -EINVAL;
2232 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002233 usecase->devices = usecase->stream.out->devices;
2234 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002235 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002236 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002237 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002238 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002239 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002240 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2241
2242 if ((usecase->stream.out != NULL &&
2243 voip_usecase != NULL &&
2244 usecase->stream.out->usecase == voip_usecase->id) &&
2245 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002246 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2247 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002248 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002249 select_devices(adev, adev->active_input->usecase);
2250 }
2251 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002252 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302253 if (usecase->stream.in == NULL) {
2254 ALOGE("%s: stream.in is NULL", __func__);
2255 return -EINVAL;
2256 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 usecase->devices = usecase->stream.in->device;
2258 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002259 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002260 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002261 if (adev->active_input &&
2262 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302263 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002264 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2265 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2266 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2267 out_device = voip_usecase->stream.out->devices;
2268 else if (adev->primary_output && !adev->primary_output->standby)
2269 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002270 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002271 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2272 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002273 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002274 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002275 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002276 }
2277 }
2278
2279 if (out_snd_device == usecase->out_snd_device &&
2280 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302281
2282 if (!force_device_switch(usecase))
2283 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 }
2285
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302286 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002287 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302288 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2289 return 0;
2290 }
2291
Aalique Grahame22e49102018-12-18 14:23:57 -08002292 if (out_snd_device != SND_DEVICE_NONE &&
2293 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2294 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2295 __func__,
2296 use_case_table[uc_id],
2297 adev->last_logged_snd_device[uc_id][0],
2298 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2299 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2300 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2301 -1,
2302 out_snd_device,
2303 platform_get_snd_device_name(out_snd_device),
2304 platform_get_snd_device_acdb_id(out_snd_device));
2305 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2306 }
2307 if (in_snd_device != SND_DEVICE_NONE &&
2308 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2309 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2310 __func__,
2311 use_case_table[uc_id],
2312 adev->last_logged_snd_device[uc_id][1],
2313 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2314 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2315 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2316 -1,
2317 in_snd_device,
2318 platform_get_snd_device_name(in_snd_device),
2319 platform_get_snd_device_acdb_id(in_snd_device));
2320 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2321 }
2322
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 /*
2325 * Limitation: While in call, to do a device switch we need to disable
2326 * and enable both RX and TX devices though one of them is same as current
2327 * device.
2328 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002329 if ((usecase->type == VOICE_CALL) &&
2330 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2331 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002332 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002333 }
2334
2335 if (((usecase->type == VOICE_CALL) ||
2336 (usecase->type == VOIP_CALL)) &&
2337 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2338 /* Disable sidetone only if voice/voip call already exists */
2339 if (voice_is_call_state_active(adev) ||
2340 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002341 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002342
2343 /* Disable aanc only if voice call exists */
2344 if (voice_is_call_state_active(adev))
2345 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002346 }
2347
Aalique Grahame22e49102018-12-18 14:23:57 -08002348 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2349 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002350 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302351 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002352 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2353 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2354 else
2355 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302356 }
2357
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002358 /* Disable current sound devices */
2359 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002360 disable_audio_route(adev, usecase);
2361 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 }
2363
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002364 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002365 disable_audio_route(adev, usecase);
2366 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 }
2368
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002369 /* Applicable only on the targets that has external modem.
2370 * New device information should be sent to modem before enabling
2371 * the devices to reduce in-call device switch time.
2372 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002373 if ((usecase->type == VOICE_CALL) &&
2374 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2375 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002376 status = platform_switch_voice_call_enable_device_config(adev->platform,
2377 out_snd_device,
2378 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002379 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002380
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002381 /* Enable new sound devices */
2382 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002383 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302384 if (platform_check_codec_asrc_support(adev->platform))
2385 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002386 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 }
2388
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002389 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302390 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002391 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002392 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002393
Avinash Vaish71a8b972014-07-24 15:36:33 +05302394 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002395 status = platform_switch_voice_call_device_post(adev->platform,
2396 out_snd_device,
2397 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302398 enable_audio_route_for_voice_usecases(adev, usecase);
2399 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002400
sangwoo170731f2013-06-08 15:36:36 +09002401 usecase->in_snd_device = in_snd_device;
2402 usecase->out_snd_device = out_snd_device;
2403
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302404 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2405 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302406 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002407 if ((24 == usecase->stream.out->bit_width) &&
2408 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2409 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2410 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2411 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2412 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2413 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2414 /*
2415 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2416 * configured device sample rate, if not update the COPP rate to be equal to the
2417 * device sample rate, else open COPP at stream sample rate
2418 */
2419 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2420 usecase->stream.out->sample_rate,
2421 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302422 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2423 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002424 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2425 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2426 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2427 }
2428
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002429 /* Notify device change info to effect clients registered */
2430 audio_extn_gef_notify_device_config(
2431 usecase->stream.out->devices,
2432 usecase->stream.out->channel_mask,
2433 usecase->stream.out->app_type_cfg.sample_rate,
2434 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302435 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002436 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002437
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002438 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002439
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002440 /* If input stream is already running then effect needs to be
2441 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002442 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2443 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002444 check_and_enable_effect(adev);
2445
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002446 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002447 /* Enable aanc only if voice call exists */
2448 if (voice_is_call_state_active(adev))
2449 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2450
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002451 /* Enable sidetone only if other voice/voip call already exists */
2452 if (voice_is_call_state_active(adev) ||
2453 voice_extn_compress_voip_is_started(adev))
2454 voice_set_sidetone(adev, out_snd_device, true);
2455 }
2456
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002457 /* Applicable only on the targets that has external modem.
2458 * Enable device command should be sent to modem only after
2459 * enabling voice call mixer controls
2460 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002461 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002462 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2463 out_snd_device,
2464 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302465
2466 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2467
2468 if (usecase->type == VOIP_CALL) {
2469 if (adev->active_input != NULL &&
2470 !adev->active_input->standby) {
2471 if (is_bt_soc_on(adev) == false){
2472 ALOGD("BT SCO MIC disconnected while in connection");
2473 if (adev->active_input->pcm != NULL)
2474 pcm_stop(adev->active_input->pcm);
2475 }
2476 }
2477 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2478 && usecase->stream.out->started) {
2479 if (is_bt_soc_on(adev) == false) {
2480 ALOGD("BT SCO/A2DP disconnected while in connection");
2481 out_standby_l(&usecase->stream.out->stream.common);
2482 }
2483 }
2484 } else if ((usecase->stream.out != NULL) &&
2485 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302486 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2487 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302488 usecase->stream.out->started) {
2489 if (is_bt_soc_on(adev) == false) {
2490 ALOGD("BT SCO/A2dp disconnected while in connection");
2491 out_standby_l(&usecase->stream.out->stream.common);
2492 }
2493 }
2494 }
2495
Aalique Grahame22e49102018-12-18 14:23:57 -08002496 if (usecase == voip_usecase) {
2497 struct stream_out *voip_out = voip_usecase->stream.out;
2498 audio_extn_utils_send_app_type_gain(adev,
2499 voip_out->app_type_cfg.app_type,
2500 &voip_out->app_type_cfg.gain[0]);
2501 }
2502
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302503 ALOGD("%s: done",__func__);
2504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 return status;
2506}
2507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508static int stop_input_stream(struct stream_in *in)
2509{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302510 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302512
2513 if (in == NULL) {
2514 ALOGE("%s: stream_in ptr is NULL", __func__);
2515 return -EINVAL;
2516 }
2517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 struct audio_device *adev = in->dev;
2519
Eric Laurent994a6932013-07-17 11:51:42 -07002520 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002521 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 uc_info = get_usecase_from_list(adev, in->usecase);
2523 if (uc_info == NULL) {
2524 ALOGE("%s: Could not find the usecase (%d) in the list",
2525 __func__, in->usecase);
2526 return -EINVAL;
2527 }
2528
Derek Chenea197282019-01-07 17:35:01 -08002529 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2530 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002531
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002532 /* Close in-call recording streams */
2533 voice_check_and_stop_incall_rec_usecase(adev, in);
2534
Eric Laurent150dbfe2013-02-27 14:31:02 -08002535 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002536 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537
2538 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002539 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002541 list_remove(&uc_info->list);
2542 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002544 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302545 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002546 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 return ret;
2548}
2549
2550int start_input_stream(struct stream_in *in)
2551{
2552 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002553 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302555
2556 if (in == NULL) {
2557 ALOGE("%s: stream_in ptr is NULL", __func__);
2558 return -EINVAL;
2559 }
2560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002562 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002563 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564
Mingming Yin2664a5b2015-09-03 10:53:11 -07002565 if (get_usecase_from_list(adev, usecase) == NULL)
2566 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302567 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2568 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002569
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302570 if (CARD_STATUS_OFFLINE == in->card_status||
2571 CARD_STATUS_OFFLINE == adev->card_status) {
2572 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302573 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302574 goto error_config;
2575 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302576
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302577 if (audio_is_bluetooth_sco_device(in->device)) {
2578 if (!adev->bt_sco_on) {
2579 ALOGE("%s: SCO profile is not ready, return error", __func__);
2580 ret = -EIO;
2581 goto error_config;
2582 }
2583 }
2584
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002585 /* Check if source matches incall recording usecase criteria */
2586 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2587 if (ret)
2588 goto error_config;
2589 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002590 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2591
2592 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2593 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2594 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002595 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002596 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002597
Eric Laurentb23d5282013-05-14 15:27:20 -07002598 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 if (in->pcm_device_id < 0) {
2600 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2601 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002602 ret = -EINVAL;
2603 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002605
2606 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002608
2609 if (!uc_info) {
2610 ret = -ENOMEM;
2611 goto error_config;
2612 }
2613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 uc_info->id = in->usecase;
2615 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002616 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002617 uc_info->devices = in->device;
2618 uc_info->in_snd_device = SND_DEVICE_NONE;
2619 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002621 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302622 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2623 adev->perf_lock_opts,
2624 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002625 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626
Derek Chenea197282019-01-07 17:35:01 -08002627 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2628 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002629
Haynes Mathew George16081042017-05-31 17:16:49 -07002630 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302631 ret = audio_extn_cin_start_input_stream(in);
2632 if (ret)
2633 goto error_open;
2634 else
2635 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002636 }
2637
Haynes Mathew George16081042017-05-31 17:16:49 -07002638 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002639 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002640 ALOGE("%s: pcm stream not ready", __func__);
2641 goto error_open;
2642 }
2643 ret = pcm_start(in->pcm);
2644 if (ret < 0) {
2645 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2646 goto error_open;
2647 }
2648 } else {
2649 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2650 unsigned int pcm_open_retry_count = 0;
2651
2652 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2653 flags |= PCM_MMAP | PCM_NOIRQ;
2654 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2655 } else if (in->realtime) {
2656 flags |= PCM_MMAP | PCM_NOIRQ;
2657 }
2658
Garmond Leunge2433c32017-09-28 21:51:22 -07002659 if (audio_extn_ffv_get_stream() == in) {
2660 ALOGD("%s: ffv stream, update pcm config", __func__);
2661 audio_extn_ffv_update_pcm_config(&config);
2662 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002663 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2664 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2665
2666 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002667 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002668 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002669 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002670 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302671 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302672 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2673 adev->card_status = CARD_STATUS_OFFLINE;
2674 in->card_status = CARD_STATUS_OFFLINE;
2675 ret = -EIO;
2676 goto error_open;
2677 }
2678
Haynes Mathew George16081042017-05-31 17:16:49 -07002679 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2680 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2681 if (in->pcm != NULL) {
2682 pcm_close(in->pcm);
2683 in->pcm = NULL;
2684 }
2685 if (pcm_open_retry_count-- == 0) {
2686 ret = -EIO;
2687 goto error_open;
2688 }
2689 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2690 continue;
2691 }
2692 break;
2693 }
2694
2695 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002696 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002697 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002698 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002699 if (ret < 0) {
2700 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2701 pcm_close(in->pcm);
2702 in->pcm = NULL;
2703 goto error_open;
2704 }
2705 register_in_stream(in);
2706 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002707 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002708 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002709 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002710 if (ret < 0) {
2711 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002712 pcm_close(in->pcm);
2713 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002714 goto error_open;
2715 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002716 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002717 }
2718
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002719 check_and_enable_effect(adev);
2720
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302721done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302722 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002723 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302724 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002725 return ret;
2726
2727error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302728 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002730error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302731 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302732 /*
2733 * sleep 50ms to allow sufficient time for kernel
2734 * drivers to recover incases like SSR.
2735 */
2736 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302738 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002739 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740}
2741
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002742void lock_input_stream(struct stream_in *in)
2743{
2744 pthread_mutex_lock(&in->pre_lock);
2745 pthread_mutex_lock(&in->lock);
2746 pthread_mutex_unlock(&in->pre_lock);
2747}
2748
2749void lock_output_stream(struct stream_out *out)
2750{
2751 pthread_mutex_lock(&out->pre_lock);
2752 pthread_mutex_lock(&out->lock);
2753 pthread_mutex_unlock(&out->pre_lock);
2754}
2755
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002756/* must be called with out->lock locked */
2757static int send_offload_cmd_l(struct stream_out* out, int command)
2758{
2759 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2760
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002761 if (!cmd) {
2762 ALOGE("failed to allocate mem for command 0x%x", command);
2763 return -ENOMEM;
2764 }
2765
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766 ALOGVV("%s %d", __func__, command);
2767
2768 cmd->cmd = command;
2769 list_add_tail(&out->offload_cmd_list, &cmd->node);
2770 pthread_cond_signal(&out->offload_cond);
2771 return 0;
2772}
2773
2774/* must be called iwth out->lock locked */
2775static void stop_compressed_output_l(struct stream_out *out)
2776{
2777 out->offload_state = OFFLOAD_STATE_IDLE;
2778 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002779 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 if (out->compr != NULL) {
2781 compress_stop(out->compr);
2782 while (out->offload_thread_blocked) {
2783 pthread_cond_wait(&out->cond, &out->lock);
2784 }
2785 }
2786}
2787
Varun Balaraje49253e2017-07-06 19:48:56 +05302788bool is_interactive_usecase(audio_usecase_t uc_id)
2789{
2790 unsigned int i;
2791 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2792 if (uc_id == interactive_usecases[i])
2793 return true;
2794 }
2795 return false;
2796}
2797
2798static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2799{
2800 audio_usecase_t ret_uc = USECASE_INVALID;
2801 unsigned int intract_uc_index;
2802 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2803
2804 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2805 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2806 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2807 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2808 ret_uc = interactive_usecases[intract_uc_index];
2809 break;
2810 }
2811 }
2812
2813 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2814 return ret_uc;
2815}
2816
2817static void free_interactive_usecase(struct audio_device *adev,
2818 audio_usecase_t uc_id)
2819{
2820 unsigned int interact_uc_index;
2821 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2822
2823 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2824 if (interactive_usecases[interact_uc_index] == uc_id) {
2825 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2826 break;
2827 }
2828 }
2829 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2830}
2831
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002832bool is_offload_usecase(audio_usecase_t uc_id)
2833{
2834 unsigned int i;
2835 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2836 if (uc_id == offload_usecases[i])
2837 return true;
2838 }
2839 return false;
2840}
2841
Dhananjay Kumarac341582017-02-23 23:42:25 +05302842static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002843{
vivek mehta446c3962015-09-14 10:57:35 -07002844 audio_usecase_t ret_uc = USECASE_INVALID;
2845 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002846 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002847 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302848 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002849 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2850 else
2851 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002852
vivek mehta446c3962015-09-14 10:57:35 -07002853 pthread_mutex_lock(&adev->lock);
2854 if (get_usecase_from_list(adev, ret_uc) != NULL)
2855 ret_uc = USECASE_INVALID;
2856 pthread_mutex_unlock(&adev->lock);
2857
2858 return ret_uc;
2859 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002860
2861 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002862 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2863 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2864 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2865 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002866 break;
2867 }
2868 }
vivek mehta446c3962015-09-14 10:57:35 -07002869
2870 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2871 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002872}
2873
2874static void free_offload_usecase(struct audio_device *adev,
2875 audio_usecase_t uc_id)
2876{
vivek mehta446c3962015-09-14 10:57:35 -07002877 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002878 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002879
2880 if (!adev->multi_offload_enable)
2881 return;
2882
2883 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2884 if (offload_usecases[offload_uc_index] == uc_id) {
2885 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002886 break;
2887 }
2888 }
2889 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2890}
2891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892static void *offload_thread_loop(void *context)
2893{
2894 struct stream_out *out = (struct stream_out *) context;
2895 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002896 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002899 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2901
2902 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002903 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 for (;;) {
2905 struct offload_cmd *cmd = NULL;
2906 stream_callback_event_t event;
2907 bool send_callback = false;
2908
2909 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2910 __func__, list_empty(&out->offload_cmd_list),
2911 out->offload_state);
2912 if (list_empty(&out->offload_cmd_list)) {
2913 ALOGV("%s SLEEPING", __func__);
2914 pthread_cond_wait(&out->offload_cond, &out->lock);
2915 ALOGV("%s RUNNING", __func__);
2916 continue;
2917 }
2918
2919 item = list_head(&out->offload_cmd_list);
2920 cmd = node_to_item(item, struct offload_cmd, node);
2921 list_remove(item);
2922
2923 ALOGVV("%s STATE %d CMD %d out->compr %p",
2924 __func__, out->offload_state, cmd->cmd, out->compr);
2925
2926 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2927 free(cmd);
2928 break;
2929 }
2930
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002931 // allow OFFLOAD_CMD_ERROR reporting during standby
2932 // this is needed to handle failures during compress_open
2933 // Note however that on a pause timeout, the stream is closed
2934 // and no offload usecase will be active. Therefore this
2935 // special case is needed for compress_open failures alone
2936 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2937 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002939 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 pthread_cond_signal(&out->cond);
2941 continue;
2942 }
2943 out->offload_thread_blocked = true;
2944 pthread_mutex_unlock(&out->lock);
2945 send_callback = false;
2946 switch(cmd->cmd) {
2947 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002948 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002950 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 send_callback = true;
2952 event = STREAM_CBK_EVENT_WRITE_READY;
2953 break;
2954 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002955 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302956 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002957 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302958 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002959 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302960 if (ret < 0)
2961 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302962 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302963 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002964 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002965 else
2966 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002967 if (-ENETRESET != ret && !(-EINTR == ret &&
2968 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302969 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302970 pthread_mutex_lock(&out->lock);
2971 out->send_new_metadata = 1;
2972 out->send_next_track_params = true;
2973 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302974 event = STREAM_CBK_EVENT_DRAIN_READY;
2975 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2976 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302977 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 break;
2979 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002980 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002981 ret = compress_drain(out->compr);
2982 ALOGD("copl(%p):out of compress_drain", out);
2983 // EINTR check avoids drain interruption due to SSR
2984 if (-ENETRESET != ret && !(-EINTR == ret &&
2985 CARD_STATUS_OFFLINE == out->card_status)) {
2986 send_callback = true;
2987 event = STREAM_CBK_EVENT_DRAIN_READY;
2988 } else
2989 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002990 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302991 case OFFLOAD_CMD_ERROR:
2992 ALOGD("copl(%p): sending error callback to AF", out);
2993 send_callback = true;
2994 event = STREAM_CBK_EVENT_ERROR;
2995 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 default:
2997 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2998 break;
2999 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003000 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 out->offload_thread_blocked = false;
3002 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003003 if (send_callback && out->client_callback) {
3004 ALOGVV("%s: sending client_callback event %d", __func__, event);
3005 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003006 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 free(cmd);
3008 }
3009
3010 pthread_cond_signal(&out->cond);
3011 while (!list_empty(&out->offload_cmd_list)) {
3012 item = list_head(&out->offload_cmd_list);
3013 list_remove(item);
3014 free(node_to_item(item, struct offload_cmd, node));
3015 }
3016 pthread_mutex_unlock(&out->lock);
3017
3018 return NULL;
3019}
3020
3021static int create_offload_callback_thread(struct stream_out *out)
3022{
3023 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3024 list_init(&out->offload_cmd_list);
3025 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3026 offload_thread_loop, out);
3027 return 0;
3028}
3029
3030static int destroy_offload_callback_thread(struct stream_out *out)
3031{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003032 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 stop_compressed_output_l(out);
3034 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3035
3036 pthread_mutex_unlock(&out->lock);
3037 pthread_join(out->offload_thread, (void **) NULL);
3038 pthread_cond_destroy(&out->offload_cond);
3039
3040 return 0;
3041}
3042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043static int stop_output_stream(struct stream_out *out)
3044{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303045 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046 struct audio_usecase *uc_info;
3047 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003048 bool has_voip_usecase =
3049 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050
Eric Laurent994a6932013-07-17 11:51:42 -07003051 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003052 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 uc_info = get_usecase_from_list(adev, out->usecase);
3054 if (uc_info == NULL) {
3055 ALOGE("%s: Could not find the usecase (%d) in the list",
3056 __func__, out->usecase);
3057 return -EINVAL;
3058 }
3059
Derek Chenea197282019-01-07 17:35:01 -08003060 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3061 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003062
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003063 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303064 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003065 if (adev->visualizer_stop_output != NULL)
3066 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003067
3068 audio_extn_dts_remove_state_notifier_node(out->usecase);
3069
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003070 if (adev->offload_effects_stop_output != NULL)
3071 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3072 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003073
Arun Mirpurief53ce52018-09-11 18:00:09 -07003074 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3075 voice_set_device_mute_flag(adev, false);
3076
Eric Laurent150dbfe2013-02-27 14:31:02 -08003077 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003078 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003079
3080 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003081 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082
Aalique Grahame22e49102018-12-18 14:23:57 -08003083 audio_extn_extspk_update(adev->extspk);
3084
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003085 if (is_offload_usecase(out->usecase)) {
3086 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3087 adev->dsp_bit_width_enforce_mode,
3088 false);
3089 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003090 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3091 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3092 false);
3093
3094 if (ret != 0)
3095 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3096 /* default service interval was successfully updated,
3097 reopen USB backend with new service interval */
3098 ret = 0;
3099 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003100
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003101 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303102 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003103 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303104 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003105 ALOGV("Disable passthrough , reset mixer to pcm");
3106 /* NO_PASSTHROUGH */
3107 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003108 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003109 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3110 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003111
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303112 /* Must be called after removing the usecase from list */
3113 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303114 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303115
Manish Dewangan21a850a2017-08-14 12:03:55 +05303116 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003117 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3118 if (ret < 0)
3119 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3120 }
3121
Aalique Grahame22e49102018-12-18 14:23:57 -08003122 if (has_voip_usecase ||
3123 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3124 struct listnode *node;
3125 struct audio_usecase *usecase;
3126 list_for_each(node, &adev->usecase_list) {
3127 usecase = node_to_item(node, struct audio_usecase, list);
3128 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3129 continue;
3130
3131 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3132 __func__, usecase->id, use_case_table[usecase->id],
3133 out->usecase, use_case_table[out->usecase]);
3134 select_devices(adev, usecase->id);
3135 }
3136 }
3137
Garmond Leung5fd0b552018-04-17 11:56:12 -07003138 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003139 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 return ret;
3141}
3142
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003143struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3144 unsigned int flags, unsigned int pcm_open_retry_count,
3145 struct pcm_config *config)
3146{
3147 struct pcm* pcm = NULL;
3148
3149 while (1) {
3150 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3151 if (pcm == NULL || !pcm_is_ready(pcm)) {
3152 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3153 if (pcm != NULL) {
3154 pcm_close(pcm);
3155 pcm = NULL;
3156 }
3157 if (pcm_open_retry_count-- == 0)
3158 return NULL;
3159
3160 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3161 continue;
3162 }
3163 break;
3164 }
3165
3166 if (pcm_is_ready(pcm)) {
3167 int ret = pcm_prepare(pcm);
3168 if (ret < 0) {
3169 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3170 pcm_close(pcm);
3171 pcm = NULL;
3172 }
3173 }
3174
3175 return pcm;
3176}
3177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178int start_output_stream(struct stream_out *out)
3179{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 struct audio_usecase *uc_info;
3182 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003183 char mixer_ctl_name[128];
3184 struct mixer_ctl *ctl = NULL;
3185 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303186 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003187 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188
Haynes Mathew George380745d2017-10-04 15:27:45 -07003189 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003190 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3191 ret = -EINVAL;
3192 goto error_config;
3193 }
3194
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003195 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303196 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003197 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303198
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303199 if (CARD_STATUS_OFFLINE == out->card_status ||
3200 CARD_STATUS_OFFLINE == adev->card_status) {
3201 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303202 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303203 goto error_config;
3204 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303205
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303206 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003207 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003208 if (out->devices &
3209 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303210 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303211 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303212 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3213 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3214 ret = -EAGAIN;
3215 goto error_config;
3216 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303217 }
3218 }
3219 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303220 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3221 if (!adev->bt_sco_on) {
3222 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3223 //combo usecase just by pass a2dp
3224 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3225 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3226 } else {
3227 ALOGE("%s: SCO profile is not ready, return error", __func__);
3228 ret = -EAGAIN;
3229 goto error_config;
3230 }
3231 }
3232 }
3233
Eric Laurentb23d5282013-05-14 15:27:20 -07003234 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 if (out->pcm_device_id < 0) {
3236 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3237 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003238 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003239 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 }
3241
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003242 if (is_haptic_usecase) {
3243 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3244 if (adev->haptic_pcm_device_id < 0) {
3245 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3246 __func__, adev->haptic_pcm_device_id, out->usecase);
3247 ret = -EINVAL;
3248 goto error_config;
3249 }
3250 }
3251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003253
3254 if (!uc_info) {
3255 ret = -ENOMEM;
3256 goto error_config;
3257 }
3258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 uc_info->id = out->usecase;
3260 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003261 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003262 uc_info->devices = out->devices;
3263 uc_info->in_snd_device = SND_DEVICE_NONE;
3264 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003265
3266 /* This must be called before adding this usecase to the list */
3267 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3268 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3269 /* USB backend is not reopened immediately.
3270 This is eventually done as part of select_devices */
3271 }
3272
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003273 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303275 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3276 adev->perf_lock_opts,
3277 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303278
3279 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303280 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303281 if (audio_extn_passthru_is_enabled() &&
3282 audio_extn_passthru_is_passthrough_stream(out)) {
3283 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303284 }
3285 }
3286
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303287 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003288 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303289 if (!a2dp_combo) {
3290 check_a2dp_restore_l(adev, out, false);
3291 } else {
3292 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003293 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3294 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3295 else
3296 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303297 select_devices(adev, out->usecase);
3298 out->devices = dev;
3299 }
3300 } else {
3301 select_devices(adev, out->usecase);
3302 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003303
Arun Mirpurief53ce52018-09-11 18:00:09 -07003304 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3305 voice_set_device_mute_flag(adev, true);
3306
Derek Chenea197282019-01-07 17:35:01 -08003307 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3308 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003310 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3311 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003312
3313 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003314 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003315 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3316 ALOGE("%s: pcm stream not ready", __func__);
3317 goto error_open;
3318 }
3319 ret = pcm_start(out->pcm);
3320 if (ret < 0) {
3321 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3322 goto error_open;
3323 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003324 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003325 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003326 unsigned int flags = PCM_OUT;
3327 unsigned int pcm_open_retry_count = 0;
3328 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3329 flags |= PCM_MMAP | PCM_NOIRQ;
3330 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003331 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003332 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003333 } else
3334 flags |= PCM_MONOTONIC;
3335
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003336 if ((adev->vr_audio_mode_enabled) &&
3337 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3338 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3339 "PCM_Dev %d Topology", out->pcm_device_id);
3340 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3341 if (!ctl) {
3342 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3343 __func__, mixer_ctl_name);
3344 } else {
3345 //if success use ULLPP
3346 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3347 __func__, mixer_ctl_name, out->pcm_device_id);
3348 //There is a still a possibility that some sessions
3349 // that request for FAST|RAW when 3D audio is active
3350 //can go through ULLPP. Ideally we expects apps to
3351 //listen to audio focus and stop concurrent playback
3352 //Also, we will look for mode flag (voice_in_communication)
3353 //before enabling the realtime flag.
3354 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3355 }
3356 }
3357
Surendar Karka91fa3682018-07-02 18:12:12 +05303358 if (out->realtime)
3359 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3360 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3361
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003362 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3363 flags, pcm_open_retry_count,
3364 &(out->config));
3365 if (out->pcm == NULL) {
3366 ret = -EIO;
3367 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003369
3370 if (is_haptic_usecase) {
3371 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3372 adev->haptic_pcm_device_id,
3373 flags, pcm_open_retry_count,
3374 &(adev->haptics_config));
3375 // failure to open haptics pcm shouldnt stop audio,
3376 // so do not close audio pcm in case of error
3377 }
3378
Surendar Karka91fa3682018-07-02 18:12:12 +05303379 if (!out->realtime)
3380 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303381 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003382
Zhou Song2b8f28f2017-09-11 10:51:38 +08003383 // apply volume for voip playback after path is set up
3384 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3385 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303386 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3387 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303388 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3389 out->apply_volume = false;
3390 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003391 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003392 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303393 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003394 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3395 adev->dsp_bit_width_enforce_mode,
3396 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003398 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003399 out->compr = compress_open(adev->snd_card,
3400 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003401 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003402 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303403 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303404 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3405 adev->card_status = CARD_STATUS_OFFLINE;
3406 out->card_status = CARD_STATUS_OFFLINE;
3407 ret = -EIO;
3408 goto error_open;
3409 }
3410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003411 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003412 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 compress_close(out->compr);
3414 out->compr = NULL;
3415 ret = -EIO;
3416 goto error_open;
3417 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303418 /* compress_open sends params of the track, so reset the flag here */
3419 out->is_compr_metadata_avail = false;
3420
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003421 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003422 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003423
Fred Oh3f43e742015-03-04 18:42:34 -08003424 /* Since small bufs uses blocking writes, a write will be blocked
3425 for the default max poll time (20s) in the event of an SSR.
3426 Reduce the poll time to observe and deal with SSR faster.
3427 */
Ashish Jain5106d362016-05-11 19:23:33 +05303428 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003429 compress_set_max_poll_wait(out->compr, 1000);
3430 }
3431
Manish Dewangan69426c82017-01-30 17:35:36 +05303432 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303433 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303434
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003435 audio_extn_dts_create_state_notifier_node(out->usecase);
3436 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3437 popcount(out->channel_mask),
3438 out->playback_started);
3439
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003440#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303441 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003442 audio_extn_dolby_send_ddp_endp_params(adev);
3443#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303444 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3445 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003446 if (adev->visualizer_start_output != NULL)
3447 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3448 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303449 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003450 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003453
3454 if (ret == 0) {
3455 register_out_stream(out);
3456 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003457 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3458 ALOGE("%s: pcm stream not ready", __func__);
3459 goto error_open;
3460 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003461 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003462 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003463 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003464 if (ret < 0)
3465 goto error_open;
3466 }
3467 }
3468
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303469 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003470 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003471
Manish Dewangan21a850a2017-08-14 12:03:55 +05303472 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003473 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003474 if (ret < 0)
3475 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3476 }
3477
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003478 // consider a scenario where on pause lower layers are tear down.
3479 // so on resume, swap mixer control need to be sent only when
3480 // backend is active, hence rather than sending from enable device
3481 // sending it from start of streamtream
3482
3483 platform_set_swap_channels(adev, true);
3484
Haynes Mathew George380745d2017-10-04 15:27:45 -07003485 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303486 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003487 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003489 if (adev->haptic_pcm) {
3490 pcm_close(adev->haptic_pcm);
3491 adev->haptic_pcm = NULL;
3492 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303493 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003495error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303496 /*
3497 * sleep 50ms to allow sufficient time for kernel
3498 * drivers to recover incases like SSR.
3499 */
3500 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003501 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303502 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003503 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504}
3505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506static int check_input_parameters(uint32_t sample_rate,
3507 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003508 int channel_count,
3509 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003511 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303513 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3514 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3515 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003516 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003517 !audio_extn_compr_cap_format_supported(format) &&
3518 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003519 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003520
Aalique Grahame22e49102018-12-18 14:23:57 -08003521 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3522 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3523 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3524 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3525 return -EINVAL;
3526 }
3527
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003528 switch (channel_count) {
3529 case 1:
3530 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303531 case 3:
3532 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003533 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003534 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003535 break;
3536 default:
3537 ret = -EINVAL;
3538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
3540 switch (sample_rate) {
3541 case 8000:
3542 case 11025:
3543 case 12000:
3544 case 16000:
3545 case 22050:
3546 case 24000:
3547 case 32000:
3548 case 44100:
3549 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003550 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303551 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003552 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303553 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 break;
3555 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003556 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 }
3558
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003559 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560}
3561
Naresh Tanniru04f71882018-06-26 17:46:22 +05303562
3563/** Add a value in a list if not already present.
3564 * @return true if value was successfully inserted or already present,
3565 * false if the list is full and does not contain the value.
3566 */
3567static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3568 for (size_t i = 0; i < list_length; i++) {
3569 if (list[i] == value) return true; // value is already present
3570 if (list[i] == 0) { // no values in this slot
3571 list[i] = value;
3572 return true; // value inserted
3573 }
3574 }
3575 return false; // could not insert value
3576}
3577
3578/** Add channel_mask in supported_channel_masks if not already present.
3579 * @return true if channel_mask was successfully inserted or already present,
3580 * false if supported_channel_masks is full and does not contain channel_mask.
3581 */
3582static void register_channel_mask(audio_channel_mask_t channel_mask,
3583 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3584 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3585 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3586}
3587
3588/** Add format in supported_formats if not already present.
3589 * @return true if format was successfully inserted or already present,
3590 * false if supported_formats is full and does not contain format.
3591 */
3592static void register_format(audio_format_t format,
3593 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3594 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3595 "%s: stream can not declare supporting its format %x", __func__, format);
3596}
3597/** Add sample_rate in supported_sample_rates if not already present.
3598 * @return true if sample_rate was successfully inserted or already present,
3599 * false if supported_sample_rates is full and does not contain sample_rate.
3600 */
3601static void register_sample_rate(uint32_t sample_rate,
3602 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3603 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3604 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3605}
3606
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003607static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3608{
3609 uint32_t high = num1, low = num2, temp = 0;
3610
3611 if (!num1 || !num2)
3612 return 0;
3613
3614 if (num1 < num2) {
3615 high = num2;
3616 low = num1;
3617 }
3618
3619 while (low != 0) {
3620 temp = low;
3621 low = high % low;
3622 high = temp;
3623 }
3624 return (num1 * num2)/high;
3625}
3626
3627static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3628{
3629 uint32_t remainder = 0;
3630
3631 if (!multiplier)
3632 return num;
3633
3634 remainder = num % multiplier;
3635 if (remainder)
3636 num += (multiplier - remainder);
3637
3638 return num;
3639}
3640
Aalique Grahame22e49102018-12-18 14:23:57 -08003641static size_t get_stream_buffer_size(size_t duration_ms,
3642 uint32_t sample_rate,
3643 audio_format_t format,
3644 int channel_count,
3645 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
3647 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003648 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649
Aalique Grahame22e49102018-12-18 14:23:57 -08003650 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003651 if (is_low_latency)
3652 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303653
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003654 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003655 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Ralf Herzbd08d632018-09-28 15:50:49 +02003657 /* make sure the size is multiple of 32 bytes and additionally multiple of
3658 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003659 * At 48 kHz mono 16-bit PCM:
3660 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3661 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003662 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003663 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003664 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003665
3666 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667}
3668
Aalique Grahame22e49102018-12-18 14:23:57 -08003669static size_t get_input_buffer_size(uint32_t sample_rate,
3670 audio_format_t format,
3671 int channel_count,
3672 bool is_low_latency)
3673{
3674 /* Don't know if USB HIFI in this context so use true to be conservative */
3675 if (check_input_parameters(sample_rate, format, channel_count,
3676 true /*is_usb_hifi */) != 0)
3677 return 0;
3678
3679 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3680 sample_rate,
3681 format,
3682 channel_count,
3683 is_low_latency);
3684}
3685
Ashish Jain058165c2016-09-28 23:18:48 +05303686static size_t get_output_period_size(uint32_t sample_rate,
3687 audio_format_t format,
3688 int channel_count,
3689 int duration /*in millisecs*/)
3690{
3691 size_t size = 0;
3692 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3693
3694 if ((duration == 0) || (sample_rate == 0) ||
3695 (bytes_per_sample == 0) || (channel_count == 0)) {
3696 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3697 bytes_per_sample, channel_count);
3698 return -EINVAL;
3699 }
3700
3701 size = (sample_rate *
3702 duration *
3703 bytes_per_sample *
3704 channel_count) / 1000;
3705 /*
3706 * To have same PCM samples for all channels, the buffer size requires to
3707 * be multiple of (number of channels * bytes per sample)
3708 * For writes to succeed, the buffer must be written at address which is multiple of 32
3709 */
3710 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3711
3712 return (size/(channel_count * bytes_per_sample));
3713}
3714
Zhou Song48453a02018-01-10 17:50:59 +08003715static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303716{
3717 uint64_t actual_frames_rendered = 0;
3718 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3719
3720 /* This adjustment accounts for buffering after app processor.
3721 * It is based on estimated DSP latency per use case, rather than exact.
3722 */
3723 int64_t platform_latency = platform_render_latency(out->usecase) *
3724 out->sample_rate / 1000000LL;
3725
Zhou Song48453a02018-01-10 17:50:59 +08003726 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303727 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3728 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3729 * hence only estimate.
3730 */
3731 int64_t signed_frames = out->written - kernel_buffer_size;
3732
3733 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3734
Zhou Song48453a02018-01-10 17:50:59 +08003735 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303736 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003737 if (timestamp != NULL )
3738 *timestamp = out->writeAt;
3739 } else if (timestamp != NULL) {
3740 clock_gettime(CLOCK_MONOTONIC, timestamp);
3741 }
3742 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303743
3744 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3745 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3746 (long long int)out->written, (int)kernel_buffer_size,
3747 audio_bytes_per_sample(out->compr_config.codec->format),
3748 popcount(out->channel_mask));
3749
3750 return actual_frames_rendered;
3751}
3752
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3754{
3755 struct stream_out *out = (struct stream_out *)stream;
3756
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758}
3759
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003760static int out_set_sample_rate(struct audio_stream *stream __unused,
3761 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762{
3763 return -ENOSYS;
3764}
3765
3766static size_t out_get_buffer_size(const struct audio_stream *stream)
3767{
3768 struct stream_out *out = (struct stream_out *)stream;
3769
Varun Balaraje49253e2017-07-06 19:48:56 +05303770 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303771 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303772 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303773 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3774 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3775 else
3776 return out->compr_config.fragment_size;
3777 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003778 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003779 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3780 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 +05303781 else if (is_offload_usecase(out->usecase) &&
3782 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303783 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003784
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003785 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003786 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787}
3788
3789static uint32_t out_get_channels(const struct audio_stream *stream)
3790{
3791 struct stream_out *out = (struct stream_out *)stream;
3792
3793 return out->channel_mask;
3794}
3795
3796static audio_format_t out_get_format(const struct audio_stream *stream)
3797{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003798 struct stream_out *out = (struct stream_out *)stream;
3799
3800 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801}
3802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003803static int out_set_format(struct audio_stream *stream __unused,
3804 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805{
3806 return -ENOSYS;
3807}
3808
3809static int out_standby(struct audio_stream *stream)
3810{
3811 struct stream_out *out = (struct stream_out *)stream;
3812 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003813 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303815 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3816 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003818 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003820 if (adev->adm_deregister_stream)
3821 adev->adm_deregister_stream(adev->adm_data, out->handle);
3822
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003823 if (is_offload_usecase(out->usecase))
3824 stop_compressed_output_l(out);
3825
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003826 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003828 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3829 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303830 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003831 pthread_mutex_unlock(&adev->lock);
3832 pthread_mutex_unlock(&out->lock);
3833 ALOGD("VOIP output entered standby");
3834 return 0;
3835 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836 if (out->pcm) {
3837 pcm_close(out->pcm);
3838 out->pcm = NULL;
3839 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003840 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3841 do_stop = out->playback_started;
3842 out->playback_started = false;
3843 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003844 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003845 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303846 out->send_next_track_params = false;
3847 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003848 out->gapless_mdata.encoder_delay = 0;
3849 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 if (out->compr != NULL) {
3851 compress_close(out->compr);
3852 out->compr = NULL;
3853 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003854 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003855 if (do_stop) {
3856 stop_output_stream(out);
3857 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003858 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 }
3860 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303861 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 return 0;
3863}
3864
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303865static int out_on_error(struct audio_stream *stream)
3866{
3867 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003868 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303869
3870 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003871 // always send CMD_ERROR for offload streams, this
3872 // is needed e.g. when SSR happens within compress_open
3873 // since the stream is active, offload_callback_thread is also active.
3874 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3875 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003876 }
3877 pthread_mutex_unlock(&out->lock);
3878
3879 status = out_standby(&out->stream.common);
3880
3881 lock_output_stream(out);
3882 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003883 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303884 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303885
3886 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3887 ALOGD("Setting previous card status if offline");
3888 out->prev_card_status_offline = true;
3889 }
3890
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303891 pthread_mutex_unlock(&out->lock);
3892
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003893 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303894}
3895
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303896/*
3897 *standby implementation without locks, assumes that the callee already
3898 *has taken adev and out lock.
3899 */
3900int out_standby_l(struct audio_stream *stream)
3901{
3902 struct stream_out *out = (struct stream_out *)stream;
3903 struct audio_device *adev = out->dev;
3904
3905 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3906 stream, out->usecase, use_case_table[out->usecase]);
3907
3908 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003909 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303910 if (adev->adm_deregister_stream)
3911 adev->adm_deregister_stream(adev->adm_data, out->handle);
3912
3913 if (is_offload_usecase(out->usecase))
3914 stop_compressed_output_l(out);
3915
3916 out->standby = true;
3917 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3918 voice_extn_compress_voip_close_output_stream(stream);
3919 out->started = 0;
3920 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003921 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303922 return 0;
3923 } else if (!is_offload_usecase(out->usecase)) {
3924 if (out->pcm) {
3925 pcm_close(out->pcm);
3926 out->pcm = NULL;
3927 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003928 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3929 if (adev->haptic_pcm) {
3930 pcm_close(adev->haptic_pcm);
3931 adev->haptic_pcm = NULL;
3932 }
3933
3934 if (adev->haptic_buffer != NULL) {
3935 free(adev->haptic_buffer);
3936 adev->haptic_buffer = NULL;
3937 adev->haptic_buffer_size = 0;
3938 }
3939 adev->haptic_pcm_device_id = 0;
3940 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303941 } else {
3942 ALOGD("copl(%p):standby", out);
3943 out->send_next_track_params = false;
3944 out->is_compr_metadata_avail = false;
3945 out->gapless_mdata.encoder_delay = 0;
3946 out->gapless_mdata.encoder_padding = 0;
3947 if (out->compr != NULL) {
3948 compress_close(out->compr);
3949 out->compr = NULL;
3950 }
3951 }
3952 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003953 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303954 }
3955 ALOGD("%s: exit", __func__);
3956 return 0;
3957}
3958
Aalique Grahame22e49102018-12-18 14:23:57 -08003959static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960{
Aalique Grahame22e49102018-12-18 14:23:57 -08003961 struct stream_out *out = (struct stream_out *)stream;
3962
3963 // We try to get the lock for consistency,
3964 // but it isn't necessary for these variables.
3965 // If we're not in standby, we may be blocked on a write.
3966 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
3967 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
3968 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
3969
3970 if (locked) {
3971 pthread_mutex_unlock(&out->lock);
3972 }
3973
3974 // dump error info
3975 (void)error_log_dump(
3976 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
3977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978 return 0;
3979}
3980
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003981static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3982{
3983 int ret = 0;
3984 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003985
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003986 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003987 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003988 return -EINVAL;
3989 }
3990
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303991 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003992
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003993 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3994 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303995 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003996 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003997 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3998 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303999 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004000 }
4001
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004002 ALOGV("%s new encoder delay %u and padding %u", __func__,
4003 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4004
4005 return 0;
4006}
4007
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004008static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4009{
4010 return out == adev->primary_output || out == adev->voice_tx_output;
4011}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004012
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304013// note: this call is safe only if the stream_cb is
4014// removed first in close_output_stream (as is done now).
4015static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4016{
4017 if (!stream || !parms)
4018 return;
4019
4020 struct stream_out *out = (struct stream_out *)stream;
4021 struct audio_device *adev = out->dev;
4022
4023 card_status_t status;
4024 int card;
4025 if (parse_snd_card_status(parms, &card, &status) < 0)
4026 return;
4027
4028 pthread_mutex_lock(&adev->lock);
4029 bool valid_cb = (card == adev->snd_card);
4030 pthread_mutex_unlock(&adev->lock);
4031
4032 if (!valid_cb)
4033 return;
4034
4035 lock_output_stream(out);
4036 if (out->card_status != status)
4037 out->card_status = status;
4038 pthread_mutex_unlock(&out->lock);
4039
4040 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4041 use_case_table[out->usecase],
4042 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4043
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304044 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304045 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304046 if (voice_is_call_state_active(adev) &&
4047 out == adev->primary_output) {
4048 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4049 pthread_mutex_lock(&adev->lock);
4050 voice_stop_call(adev);
4051 adev->mode = AUDIO_MODE_NORMAL;
4052 pthread_mutex_unlock(&adev->lock);
4053 }
4054 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304055 return;
4056}
4057
Kevin Rocardfce19002017-08-07 19:21:36 -07004058static int get_alive_usb_card(struct str_parms* parms) {
4059 int card;
4060 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4061 !audio_extn_usb_alive(card)) {
4062 return card;
4063 }
4064 return -ENODEV;
4065}
4066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4068{
4069 struct stream_out *out = (struct stream_out *)stream;
4070 struct audio_device *adev = out->dev;
4071 struct str_parms *parms;
4072 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004073 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304074 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004075 bool reconfig = false;
4076 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077
sangwoobc677242013-08-08 16:53:43 +09004078 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004079 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304081 if (!parms)
4082 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004083 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4084 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004086 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004087 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004089 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004090 * When HDMI cable is unplugged the music playback is paused and
4091 * the policy manager sends routing=0. But the audioflinger continues
4092 * to write data until standby time (3sec). As the HDMI core is
4093 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004094 * Avoid this by routing audio to speaker until standby.
4095 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004096 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4097 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304098 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004099 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4100 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004101 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304102 /*
4103 * When A2DP is disconnected the
4104 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004105 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304106 * (3sec). As BT is turned off, the write gets blocked.
4107 * Avoid this by routing audio to speaker until standby.
4108 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004109 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004110 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004111 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304112 val = AUDIO_DEVICE_OUT_SPEAKER;
4113 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304114 /*
4115 * When USB headset is disconnected the music platback paused
4116 * and the policy manager send routing=0. But if the USB is connected
4117 * back before the standby time, AFE is not closed and opened
4118 * when USB is connected back. So routing to speker will guarantee
4119 * AFE reconfiguration and AFE will be opend once USB is connected again
4120 */
4121 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4122 (val == AUDIO_DEVICE_NONE) &&
4123 !audio_extn_usb_connected(parms)) {
4124 val = AUDIO_DEVICE_OUT_SPEAKER;
4125 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304126 /* To avoid a2dp to sco overlapping / BT device improper state
4127 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304128 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304129 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004130 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004131 if (val &
4132 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304133 //combo usecase just by pass a2dp
4134 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304135 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304136 } else {
4137 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4138 /* update device to a2dp and don't route as BT returned error
4139 * However it is still possible a2dp routing called because
4140 * of current active device disconnection (like wired headset)
4141 */
4142 out->devices = val;
4143 pthread_mutex_unlock(&out->lock);
4144 pthread_mutex_unlock(&adev->lock);
4145 goto error;
4146 }
4147 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304148 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004149
4150 audio_devices_t new_dev = val;
4151
4152 // Workaround: If routing to an non existing usb device, fail gracefully
4153 // The routing request will otherwise block during 10 second
4154 int card;
4155 if (audio_is_usb_out_device(new_dev) &&
4156 (card = get_alive_usb_card(parms)) >= 0) {
4157
4158 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4159 pthread_mutex_unlock(&adev->lock);
4160 pthread_mutex_unlock(&out->lock);
4161 ret = -ENOSYS;
4162 goto routing_fail;
4163 }
4164
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004165 /*
4166 * select_devices() call below switches all the usecases on the same
4167 * backend to the new device. Refer to check_usecases_codec_backend() in
4168 * the select_devices(). But how do we undo this?
4169 *
4170 * For example, music playback is active on headset (deep-buffer usecase)
4171 * and if we go to ringtones and select a ringtone, low-latency usecase
4172 * will be started on headset+speaker. As we can't enable headset+speaker
4173 * and headset devices at the same time, select_devices() switches the music
4174 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4175 * So when the ringtone playback is completed, how do we undo the same?
4176 *
4177 * We are relying on the out_set_parameters() call on deep-buffer output,
4178 * once the ringtone playback is ended.
4179 * NOTE: We should not check if the current devices are same as new devices.
4180 * Because select_devices() must be called to switch back the music
4181 * playback to headset.
4182 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004183 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004184 audio_devices_t new_dev = val;
4185 bool same_dev = out->devices == new_dev;
4186 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004187
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004188 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004189 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004190 if (adev->mode == AUDIO_MODE_IN_CALL) {
4191 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004192 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4193 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4194 audio_extn_usb_set_service_interval(true /*playback*/,
4195 service_interval,
4196 &reconfig);
4197 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4198 }
4199 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004200 }
4201 } else {
4202 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004203 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004204 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004205 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004206
4207 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004208 if (!same_dev) {
4209 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304210 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4211 adev->perf_lock_opts,
4212 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004213 if (adev->adm_on_routing_change)
4214 adev->adm_on_routing_change(adev->adm_data,
4215 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004216 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304217 if (!bypass_a2dp) {
4218 select_devices(adev, out->usecase);
4219 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004220 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4221 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4222 else
4223 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304224 select_devices(adev, out->usecase);
4225 out->devices = new_dev;
4226 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004227
4228 if (!same_dev) {
4229 // on device switch force swap, lower functions will make sure
4230 // to check if swap is allowed or not.
4231 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304232 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004233 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304234 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4235 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004236 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304237 pthread_mutex_lock(&out->compr_mute_lock);
4238 out->a2dp_compress_mute = false;
4239 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4240 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004241 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4242 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304243 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004244 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004245 }
4246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004248 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004249
4250 /*handles device and call state changes*/
4251 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004253 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004254
4255 if (out == adev->primary_output) {
4256 pthread_mutex_lock(&adev->lock);
4257 audio_extn_set_parameters(adev, parms);
4258 pthread_mutex_unlock(&adev->lock);
4259 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004260 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004261 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004262 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004263
4264 audio_extn_dts_create_state_notifier_node(out->usecase);
4265 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4266 popcount(out->channel_mask),
4267 out->playback_started);
4268
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004269 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004270 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004271
Surendar Karkaf51b5842018-04-26 11:28:38 +05304272 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4273 sizeof(value));
4274 if (err >= 0) {
4275 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4276 audio_extn_send_dual_mono_mixing_coefficients(out);
4277 }
4278
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304279 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4280 if (err >= 0) {
4281 strlcpy(out->profile, value, sizeof(out->profile));
4282 ALOGV("updating stream profile with value '%s'", out->profile);
4283 lock_output_stream(out);
4284 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4285 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004286 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304287 out->sample_rate, out->bit_width,
4288 out->channel_mask, out->profile,
4289 &out->app_type_cfg);
4290 pthread_mutex_unlock(&out->lock);
4291 }
4292
Alexy Joseph98988832017-01-13 14:56:59 -08004293 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004294 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4295 // and vendor.audio.hal.output.suspend.supported is set to true
4296 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004297 //check suspend parameter only for low latency and if the property
4298 //is enabled
4299 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4300 ALOGI("%s: got suspend_playback %s", __func__, value);
4301 lock_output_stream(out);
4302 if (!strncmp(value, "false", 5)) {
4303 //suspend_playback=false is supposed to set QOS value back to 75%
4304 //the mixer control sent with value Enable will achieve that
4305 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4306 } else if (!strncmp (value, "true", 4)) {
4307 //suspend_playback=true is supposed to remove QOS value
4308 //resetting the mixer control will set the default value
4309 //for the mixer control which is Disable and this removes the QOS vote
4310 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4311 } else {
4312 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4313 " got %s", __func__, value);
4314 ret = -1;
4315 }
4316
4317 if (ret != 0) {
4318 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4319 __func__, out->pm_qos_mixer_path, ret);
4320 }
4321
4322 pthread_mutex_unlock(&out->lock);
4323 }
4324 }
4325 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304327error:
Eric Laurent994a6932013-07-17 11:51:42 -07004328 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 return ret;
4330}
4331
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004332static bool stream_get_parameter_channels(struct str_parms *query,
4333 struct str_parms *reply,
4334 audio_channel_mask_t *supported_channel_masks) {
4335 int ret = -1;
4336 char value[512];
4337 bool first = true;
4338 size_t i, j;
4339
4340 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4341 ret = 0;
4342 value[0] = '\0';
4343 i = 0;
4344 while (supported_channel_masks[i] != 0) {
4345 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4346 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4347 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304348 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004349
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304350 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004351 first = false;
4352 break;
4353 }
4354 }
4355 i++;
4356 }
4357 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4358 }
4359 return ret == 0;
4360}
4361
4362static bool stream_get_parameter_formats(struct str_parms *query,
4363 struct str_parms *reply,
4364 audio_format_t *supported_formats) {
4365 int ret = -1;
4366 char value[256];
4367 size_t i, j;
4368 bool first = true;
4369
4370 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4371 ret = 0;
4372 value[0] = '\0';
4373 i = 0;
4374 while (supported_formats[i] != 0) {
4375 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4376 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4377 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304378 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004379 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304380 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004381 first = false;
4382 break;
4383 }
4384 }
4385 i++;
4386 }
4387 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4388 }
4389 return ret == 0;
4390}
4391
4392static bool stream_get_parameter_rates(struct str_parms *query,
4393 struct str_parms *reply,
4394 uint32_t *supported_sample_rates) {
4395
4396 int i;
4397 char value[256];
4398 int ret = -1;
4399 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4400 ret = 0;
4401 value[0] = '\0';
4402 i=0;
4403 int cursor = 0;
4404 while (supported_sample_rates[i]) {
4405 int avail = sizeof(value) - cursor;
4406 ret = snprintf(value + cursor, avail, "%s%d",
4407 cursor > 0 ? "|" : "",
4408 supported_sample_rates[i]);
4409 if (ret < 0 || ret >= avail) {
4410 // if cursor is at the last element of the array
4411 // overwrite with \0 is duplicate work as
4412 // snprintf already put a \0 in place.
4413 // else
4414 // we had space to write the '|' at value[cursor]
4415 // (which will be overwritten) or no space to fill
4416 // the first element (=> cursor == 0)
4417 value[cursor] = '\0';
4418 break;
4419 }
4420 cursor += ret;
4421 ++i;
4422 }
4423 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4424 value);
4425 }
4426 return ret >= 0;
4427}
4428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4430{
4431 struct stream_out *out = (struct stream_out *)stream;
4432 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004433 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434 char value[256];
4435 struct str_parms *reply = str_parms_create();
4436 size_t i, j;
4437 int ret;
4438 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004439
4440 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004441 if (reply) {
4442 str_parms_destroy(reply);
4443 }
4444 if (query) {
4445 str_parms_destroy(query);
4446 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004447 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4448 return NULL;
4449 }
4450
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004451 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4453 if (ret >= 0) {
4454 value[0] = '\0';
4455 i = 0;
4456 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004457 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4458 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004460 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004462 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463 first = false;
4464 break;
4465 }
4466 }
4467 i++;
4468 }
4469 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4470 str = str_parms_to_str(reply);
4471 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004472 voice_extn_out_get_parameters(out, query, reply);
4473 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004475
Alexy Joseph62142aa2015-11-16 15:10:34 -08004476
4477 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4478 if (ret >= 0) {
4479 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304480 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4481 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004482 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304483 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004484 } else {
4485 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304486 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004487 }
4488 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004489 if (str)
4490 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004491 str = str_parms_to_str(reply);
4492 }
4493
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004494 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4495 if (ret >= 0) {
4496 value[0] = '\0';
4497 i = 0;
4498 first = true;
4499 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004500 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4501 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004502 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004503 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004504 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004505 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004506 first = false;
4507 break;
4508 }
4509 }
4510 i++;
4511 }
4512 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004513 if (str)
4514 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004515 str = str_parms_to_str(reply);
4516 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004517
4518 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4519 if (ret >= 0) {
4520 value[0] = '\0';
4521 i = 0;
4522 first = true;
4523 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004524 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4525 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004526 if (!first) {
4527 strlcat(value, "|", sizeof(value));
4528 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004529 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004530 first = false;
4531 break;
4532 }
4533 }
4534 i++;
4535 }
4536 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4537 if (str)
4538 free(str);
4539 str = str_parms_to_str(reply);
4540 }
4541
Alexy Joseph98988832017-01-13 14:56:59 -08004542 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4543 //only low latency track supports suspend_resume
4544 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004545 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004546 if (str)
4547 free(str);
4548 str = str_parms_to_str(reply);
4549 }
4550
4551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552 str_parms_destroy(query);
4553 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004554 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 return str;
4556}
4557
4558static uint32_t out_get_latency(const struct audio_stream_out *stream)
4559{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004560 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004562 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563
Alexy Josephaa54c872014-12-03 02:46:47 -08004564 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304565 lock_output_stream(out);
4566 latency = audio_extn_utils_compress_get_dsp_latency(out);
4567 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004568 } else if ((out->realtime) ||
4569 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004570 // since the buffer won't be filled up faster than realtime,
4571 // return a smaller number
4572 if (out->config.rate)
4573 period_ms = (out->af_period_multiplier * out->config.period_size *
4574 1000) / (out->config.rate);
4575 else
4576 period_ms = 0;
4577 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004578 } else {
4579 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004580 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004581 }
4582
yidongh0515e042017-07-06 15:00:34 +08004583 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004584 latency += audio_extn_a2dp_get_encoder_latency();
4585
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304586 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004587 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588}
4589
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304590static float AmpToDb(float amplification)
4591{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304592 float db = DSD_VOLUME_MIN_DB;
4593 if (amplification > 0) {
4594 db = 20 * log10(amplification);
4595 if(db < DSD_VOLUME_MIN_DB)
4596 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304597 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304598 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304599}
4600
Arun Mirpuri5d170872019-03-26 13:21:31 -07004601static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4602 float right)
4603{
4604 struct stream_out *out = (struct stream_out *)stream;
4605 long volume = 0;
4606 char mixer_ctl_name[128] = "";
4607 struct audio_device *adev = out->dev;
4608 struct mixer_ctl *ctl = NULL;
4609 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4610 PCM_PLAYBACK);
4611
4612 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4613 "Playback %d Volume", pcm_device_id);
4614 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4615 if (!ctl) {
4616 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4617 __func__, mixer_ctl_name);
4618 return -EINVAL;
4619 }
4620 if (left != right)
4621 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4622 __func__, left, right);
4623 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4624 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4625 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4626 __func__, mixer_ctl_name, volume);
4627 return -EINVAL;
4628 }
4629 return 0;
4630}
4631
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304632static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4633 float right)
4634{
4635 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304636 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304637 char mixer_ctl_name[128];
4638 struct audio_device *adev = out->dev;
4639 struct mixer_ctl *ctl;
4640 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4641 PCM_PLAYBACK);
4642
4643 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4644 "Compress Playback %d Volume", pcm_device_id);
4645 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4646 if (!ctl) {
4647 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4648 __func__, mixer_ctl_name);
4649 return -EINVAL;
4650 }
4651 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4652 __func__, mixer_ctl_name, left, right);
4653 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4654 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4655 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4656
4657 return 0;
4658}
4659
Zhou Song2b8f28f2017-09-11 10:51:38 +08004660static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4661 float right)
4662{
4663 struct stream_out *out = (struct stream_out *)stream;
4664 char mixer_ctl_name[] = "App Type Gain";
4665 struct audio_device *adev = out->dev;
4666 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304667 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004668
4669 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4670 if (!ctl) {
4671 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4672 __func__, mixer_ctl_name);
4673 return -EINVAL;
4674 }
4675
4676 set_values[0] = 0; //0: Rx Session 1:Tx Session
4677 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304678 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4679 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004680
4681 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4682 return 0;
4683}
4684
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304685static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4686 float right)
4687{
4688 struct stream_out *out = (struct stream_out *)stream;
4689 /* Volume control for pcm playback */
4690 if (left != right) {
4691 return -EINVAL;
4692 } else {
4693 char mixer_ctl_name[128];
4694 struct audio_device *adev = out->dev;
4695 struct mixer_ctl *ctl;
4696 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4697 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4698 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4699 if (!ctl) {
4700 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4701 return -EINVAL;
4702 }
4703
4704 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4705 int ret = mixer_ctl_set_value(ctl, 0, volume);
4706 if (ret < 0) {
4707 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4708 return -EINVAL;
4709 }
4710
4711 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4712
4713 return 0;
4714 }
4715}
4716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717static int out_set_volume(struct audio_stream_out *stream, float left,
4718 float right)
4719{
Eric Laurenta9024de2013-04-04 09:19:12 -07004720 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004721 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304722 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004723
Arun Mirpuri5d170872019-03-26 13:21:31 -07004724 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004725 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4726 /* only take left channel into account: the API is for stereo anyway */
4727 out->muted = (left == 0.0f);
4728 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004729 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304730 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004731 /*
4732 * Set mute or umute on HDMI passthrough stream.
4733 * Only take left channel into account.
4734 * Mute is 0 and unmute 1
4735 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304736 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304737 } else if (out->format == AUDIO_FORMAT_DSD){
4738 char mixer_ctl_name[128] = "DSD Volume";
4739 struct audio_device *adev = out->dev;
4740 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4741
4742 if (!ctl) {
4743 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4744 __func__, mixer_ctl_name);
4745 return -EINVAL;
4746 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304747 volume[0] = (long)(AmpToDb(left));
4748 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304749 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4750 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004751 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304752 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004753 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304754 if (!out->a2dp_compress_mute)
4755 ret = out_set_compr_volume(stream, left, right);
4756 out->volume_l = left;
4757 out->volume_r = right;
4758 pthread_mutex_unlock(&out->compr_mute_lock);
4759 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004760 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004761 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004762 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4763 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4764 if (!out->standby) {
4765 audio_extn_utils_send_app_type_gain(out->dev,
4766 out->app_type_cfg.app_type,
4767 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004768 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004769 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004770 out->volume_l = left;
4771 out->volume_r = right;
4772 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004773 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4774 ALOGV("%s: MMAP set volume called", __func__);
4775 if (!out->standby)
4776 ret = out_set_mmap_volume(stream, left, right);
4777 out->volume_l = left;
4778 out->volume_r = right;
4779 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304780 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304781 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4782 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304783 /* Volume control for pcm playback */
4784 if (!out->standby)
4785 ret = out_set_pcm_volume(stream, left, right);
4786 else
4787 out->apply_volume = true;
4788
4789 out->volume_l = left;
4790 out->volume_r = right;
4791 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004792 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794 return -ENOSYS;
4795}
4796
Zhou Songc9672822017-08-16 16:01:39 +08004797static void update_frames_written(struct stream_out *out, size_t bytes)
4798{
4799 size_t bpf = 0;
4800
4801 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4802 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4803 bpf = 1;
4804 else if (!is_offload_usecase(out->usecase))
4805 bpf = audio_bytes_per_sample(out->format) *
4806 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004807
4808 pthread_mutex_lock(&out->position_query_lock);
4809 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004810 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004811 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4812 }
4813 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004814}
4815
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004816int split_and_write_audio_haptic_data(struct stream_out *out,
4817 const void *buffer, size_t bytes_to_write)
4818{
4819 struct audio_device *adev = out->dev;
4820
4821 int ret = 0;
4822 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4823 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4824 size_t frame_size = channel_count * bytes_per_sample;
4825 size_t frame_count = bytes_to_write / frame_size;
4826
4827 bool force_haptic_path =
4828 property_get_bool("vendor.audio.test_haptic", false);
4829
4830 // extract Haptics data from Audio buffer
4831 bool alloc_haptic_buffer = false;
4832 int haptic_channel_count = adev->haptics_config.channels;
4833 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4834 size_t audio_frame_size = frame_size - haptic_frame_size;
4835 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4836
4837 if (adev->haptic_buffer == NULL) {
4838 alloc_haptic_buffer = true;
4839 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4840 free(adev->haptic_buffer);
4841 adev->haptic_buffer_size = 0;
4842 alloc_haptic_buffer = true;
4843 }
4844
4845 if (alloc_haptic_buffer) {
4846 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4847 adev->haptic_buffer_size = total_haptic_buffer_size;
4848 }
4849
4850 size_t src_index = 0, aud_index = 0, hap_index = 0;
4851 uint8_t *audio_buffer = (uint8_t *)buffer;
4852 uint8_t *haptic_buffer = adev->haptic_buffer;
4853
4854 // This is required for testing only. This works for stereo data only.
4855 // One channel is fed to audio stream and other to haptic stream for testing.
4856 if (force_haptic_path)
4857 audio_frame_size = haptic_frame_size = bytes_per_sample;
4858
4859 for (size_t i = 0; i < frame_count; i++) {
4860 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4861 audio_frame_size);
4862 aud_index += audio_frame_size;
4863 src_index += audio_frame_size;
4864
4865 if (adev->haptic_pcm)
4866 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4867 haptic_frame_size);
4868 hap_index += haptic_frame_size;
4869 src_index += haptic_frame_size;
4870
4871 // This is required for testing only.
4872 // Discard haptic channel data.
4873 if (force_haptic_path)
4874 src_index += haptic_frame_size;
4875 }
4876
4877 // write to audio pipeline
4878 ret = pcm_write(out->pcm, (void *)audio_buffer,
4879 frame_count * audio_frame_size);
4880
4881 // write to haptics pipeline
4882 if (adev->haptic_pcm)
4883 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4884 frame_count * haptic_frame_size);
4885
4886 return ret;
4887}
4888
Aalique Grahame22e49102018-12-18 14:23:57 -08004889#ifdef NO_AUDIO_OUT
4890static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4891 const void *buffer __unused, size_t bytes)
4892{
4893 struct stream_out *out = (struct stream_out *)stream;
4894
4895 /* No Output device supported other than BT for playback.
4896 * Sleep for the amount of buffer duration
4897 */
4898 lock_output_stream(out);
4899 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4900 (const struct audio_stream_out *)&out->stream) /
4901 out_get_sample_rate(&out->stream.common));
4902 pthread_mutex_unlock(&out->lock);
4903 return bytes;
4904}
4905#endif
4906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4908 size_t bytes)
4909{
4910 struct stream_out *out = (struct stream_out *)stream;
4911 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004912 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304913 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004914 const size_t frame_size = audio_stream_out_frame_size(stream);
4915 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916
Haynes Mathew George380745d2017-10-04 15:27:45 -07004917 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004918 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304919
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304920 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004921
Dhananjay Kumarac341582017-02-23 23:42:25 +05304922 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304923 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304924 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4925 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004926 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304927 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304928 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304929 ALOGD(" %s: sound card is not active/SSR state", __func__);
4930 ret= -EIO;
4931 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304932 }
4933 }
4934
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304935 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304936 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304937 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304938 goto exit;
4939 }
4940
Haynes Mathew George16081042017-05-31 17:16:49 -07004941 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4942 ret = -EINVAL;
4943 goto exit;
4944 }
4945
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304946 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4947 !out->is_iec61937_info_available) {
4948
4949 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4950 out->is_iec61937_info_available = true;
4951 } else if (audio_extn_passthru_is_enabled()) {
4952 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304953 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304954
4955 if((out->format == AUDIO_FORMAT_DTS) ||
4956 (out->format == AUDIO_FORMAT_DTS_HD)) {
4957 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4958 buffer, bytes);
4959 if (ret) {
4960 if (ret != -ENOSYS) {
4961 out->is_iec61937_info_available = false;
4962 ALOGD("iec61937 transmission info not yet updated retry");
4963 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304964 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304965 /* if stream has started and after that there is
4966 * stream config change (iec transmission config)
4967 * then trigger select_device to update backend configuration.
4968 */
4969 out->stream_config_changed = true;
4970 pthread_mutex_lock(&adev->lock);
4971 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304972 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4973 ret = -EINVAL;
4974 goto exit;
4975 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304976 pthread_mutex_unlock(&adev->lock);
4977 out->stream_config_changed = false;
4978 out->is_iec61937_info_available = true;
4979 }
4980 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304981
Garmond Leung317cbf12017-09-13 16:20:50 -07004982 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304983 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4984 (out->is_iec61937_info_available == true)) {
4985 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4986 ret = -EINVAL;
4987 goto exit;
4988 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304989 }
4990 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304991
4992 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004993 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004994 if (!(out->devices &
4995 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304996 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304997 ret = -EIO;
4998 goto exit;
4999 }
5000 }
5001 }
5002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005004 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005005 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005006 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5007 ret = voice_extn_compress_voip_start_output_stream(out);
5008 else
5009 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005010 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005011 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005013 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014 goto exit;
5015 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305016 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005017 if (last_known_cal_step != -1) {
5018 ALOGD("%s: retry previous failed cal level set", __func__);
5019 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305020 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005021 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305022
5023 if ((out->is_iec61937_info_available == true) &&
5024 (audio_extn_passthru_is_passthrough_stream(out))&&
5025 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5026 ret = -EINVAL;
5027 goto exit;
5028 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305029 if (out->set_dual_mono)
5030 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032
Ashish Jain81eb2a82015-05-13 10:52:34 +05305033 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005034 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305035 adev->is_channel_status_set = true;
5036 }
5037
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005038 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005039 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005040 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005041 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005042 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5043 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305044 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5045 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005046 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305047 out->send_next_track_params = false;
5048 out->is_compr_metadata_avail = false;
5049 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005050 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305051 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305052 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005053
Ashish Jain83a6cc22016-06-28 14:34:17 +05305054 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305055 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305056 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305057 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005058 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305059 return -EINVAL;
5060 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305061 audio_format_t dst_format = out->hal_op_format;
5062 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305063
Dieter Luecking5d57def2018-09-07 14:23:37 +02005064 /* prevent division-by-zero */
5065 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5066 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5067 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5068 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305069 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005070 ATRACE_END();
5071 return -EINVAL;
5072 }
5073
Ashish Jainf1eaa582016-05-23 20:54:24 +05305074 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5075 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5076
Ashish Jain83a6cc22016-06-28 14:34:17 +05305077 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305078 dst_format,
5079 buffer,
5080 src_format,
5081 frames);
5082
Ashish Jain83a6cc22016-06-28 14:34:17 +05305083 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305084 bytes_to_write);
5085
5086 /*Convert written bytes in audio flinger format*/
5087 if (ret > 0)
5088 ret = ((ret * format_to_bitwidth_table[out->format]) /
5089 format_to_bitwidth_table[dst_format]);
5090 }
5091 } else
5092 ret = compress_write(out->compr, buffer, bytes);
5093
Zhou Songc9672822017-08-16 16:01:39 +08005094 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5095 update_frames_written(out, bytes);
5096
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305097 if (ret < 0)
5098 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005099 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305100 /*msg to cb thread only if non blocking write is enabled*/
5101 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305102 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005103 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305104 } else if (-ENETRESET == ret) {
5105 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305106 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305107 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305108 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005109 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305110 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005111 }
Ashish Jain5106d362016-05-11 19:23:33 +05305112
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305113 /* Call compr start only when non-zero bytes of data is there to be rendered */
5114 if (!out->playback_started && ret > 0) {
5115 int status = compress_start(out->compr);
5116 if (status < 0) {
5117 ret = status;
5118 ALOGE("%s: compr start failed with err %d", __func__, errno);
5119 goto exit;
5120 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005121 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005122 out->playback_started = 1;
5123 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005124
5125 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5126 popcount(out->channel_mask),
5127 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005128 }
5129 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005130 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005131 return ret;
5132 } else {
5133 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005134 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005135 if (out->muted)
5136 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005137 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5138 __func__, frames, frame_size, bytes_to_write);
5139
Aalique Grahame22e49102018-12-18 14:23:57 -08005140 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005141 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005142 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5143 int16_t *src = (int16_t *)buffer;
5144 int16_t *dst = (int16_t *)buffer;
5145
5146 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5147 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005148 "out_write called for %s use case with wrong properties",
5149 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005150
5151 /*
5152 * FIXME: this can be removed once audio flinger mixer supports
5153 * mono output
5154 */
5155
5156 /*
5157 * Code below goes over each frame in the buffer and adds both
5158 * L and R samples and then divides by 2 to convert to mono
5159 */
5160 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5161 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5162 }
5163 bytes_to_write /= 2;
5164 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005165
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305166 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005167
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005168 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005169
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005170 if (out->config.rate)
5171 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5172 out->config.rate;
5173
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005174 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005175 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5176
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005177 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005178 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005179 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305180 out->convert_buffer != NULL) {
5181
5182 memcpy_by_audio_format(out->convert_buffer,
5183 out->hal_op_format,
5184 buffer,
5185 out->hal_ip_format,
5186 out->config.period_size * out->config.channels);
5187
5188 ret = pcm_write(out->pcm, out->convert_buffer,
5189 (out->config.period_size *
5190 out->config.channels *
5191 format_to_bitwidth_table[out->hal_op_format]));
5192 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305193 /*
5194 * To avoid underrun in DSP when the application is not pumping
5195 * data at required rate, check for the no. of bytes and ignore
5196 * pcm_write if it is less than actual buffer size.
5197 * It is a work around to a change in compress VOIP driver.
5198 */
5199 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5200 bytes < (out->config.period_size * out->config.channels *
5201 audio_bytes_per_sample(out->format))) {
5202 size_t voip_buf_size =
5203 out->config.period_size * out->config.channels *
5204 audio_bytes_per_sample(out->format);
5205 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5206 __func__, bytes, voip_buf_size);
5207 usleep(((uint64_t)voip_buf_size - bytes) *
5208 1000000 / audio_stream_out_frame_size(stream) /
5209 out_get_sample_rate(&out->stream.common));
5210 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005211 } else {
5212 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5213 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5214 else
5215 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5216 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305217 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005218
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005219 release_out_focus(out);
5220
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305221 if (ret < 0)
5222 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005223 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305224 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226 }
5227
5228exit:
Zhou Songc9672822017-08-16 16:01:39 +08005229 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305230 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305231 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305232 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233 pthread_mutex_unlock(&out->lock);
5234
5235 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005236 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005237 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305238 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305239 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305240 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305241 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305242 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305243 out->standby = true;
5244 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305245 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005246 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5247 /* prevent division-by-zero */
5248 uint32_t stream_size = audio_stream_out_frame_size(stream);
5249 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005250
Dieter Luecking5d57def2018-09-07 14:23:37 +02005251 if ((stream_size == 0) || (srate == 0)) {
5252 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5253 ATRACE_END();
5254 return -EINVAL;
5255 }
5256 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5257 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005258 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305259 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005260 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005261 return ret;
5262 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005264 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265 return bytes;
5266}
5267
5268static int out_get_render_position(const struct audio_stream_out *stream,
5269 uint32_t *dsp_frames)
5270{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005271 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005272
5273 if (dsp_frames == NULL)
5274 return -EINVAL;
5275
5276 *dsp_frames = 0;
5277 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005278 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305279
5280 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5281 * this operation and adev_close_output_stream(where out gets reset).
5282 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305283 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005284 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305285 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005286 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305287 return 0;
5288 }
5289
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005290 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305291 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305292 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005293 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305294 if (ret < 0)
5295 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005296 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305297 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005298 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305299 if (-ENETRESET == ret) {
5300 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305301 out->card_status = CARD_STATUS_OFFLINE;
5302 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305303 } else if(ret < 0) {
5304 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305305 ret = -EINVAL;
5306 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305307 /*
5308 * Handle corner case where compress session is closed during SSR
5309 * and timestamp is queried
5310 */
5311 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305312 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305313 } else if (out->prev_card_status_offline) {
5314 ALOGE("ERROR: previously sound card was offline,return error");
5315 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305316 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305317 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005318 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305319 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305320 pthread_mutex_unlock(&out->lock);
5321 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005322 } else if (audio_is_linear_pcm(out->format)) {
5323 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005324 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005325 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005326 } else
5327 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005328}
5329
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005330static int out_add_audio_effect(const struct audio_stream *stream __unused,
5331 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005332{
5333 return 0;
5334}
5335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005336static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5337 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338{
5339 return 0;
5340}
5341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005342static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5343 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005344{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305345 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346}
5347
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005348static int out_get_presentation_position(const struct audio_stream_out *stream,
5349 uint64_t *frames, struct timespec *timestamp)
5350{
5351 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305352 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005353 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005354
Ashish Jain5106d362016-05-11 19:23:33 +05305355 /* below piece of code is not guarded against any lock because audioFliner serializes
5356 * this operation and adev_close_output_stream( where out gets reset).
5357 */
5358 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305359 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005360 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305361 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5362 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5363 return 0;
5364 }
5365
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005366 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005367
Ashish Jain5106d362016-05-11 19:23:33 +05305368 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5369 ret = compress_get_tstamp(out->compr, &dsp_frames,
5370 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005371 // Adjustment accounts for A2dp encoder latency with offload usecases
5372 // Note: Encoder latency is returned in ms.
5373 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5374 unsigned long offset =
5375 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5376 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5377 }
Ashish Jain5106d362016-05-11 19:23:33 +05305378 ALOGVV("%s rendered frames %ld sample_rate %d",
5379 __func__, dsp_frames, out->sample_rate);
5380 *frames = dsp_frames;
5381 if (ret < 0)
5382 ret = -errno;
5383 if (-ENETRESET == ret) {
5384 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305385 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305386 ret = -EINVAL;
5387 } else
5388 ret = 0;
5389 /* this is the best we can do */
5390 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005391 } else {
5392 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005393 unsigned int avail;
5394 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5395 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5396 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5397 // This adjustment accounts for buffering after app processor.
5398 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005399 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005400 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005401
Weiyin Jiangd4633762018-03-16 12:05:03 +08005402 // Adjustment accounts for A2dp encoder latency with non offload usecases
5403 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5404 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5405 signed_frames -=
5406 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5407 }
5408
5409 // It would be unusual for this value to be negative, but check just in case ...
5410 if (signed_frames >= 0) {
5411 *frames = signed_frames;
5412 ret = 0;
5413 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005414 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305415 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305416 *frames = out->written;
5417 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305418 if (is_offload_usecase(out->usecase))
5419 ret = -EINVAL;
5420 else
5421 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005422 }
5423 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005424 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005425 return ret;
5426}
5427
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005428static int out_set_callback(struct audio_stream_out *stream,
5429 stream_callback_t callback, void *cookie)
5430{
5431 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005432 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005433
5434 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005435 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005436 out->client_callback = callback;
5437 out->client_cookie = cookie;
5438 if (out->adsp_hdlr_stream_handle) {
5439 ret = audio_extn_adsp_hdlr_stream_set_callback(
5440 out->adsp_hdlr_stream_handle,
5441 callback,
5442 cookie);
5443 if (ret)
5444 ALOGW("%s:adsp hdlr callback registration failed %d",
5445 __func__, ret);
5446 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005447 pthread_mutex_unlock(&out->lock);
5448 return 0;
5449}
5450
5451static int out_pause(struct audio_stream_out* stream)
5452{
5453 struct stream_out *out = (struct stream_out *)stream;
5454 int status = -ENOSYS;
5455 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005456 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005457 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005458 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005459 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305460 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305461 status = compress_pause(out->compr);
5462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005463 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005464
Mingming Yin21854652016-04-13 11:54:02 -07005465 if (audio_extn_passthru_is_active()) {
5466 ALOGV("offload use case, pause passthru");
5467 audio_extn_passthru_on_pause(out);
5468 }
5469
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305470 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005471 audio_extn_dts_notify_playback_state(out->usecase, 0,
5472 out->sample_rate, popcount(out->channel_mask),
5473 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005474 }
5475 pthread_mutex_unlock(&out->lock);
5476 }
5477 return status;
5478}
5479
5480static int out_resume(struct audio_stream_out* stream)
5481{
5482 struct stream_out *out = (struct stream_out *)stream;
5483 int status = -ENOSYS;
5484 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005485 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005486 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005487 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005488 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005489 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305490 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305491 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005492 }
5493 if (!status) {
5494 out->offload_state = OFFLOAD_STATE_PLAYING;
5495 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305496 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005497 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5498 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005499 }
5500 pthread_mutex_unlock(&out->lock);
5501 }
5502 return status;
5503}
5504
5505static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5506{
5507 struct stream_out *out = (struct stream_out *)stream;
5508 int status = -ENOSYS;
5509 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005510 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005512 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5513 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5514 else
5515 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5516 pthread_mutex_unlock(&out->lock);
5517 }
5518 return status;
5519}
5520
5521static int out_flush(struct audio_stream_out* stream)
5522{
5523 struct stream_out *out = (struct stream_out *)stream;
5524 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005525 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005526 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005527 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005528 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5529 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005530 } else {
5531 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5532 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005533 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005534 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005535 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005536 return 0;
5537 }
5538 return -ENOSYS;
5539}
5540
Haynes Mathew George16081042017-05-31 17:16:49 -07005541static int out_stop(const struct audio_stream_out* stream)
5542{
5543 struct stream_out *out = (struct stream_out *)stream;
5544 struct audio_device *adev = out->dev;
5545 int ret = -ENOSYS;
5546
5547 ALOGV("%s", __func__);
5548 pthread_mutex_lock(&adev->lock);
5549 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5550 out->playback_started && out->pcm != NULL) {
5551 pcm_stop(out->pcm);
5552 ret = stop_output_stream(out);
5553 out->playback_started = false;
5554 }
5555 pthread_mutex_unlock(&adev->lock);
5556 return ret;
5557}
5558
5559static int out_start(const struct audio_stream_out* stream)
5560{
5561 struct stream_out *out = (struct stream_out *)stream;
5562 struct audio_device *adev = out->dev;
5563 int ret = -ENOSYS;
5564
5565 ALOGV("%s", __func__);
5566 pthread_mutex_lock(&adev->lock);
5567 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5568 !out->playback_started && out->pcm != NULL) {
5569 ret = start_output_stream(out);
5570 if (ret == 0) {
5571 out->playback_started = true;
5572 }
5573 }
5574 pthread_mutex_unlock(&adev->lock);
5575 return ret;
5576}
5577
5578/*
5579 * Modify config->period_count based on min_size_frames
5580 */
5581static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5582{
5583 int periodCountRequested = (min_size_frames + config->period_size - 1)
5584 / config->period_size;
5585 int periodCount = MMAP_PERIOD_COUNT_MIN;
5586
5587 ALOGV("%s original config.period_size = %d config.period_count = %d",
5588 __func__, config->period_size, config->period_count);
5589
5590 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5591 periodCount *= 2;
5592 }
5593 config->period_count = periodCount;
5594
5595 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5596}
5597
5598static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5599 int32_t min_size_frames,
5600 struct audio_mmap_buffer_info *info)
5601{
5602 struct stream_out *out = (struct stream_out *)stream;
5603 struct audio_device *adev = out->dev;
5604 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005605 unsigned int offset1 = 0;
5606 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005607 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005608 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005609 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005610
Arun Mirpuri5d170872019-03-26 13:21:31 -07005611 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305612 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005613 pthread_mutex_lock(&adev->lock);
5614
Sharad Sanglec6f32552018-05-04 16:15:38 +05305615 if (CARD_STATUS_OFFLINE == out->card_status ||
5616 CARD_STATUS_OFFLINE == adev->card_status) {
5617 ALOGW("out->card_status or adev->card_status offline, try again");
5618 ret = -EIO;
5619 goto exit;
5620 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005621 if (info == NULL || min_size_frames == 0) {
5622 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5623 ret = -EINVAL;
5624 goto exit;
5625 }
5626 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5627 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5628 ret = -ENOSYS;
5629 goto exit;
5630 }
5631 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5632 if (out->pcm_device_id < 0) {
5633 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5634 __func__, out->pcm_device_id, out->usecase);
5635 ret = -EINVAL;
5636 goto exit;
5637 }
5638
5639 adjust_mmap_period_count(&out->config, min_size_frames);
5640
Arun Mirpuri5d170872019-03-26 13:21:31 -07005641 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005642 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5643 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5644 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305645 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305646 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5647 out->card_status = CARD_STATUS_OFFLINE;
5648 adev->card_status = CARD_STATUS_OFFLINE;
5649 ret = -EIO;
5650 goto exit;
5651 }
5652
Haynes Mathew George16081042017-05-31 17:16:49 -07005653 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5654 step = "open";
5655 ret = -ENODEV;
5656 goto exit;
5657 }
5658 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5659 if (ret < 0) {
5660 step = "begin";
5661 goto exit;
5662 }
5663 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005664 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005665 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005666 ret = platform_get_mmap_data_fd(adev->platform,
5667 out->pcm_device_id, 0 /*playback*/,
5668 &info->shared_memory_fd,
5669 &mmap_size);
5670 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005671 // Fall back to non exclusive mode
5672 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5673 } else {
5674 if (mmap_size < buffer_size) {
5675 step = "mmap";
5676 goto exit;
5677 }
5678 // FIXME: indicate exclusive mode support by returning a negative buffer size
5679 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005680 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005681 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005682 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005683
5684 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5685 if (ret < 0) {
5686 step = "commit";
5687 goto exit;
5688 }
5689
5690 out->standby = false;
5691 ret = 0;
5692
Arun Mirpuri5d170872019-03-26 13:21:31 -07005693 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005694 __func__, info->shared_memory_address, info->buffer_size_frames);
5695
5696exit:
5697 if (ret != 0) {
5698 if (out->pcm == NULL) {
5699 ALOGE("%s: %s - %d", __func__, step, ret);
5700 } else {
5701 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5702 pcm_close(out->pcm);
5703 out->pcm = NULL;
5704 }
5705 }
5706 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305707 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005708 return ret;
5709}
5710
5711static int out_get_mmap_position(const struct audio_stream_out *stream,
5712 struct audio_mmap_position *position)
5713{
5714 struct stream_out *out = (struct stream_out *)stream;
5715 ALOGVV("%s", __func__);
5716 if (position == NULL) {
5717 return -EINVAL;
5718 }
5719 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005720 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005721 return -ENOSYS;
5722 }
5723 if (out->pcm == NULL) {
5724 return -ENOSYS;
5725 }
5726
5727 struct timespec ts = { 0, 0 };
5728 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5729 if (ret < 0) {
5730 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5731 return ret;
5732 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005733 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005734 return 0;
5735}
5736
5737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005738/** audio_stream_in implementation **/
5739static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5740{
5741 struct stream_in *in = (struct stream_in *)stream;
5742
5743 return in->config.rate;
5744}
5745
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005746static int in_set_sample_rate(struct audio_stream *stream __unused,
5747 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005748{
5749 return -ENOSYS;
5750}
5751
5752static size_t in_get_buffer_size(const struct audio_stream *stream)
5753{
5754 struct stream_in *in = (struct stream_in *)stream;
5755
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005756 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5757 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005758 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5759 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 -07005760 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5761 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305762 else if(audio_extn_cin_attached_usecase(in->usecase))
5763 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005764
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005765 return in->config.period_size * in->af_period_multiplier *
5766 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005767}
5768
5769static uint32_t in_get_channels(const struct audio_stream *stream)
5770{
5771 struct stream_in *in = (struct stream_in *)stream;
5772
5773 return in->channel_mask;
5774}
5775
5776static audio_format_t in_get_format(const struct audio_stream *stream)
5777{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005778 struct stream_in *in = (struct stream_in *)stream;
5779
5780 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005781}
5782
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005783static int in_set_format(struct audio_stream *stream __unused,
5784 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005785{
5786 return -ENOSYS;
5787}
5788
5789static int in_standby(struct audio_stream *stream)
5790{
5791 struct stream_in *in = (struct stream_in *)stream;
5792 struct audio_device *adev = in->dev;
5793 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305794 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5795 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005796 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305797
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005798 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005799 if (!in->standby && in->is_st_session) {
5800 ALOGD("%s: sound trigger pcm stop lab", __func__);
5801 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005802 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005803 in->standby = 1;
5804 }
5805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005806 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005807 if (adev->adm_deregister_stream)
5808 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5809
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005810 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005811 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005812 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005813 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005814 voice_extn_compress_voip_close_input_stream(stream);
5815 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005816 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5817 do_stop = in->capture_started;
5818 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005819 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305820 if (audio_extn_cin_attached_usecase(in->usecase))
5821 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005822 }
5823
Arun Mirpuri5d170872019-03-26 13:21:31 -07005824 if (in->pcm) {
5825 ATRACE_BEGIN("pcm_in_close");
5826 pcm_close(in->pcm);
5827 ATRACE_END();
5828 in->pcm = NULL;
5829 }
5830
5831 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005832 adev->enable_voicerx = false;
5833 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005834 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005835 }
Quinn Malef6050362019-01-30 15:55:40 -08005836
5837 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5838 adev->num_va_sessions--;
5839
Eric Laurent150dbfe2013-02-27 14:31:02 -08005840 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005841 }
5842 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005843 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 return status;
5845}
5846
Aalique Grahame22e49102018-12-18 14:23:57 -08005847static int in_dump(const struct audio_stream *stream,
5848 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849{
Aalique Grahame22e49102018-12-18 14:23:57 -08005850 struct stream_in *in = (struct stream_in *)stream;
5851
5852 // We try to get the lock for consistency,
5853 // but it isn't necessary for these variables.
5854 // If we're not in standby, we may be blocked on a read.
5855 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5856 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5857 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5858 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5859
5860 if (locked) {
5861 pthread_mutex_unlock(&in->lock);
5862 }
5863
5864 // dump error info
5865 (void)error_log_dump(
5866 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868 return 0;
5869}
5870
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305871static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5872{
5873 if (!stream || !parms)
5874 return;
5875
5876 struct stream_in *in = (struct stream_in *)stream;
5877 struct audio_device *adev = in->dev;
5878
5879 card_status_t status;
5880 int card;
5881 if (parse_snd_card_status(parms, &card, &status) < 0)
5882 return;
5883
5884 pthread_mutex_lock(&adev->lock);
5885 bool valid_cb = (card == adev->snd_card);
5886 pthread_mutex_unlock(&adev->lock);
5887
5888 if (!valid_cb)
5889 return;
5890
5891 lock_input_stream(in);
5892 if (in->card_status != status)
5893 in->card_status = status;
5894 pthread_mutex_unlock(&in->lock);
5895
5896 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5897 use_case_table[in->usecase],
5898 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5899
5900 // a better solution would be to report error back to AF and let
5901 // it put the stream to standby
5902 if (status == CARD_STATUS_OFFLINE)
5903 in_standby(&in->stream.common);
5904
5905 return;
5906}
5907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005908static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5909{
5910 struct stream_in *in = (struct stream_in *)stream;
5911 struct audio_device *adev = in->dev;
5912 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005913 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005914 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005915
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305916 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005917 parms = str_parms_create_str(kvpairs);
5918
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305919 if (!parms)
5920 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005921 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005922 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005923
5924 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5925 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005926 val = atoi(value);
5927 /* no audio source uses val == 0 */
5928 if ((in->source != val) && (val != 0)) {
5929 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005930 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5931 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5932 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005933 (in->config.rate == 8000 || in->config.rate == 16000 ||
5934 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005935 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005936 err = voice_extn_compress_voip_open_input_stream(in);
5937 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005938 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005939 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005940 }
5941 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005942 }
5943 }
5944
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005945 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5946 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005947 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005948 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5949
5950 // Workaround: If routing to an non existing usb device, fail gracefully
5951 // The routing request will otherwise block during 10 second
5952 int card;
5953 if (audio_is_usb_in_device(val) &&
5954 (card = get_alive_usb_card(parms)) >= 0) {
5955
5956 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5957 ret = -ENOSYS;
5958 } else {
5959
5960 in->device = val;
5961 /* If recording is in progress, change the tx device to new device */
5962 if (!in->standby && !in->is_st_session) {
5963 ALOGV("update input routing change");
5964 // inform adm before actual routing to prevent glitches.
5965 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005966 adev->adm_on_routing_change(adev->adm_data,
5967 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005968 ret = select_devices(adev, in->usecase);
5969 }
5970 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005972 }
5973 }
5974
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305975 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5976 if (err >= 0) {
5977 strlcpy(in->profile, value, sizeof(in->profile));
5978 ALOGV("updating stream profile with value '%s'", in->profile);
5979 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5980 &adev->streams_input_cfg_list,
5981 in->device, in->flags, in->format,
5982 in->sample_rate, in->bit_width,
5983 in->profile, &in->app_type_cfg);
5984 }
5985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005986 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005987 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005988
5989 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305990error:
Eric Laurent994a6932013-07-17 11:51:42 -07005991 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005992 return ret;
5993}
5994
5995static char* in_get_parameters(const struct audio_stream *stream,
5996 const char *keys)
5997{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005998 struct stream_in *in = (struct stream_in *)stream;
5999 struct str_parms *query = str_parms_create_str(keys);
6000 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006001 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006002
6003 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006004 if (reply) {
6005 str_parms_destroy(reply);
6006 }
6007 if (query) {
6008 str_parms_destroy(query);
6009 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006010 ALOGE("in_get_parameters: failed to create query or reply");
6011 return NULL;
6012 }
6013
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006014 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006015
6016 voice_extn_in_get_parameters(in, query, reply);
6017
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006018 stream_get_parameter_channels(query, reply,
6019 &in->supported_channel_masks[0]);
6020 stream_get_parameter_formats(query, reply,
6021 &in->supported_formats[0]);
6022 stream_get_parameter_rates(query, reply,
6023 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006024 str = str_parms_to_str(reply);
6025 str_parms_destroy(query);
6026 str_parms_destroy(reply);
6027
6028 ALOGV("%s: exit: returns - %s", __func__, str);
6029 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006030}
6031
Aalique Grahame22e49102018-12-18 14:23:57 -08006032static int in_set_gain(struct audio_stream_in *stream,
6033 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006034{
Aalique Grahame22e49102018-12-18 14:23:57 -08006035 struct stream_in *in = (struct stream_in *)stream;
6036 char mixer_ctl_name[128];
6037 struct mixer_ctl *ctl;
6038 int ctl_value;
6039
6040 ALOGV("%s: gain %f", __func__, gain);
6041
6042 if (stream == NULL)
6043 return -EINVAL;
6044
6045 /* in_set_gain() only used to silence MMAP capture for now */
6046 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6047 return -ENOSYS;
6048
6049 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6050
6051 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6052 if (!ctl) {
6053 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6054 __func__, mixer_ctl_name);
6055 return -ENOSYS;
6056 }
6057
6058 if (gain < RECORD_GAIN_MIN)
6059 gain = RECORD_GAIN_MIN;
6060 else if (gain > RECORD_GAIN_MAX)
6061 gain = RECORD_GAIN_MAX;
6062 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6063
6064 mixer_ctl_set_value(ctl, 0, ctl_value);
6065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066 return 0;
6067}
6068
6069static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6070 size_t bytes)
6071{
6072 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306073
6074 if (in == NULL) {
6075 ALOGE("%s: stream_in ptr is NULL", __func__);
6076 return -EINVAL;
6077 }
6078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006079 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306080 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306081 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006082
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006083 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306084
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006085 if (in->is_st_session) {
6086 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6087 /* Read from sound trigger HAL */
6088 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006089 if (in->standby) {
6090 adev->num_va_sessions++;
6091 in->standby = 0;
6092 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006093 pthread_mutex_unlock(&in->lock);
6094 return bytes;
6095 }
6096
Haynes Mathew George16081042017-05-31 17:16:49 -07006097 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6098 ret = -ENOSYS;
6099 goto exit;
6100 }
6101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006102 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006103 pthread_mutex_lock(&adev->lock);
6104 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6105 ret = voice_extn_compress_voip_start_input_stream(in);
6106 else
6107 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006108 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6109 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006110 pthread_mutex_unlock(&adev->lock);
6111 if (ret != 0) {
6112 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006113 }
6114 in->standby = 0;
6115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006116
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006117 // what's the duration requested by the client?
6118 long ns = 0;
6119
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306120 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006121 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6122 in->config.rate;
6123
6124 request_in_focus(in, ns);
6125 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006126
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306127 if (audio_extn_cin_attached_usecase(in->usecase)) {
6128 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6129 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306130 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006131 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306132 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006133 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006134 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006135 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006136 } else if (audio_extn_ffv_get_stream() == in) {
6137 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306138 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006139 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306140 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6141 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6142 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6143 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306144 ret = -EINVAL;
6145 goto exit;
6146 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306147 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306148 ret = -errno;
6149 }
6150 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306151 /* bytes read is always set to bytes for non compress usecases */
6152 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153 }
6154
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006155 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006157 /*
Quinn Malef6050362019-01-30 15:55:40 -08006158 * Instead of writing zeroes here, we could trust the hardware to always
6159 * provide zeroes when muted. This is also muted with voice recognition
6160 * usecases so that other clients do not have access to voice recognition
6161 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006162 */
Quinn Malef6050362019-01-30 15:55:40 -08006163 if ((ret == 0 && voice_get_mic_mute(adev) &&
6164 !voice_is_in_call_rec_stream(in) &&
6165 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6166 (adev->num_va_sessions &&
6167 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6168 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6169 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006170 memset(buffer, 0, bytes);
6171
6172exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006173 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306174 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006175 pthread_mutex_unlock(&in->lock);
6176
6177 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306178 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306179 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306180 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306181 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306182 in->standby = true;
6183 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306184 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6185 bytes_read = bytes;
6186 memset(buffer, 0, bytes);
6187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006188 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006189 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306190 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306191 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006192 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306193 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006194}
6195
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006196static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006197{
6198 return 0;
6199}
6200
Aalique Grahame22e49102018-12-18 14:23:57 -08006201static int in_get_capture_position(const struct audio_stream_in *stream,
6202 int64_t *frames, int64_t *time)
6203{
6204 if (stream == NULL || frames == NULL || time == NULL) {
6205 return -EINVAL;
6206 }
6207 struct stream_in *in = (struct stream_in *)stream;
6208 int ret = -ENOSYS;
6209
6210 lock_input_stream(in);
6211 // note: ST sessions do not close the alsa pcm driver synchronously
6212 // on standby. Therefore, we may return an error even though the
6213 // pcm stream is still opened.
6214 if (in->standby) {
6215 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6216 "%s stream in standby but pcm not NULL for non ST session", __func__);
6217 goto exit;
6218 }
6219 if (in->pcm) {
6220 struct timespec timestamp;
6221 unsigned int avail;
6222 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6223 *frames = in->frames_read + avail;
6224 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6225 ret = 0;
6226 }
6227 }
6228exit:
6229 pthread_mutex_unlock(&in->lock);
6230 return ret;
6231}
6232
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006233static int add_remove_audio_effect(const struct audio_stream *stream,
6234 effect_handle_t effect,
6235 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006236{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006237 struct stream_in *in = (struct stream_in *)stream;
6238 int status = 0;
6239 effect_descriptor_t desc;
6240
6241 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006242 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6243
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006244 if (status != 0)
6245 return status;
6246
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006247 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006248 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006249 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006250 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006251 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006252 in->enable_aec != enable &&
6253 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6254 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006255 if (!enable)
6256 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6257 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6258 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6259 in->dev->enable_voicerx = enable;
6260 struct audio_usecase *usecase;
6261 struct listnode *node;
6262 list_for_each(node, &in->dev->usecase_list) {
6263 usecase = node_to_item(node, struct audio_usecase, list);
6264 if (usecase->type == PCM_PLAYBACK)
6265 select_devices(in->dev, usecase->id);
6266 }
6267 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006268 if (!in->standby) {
6269 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6270 select_devices(in->dev, in->usecase);
6271 }
6272
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006273 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006274 if (in->enable_ns != enable &&
6275 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6276 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006277 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006278 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6279 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006280 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6281 select_devices(in->dev, in->usecase);
6282 } else
6283 select_devices(in->dev, in->usecase);
6284 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006285 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006286 pthread_mutex_unlock(&in->dev->lock);
6287 pthread_mutex_unlock(&in->lock);
6288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006289 return 0;
6290}
6291
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006292static int in_add_audio_effect(const struct audio_stream *stream,
6293 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006294{
Eric Laurent994a6932013-07-17 11:51:42 -07006295 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006296 return add_remove_audio_effect(stream, effect, true);
6297}
6298
6299static int in_remove_audio_effect(const struct audio_stream *stream,
6300 effect_handle_t effect)
6301{
Eric Laurent994a6932013-07-17 11:51:42 -07006302 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006303 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006304}
6305
Derek Chenf939fb72018-11-13 13:34:41 -08006306streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6307 audio_io_handle_t input)
6308{
6309 struct listnode *node;
6310
6311 list_for_each(node, &dev->active_inputs_list) {
6312 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6313 streams_input_ctxt_t,
6314 list);
6315 if (in_ctxt->input->capture_handle == input) {
6316 return in_ctxt;
6317 }
6318 }
6319 return NULL;
6320}
6321
6322streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6323 audio_io_handle_t output)
6324{
6325 struct listnode *node;
6326
6327 list_for_each(node, &dev->active_outputs_list) {
6328 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6329 streams_output_ctxt_t,
6330 list);
6331 if (out_ctxt->output->handle == output) {
6332 return out_ctxt;
6333 }
6334 }
6335 return NULL;
6336}
6337
Haynes Mathew George16081042017-05-31 17:16:49 -07006338static int in_stop(const struct audio_stream_in* stream)
6339{
6340 struct stream_in *in = (struct stream_in *)stream;
6341 struct audio_device *adev = in->dev;
6342
6343 int ret = -ENOSYS;
6344 ALOGV("%s", __func__);
6345 pthread_mutex_lock(&adev->lock);
6346 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6347 in->capture_started && in->pcm != NULL) {
6348 pcm_stop(in->pcm);
6349 ret = stop_input_stream(in);
6350 in->capture_started = false;
6351 }
6352 pthread_mutex_unlock(&adev->lock);
6353 return ret;
6354}
6355
6356static int in_start(const struct audio_stream_in* stream)
6357{
6358 struct stream_in *in = (struct stream_in *)stream;
6359 struct audio_device *adev = in->dev;
6360 int ret = -ENOSYS;
6361
6362 ALOGV("%s in %p", __func__, in);
6363 pthread_mutex_lock(&adev->lock);
6364 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6365 !in->capture_started && in->pcm != NULL) {
6366 if (!in->capture_started) {
6367 ret = start_input_stream(in);
6368 if (ret == 0) {
6369 in->capture_started = true;
6370 }
6371 }
6372 }
6373 pthread_mutex_unlock(&adev->lock);
6374 return ret;
6375}
6376
6377static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6378 int32_t min_size_frames,
6379 struct audio_mmap_buffer_info *info)
6380{
6381 struct stream_in *in = (struct stream_in *)stream;
6382 struct audio_device *adev = in->dev;
6383 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006384 unsigned int offset1 = 0;
6385 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006386 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006387 uint32_t mmap_size = 0;
6388 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006389
6390 pthread_mutex_lock(&adev->lock);
6391 ALOGV("%s in %p", __func__, in);
6392
Sharad Sanglec6f32552018-05-04 16:15:38 +05306393 if (CARD_STATUS_OFFLINE == in->card_status||
6394 CARD_STATUS_OFFLINE == adev->card_status) {
6395 ALOGW("in->card_status or adev->card_status offline, try again");
6396 ret = -EIO;
6397 goto exit;
6398 }
6399
Haynes Mathew George16081042017-05-31 17:16:49 -07006400 if (info == NULL || min_size_frames == 0) {
6401 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6402 ret = -EINVAL;
6403 goto exit;
6404 }
6405 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6406 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6407 ALOGV("%s in %p", __func__, in);
6408 ret = -ENOSYS;
6409 goto exit;
6410 }
6411 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6412 if (in->pcm_device_id < 0) {
6413 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6414 __func__, in->pcm_device_id, in->usecase);
6415 ret = -EINVAL;
6416 goto exit;
6417 }
6418
6419 adjust_mmap_period_count(&in->config, min_size_frames);
6420
6421 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6422 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6423 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6424 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306425 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306426 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6427 in->card_status = CARD_STATUS_OFFLINE;
6428 adev->card_status = CARD_STATUS_OFFLINE;
6429 ret = -EIO;
6430 goto exit;
6431 }
6432
Haynes Mathew George16081042017-05-31 17:16:49 -07006433 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6434 step = "open";
6435 ret = -ENODEV;
6436 goto exit;
6437 }
6438
6439 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6440 if (ret < 0) {
6441 step = "begin";
6442 goto exit;
6443 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006444
Arun Mirpuri5d170872019-03-26 13:21:31 -07006445 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6446 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6447 info->burst_size_frames = in->config.period_size;
6448 ret = platform_get_mmap_data_fd(adev->platform,
6449 in->pcm_device_id, 1 /*capture*/,
6450 &info->shared_memory_fd,
6451 &mmap_size);
6452 if (ret < 0) {
6453 // Fall back to non exclusive mode
6454 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6455 } else {
6456 if (mmap_size < buffer_size) {
6457 step = "mmap";
6458 goto exit;
6459 }
6460 // FIXME: indicate exclusive mode support by returning a negative buffer size
6461 info->buffer_size_frames *= -1;
6462 }
6463
6464 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006465
6466 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6467 if (ret < 0) {
6468 step = "commit";
6469 goto exit;
6470 }
6471
6472 in->standby = false;
6473 ret = 0;
6474
6475 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6476 __func__, info->shared_memory_address, info->buffer_size_frames);
6477
6478exit:
6479 if (ret != 0) {
6480 if (in->pcm == NULL) {
6481 ALOGE("%s: %s - %d", __func__, step, ret);
6482 } else {
6483 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6484 pcm_close(in->pcm);
6485 in->pcm = NULL;
6486 }
6487 }
6488 pthread_mutex_unlock(&adev->lock);
6489 return ret;
6490}
6491
6492static int in_get_mmap_position(const struct audio_stream_in *stream,
6493 struct audio_mmap_position *position)
6494{
6495 struct stream_in *in = (struct stream_in *)stream;
6496 ALOGVV("%s", __func__);
6497 if (position == NULL) {
6498 return -EINVAL;
6499 }
6500 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6501 return -ENOSYS;
6502 }
6503 if (in->pcm == NULL) {
6504 return -ENOSYS;
6505 }
6506 struct timespec ts = { 0, 0 };
6507 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6508 if (ret < 0) {
6509 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6510 return ret;
6511 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306512 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006513 return 0;
6514}
6515
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306516static int in_get_active_microphones(const struct audio_stream_in *stream,
6517 struct audio_microphone_characteristic_t *mic_array,
6518 size_t *mic_count) {
6519 struct stream_in *in = (struct stream_in *)stream;
6520 struct audio_device *adev = in->dev;
6521 ALOGVV("%s", __func__);
6522
6523 lock_input_stream(in);
6524 pthread_mutex_lock(&adev->lock);
6525 int ret = platform_get_active_microphones(adev->platform,
6526 audio_channel_count_from_in_mask(in->channel_mask),
6527 in->usecase, mic_array, mic_count);
6528 pthread_mutex_unlock(&adev->lock);
6529 pthread_mutex_unlock(&in->lock);
6530
6531 return ret;
6532}
6533
6534static int adev_get_microphones(const struct audio_hw_device *dev,
6535 struct audio_microphone_characteristic_t *mic_array,
6536 size_t *mic_count) {
6537 struct audio_device *adev = (struct audio_device *)dev;
6538 ALOGVV("%s", __func__);
6539
6540 pthread_mutex_lock(&adev->lock);
6541 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6542 pthread_mutex_unlock(&adev->lock);
6543
6544 return ret;
6545}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306546int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006547 audio_io_handle_t handle,
6548 audio_devices_t devices,
6549 audio_output_flags_t flags,
6550 struct audio_config *config,
6551 struct audio_stream_out **stream_out,
6552 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006553{
6554 struct audio_device *adev = (struct audio_device *)dev;
6555 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306556 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006557 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006558 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306559 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006560 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6561 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6562 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6563 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006564 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006565 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006566 bool force_haptic_path =
6567 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006568
kunleizdff872d2018-08-20 14:40:33 +08006569 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006570 is_usb_dev = false;
6571 devices = AUDIO_DEVICE_OUT_SPEAKER;
6572 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6573 __func__, devices);
6574 }
6575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006576 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6579
Mingming Yin3a941d42016-02-17 18:08:05 -08006580 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6581 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306582 devices, flags, &out->stream);
6583
6584
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006585 if (!out) {
6586 return -ENOMEM;
6587 }
6588
Haynes Mathew George204045b2015-02-25 20:32:03 -08006589 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006590 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306591 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006592 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006593 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006595 if (devices == AUDIO_DEVICE_NONE)
6596 devices = AUDIO_DEVICE_OUT_SPEAKER;
6597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006598 out->flags = flags;
6599 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006600 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006601 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006602 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306603 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306604 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6605 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6606 else
6607 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006608 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006609 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006610 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306611 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306612 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306613 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006614 out->hal_output_suspend_supported = 0;
6615 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306616 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306617 out->prev_card_status_offline = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306619 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306620 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006621 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6622
Aalique Grahame22e49102018-12-18 14:23:57 -08006623 if (direct_dev &&
6624 (audio_is_linear_pcm(out->format) ||
6625 config->format == AUDIO_FORMAT_DEFAULT) &&
6626 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6627 audio_format_t req_format = config->format;
6628 audio_channel_mask_t req_channel_mask = config->channel_mask;
6629 uint32_t req_sample_rate = config->sample_rate;
6630
6631 pthread_mutex_lock(&adev->lock);
6632 if (is_hdmi) {
6633 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6634 ret = read_hdmi_sink_caps(out);
6635 if (config->sample_rate == 0)
6636 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6637 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6638 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6639 if (config->format == AUDIO_FORMAT_DEFAULT)
6640 config->format = AUDIO_FORMAT_PCM_16_BIT;
6641 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006642 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6643 &config->format,
6644 &out->supported_formats[0],
6645 MAX_SUPPORTED_FORMATS,
6646 &config->channel_mask,
6647 &out->supported_channel_masks[0],
6648 MAX_SUPPORTED_CHANNEL_MASKS,
6649 &config->sample_rate,
6650 &out->supported_sample_rates[0],
6651 MAX_SUPPORTED_SAMPLE_RATES);
6652 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006653 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006654
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006655 pthread_mutex_unlock(&adev->lock);
6656 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006657 if (ret == -ENOSYS) {
6658 /* ignore and go with default */
6659 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006660 }
6661 // For MMAP NO IRQ, allow conversions in ADSP
6662 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6663 goto error_open;
6664 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006665 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006666 goto error_open;
6667 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006668
6669 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6670 config->sample_rate = req_sample_rate;
6671 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6672 config->channel_mask = req_channel_mask;
6673 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6674 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006675 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006676
6677 out->sample_rate = config->sample_rate;
6678 out->channel_mask = config->channel_mask;
6679 out->format = config->format;
6680 if (is_hdmi) {
6681 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6682 out->config = pcm_config_hdmi_multi;
6683 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6684 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6685 out->config = pcm_config_mmap_playback;
6686 out->stream.start = out_start;
6687 out->stream.stop = out_stop;
6688 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6689 out->stream.get_mmap_position = out_get_mmap_position;
6690 } else {
6691 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6692 out->config = pcm_config_hifi;
6693 }
6694
6695 out->config.rate = out->sample_rate;
6696 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6697 if (is_hdmi) {
6698 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6699 audio_bytes_per_sample(out->format));
6700 }
6701 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006702 }
6703
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006704 /* Check for VOIP usecase */
6705 if(out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) {
6706 if (!voice_extn_is_compress_voip_supported()) {
6707 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6708 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006709 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006710 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6711 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006712
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006713 out->config = default_pcm_config_voip_copp;
6714 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6715 out->config.rate = out->sample_rate;
6716 }
6717 } else {
6718 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6719 voice_extn_compress_voip_is_active(out->dev)) &&
6720 (voice_extn_compress_voip_is_config_supported(config))) {
6721 ret = voice_extn_compress_voip_open_output_stream(out);
6722 if (ret != 0) {
6723 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6724 __func__, ret);
6725 goto error_open;
6726 }
6727 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006728 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006729 } else if (audio_is_linear_pcm(out->format) &&
6730 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6731 out->channel_mask = config->channel_mask;
6732 out->sample_rate = config->sample_rate;
6733 out->format = config->format;
6734 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6735 // does this change?
6736 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6737 out->config.rate = config->sample_rate;
6738 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6739 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6740 audio_bytes_per_sample(config->format));
6741 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006742 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306743 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306744 pthread_mutex_lock(&adev->lock);
6745 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6746 pthread_mutex_unlock(&adev->lock);
6747
6748 // reject offload during card offline to allow
6749 // fallback to s/w paths
6750 if (offline) {
6751 ret = -ENODEV;
6752 goto error_open;
6753 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006754
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006755 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6756 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6757 ALOGE("%s: Unsupported Offload information", __func__);
6758 ret = -EINVAL;
6759 goto error_open;
6760 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006761
Atul Khare3fa6e542017-08-09 00:56:17 +05306762 if (config->offload_info.format == 0)
6763 config->offload_info.format = config->format;
6764 if (config->offload_info.sample_rate == 0)
6765 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006766
Mingming Yin90310102013-11-13 16:57:00 -08006767 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306768 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006769 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006770 ret = -EINVAL;
6771 goto error_open;
6772 }
6773
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006774 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6775 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6776 (audio_extn_passthru_is_passthrough_stream(out)) &&
6777 !((config->sample_rate == 48000) ||
6778 (config->sample_rate == 96000) ||
6779 (config->sample_rate == 192000))) {
6780 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6781 __func__, config->sample_rate, config->offload_info.format);
6782 ret = -EINVAL;
6783 goto error_open;
6784 }
6785
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006786 out->compr_config.codec = (struct snd_codec *)
6787 calloc(1, sizeof(struct snd_codec));
6788
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006789 if (!out->compr_config.codec) {
6790 ret = -ENOMEM;
6791 goto error_open;
6792 }
6793
Dhananjay Kumarac341582017-02-23 23:42:25 +05306794 out->stream.pause = out_pause;
6795 out->stream.resume = out_resume;
6796 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306797 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306798 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006799 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306800 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006801 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306802 } else {
6803 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6804 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006805 }
vivek mehta446c3962015-09-14 10:57:35 -07006806
6807 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006808 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6809 config->format == 0 && config->sample_rate == 0 &&
6810 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006811 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006812 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6813 } else {
6814 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6815 ret = -EEXIST;
6816 goto error_open;
6817 }
vivek mehta446c3962015-09-14 10:57:35 -07006818 }
6819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006820 if (config->offload_info.channel_mask)
6821 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006822 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006823 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006824 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006825 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306826 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006827 ret = -EINVAL;
6828 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006829 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006830
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006831 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006832 out->sample_rate = config->offload_info.sample_rate;
6833
Mingming Yin3ee55c62014-08-04 14:23:35 -07006834 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006835
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306836 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306837 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306838 audio_extn_dolby_send_ddp_endp_params(adev);
6839 audio_extn_dolby_set_dmid(adev);
6840 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006842 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006843 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006844 out->compr_config.codec->bit_rate =
6845 config->offload_info.bit_rate;
6846 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306847 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006848 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306849 /* Update bit width only for non passthrough usecases.
6850 * For passthrough usecases, the output will always be opened @16 bit
6851 */
6852 if (!audio_extn_passthru_is_passthrough_stream(out))
6853 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306854
6855 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6856 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6857 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6858
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006859 /*TODO: Do we need to change it for passthrough */
6860 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006861
Manish Dewangana6fc5442015-08-24 20:30:31 +05306862 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6863 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306864 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306865 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306866 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6867 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306868
6869 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6870 AUDIO_FORMAT_PCM) {
6871
6872 /*Based on platform support, configure appropriate alsa format for corresponding
6873 *hal input format.
6874 */
6875 out->compr_config.codec->format = hal_format_to_alsa(
6876 config->offload_info.format);
6877
Ashish Jain83a6cc22016-06-28 14:34:17 +05306878 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306879 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306880 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306881
Dhananjay Kumarac341582017-02-23 23:42:25 +05306882 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306883 *hal input format and alsa format might differ based on platform support.
6884 */
6885 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306886 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306887
6888 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6889
6890 /* Check if alsa session is configured with the same format as HAL input format,
6891 * if not then derive correct fragment size needed to accomodate the
6892 * conversion of HAL input format to alsa format.
6893 */
6894 audio_extn_utils_update_direct_pcm_fragment_size(out);
6895
6896 /*if hal input and output fragment size is different this indicates HAL input format is
6897 *not same as the alsa format
6898 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306899 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306900 /*Allocate a buffer to convert input data to the alsa configured format.
6901 *size of convert buffer is equal to the size required to hold one fragment size
6902 *worth of pcm data, this is because flinger does not write more than fragment_size
6903 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306904 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6905 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306906 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6907 ret = -ENOMEM;
6908 goto error_open;
6909 }
6910 }
6911 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6912 out->compr_config.fragment_size =
6913 audio_extn_passthru_get_buffer_size(&config->offload_info);
6914 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6915 } else {
6916 out->compr_config.fragment_size =
6917 platform_get_compress_offload_buffer_size(&config->offload_info);
6918 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6919 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006920
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306921 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6922 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6923 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006924 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306925 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006926
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306927 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6928 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6929 }
6930
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006931 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6932 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006933
Manish Dewangan69426c82017-01-30 17:35:36 +05306934 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6935 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6936 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6937 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6938 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6939 } else {
6940 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6941 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006942
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306943 memset(&out->channel_map_param, 0,
6944 sizeof(struct audio_out_channel_map_param));
6945
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006946 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306947 out->send_next_track_params = false;
6948 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006949 out->offload_state = OFFLOAD_STATE_IDLE;
6950 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006951 out->writeAt.tv_sec = 0;
6952 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006953
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006954 audio_extn_dts_create_state_notifier_node(out->usecase);
6955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006956 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6957 __func__, config->offload_info.version,
6958 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306959
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306960 /* Check if DSD audio format is supported in codec
6961 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306962 */
6963
6964 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306965 (!platform_check_codec_dsd_support(adev->platform) ||
6966 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306967 ret = -EINVAL;
6968 goto error_open;
6969 }
6970
Ashish Jain5106d362016-05-11 19:23:33 +05306971 /* Disable gapless if any of the following is true
6972 * passthrough playback
6973 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306974 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306975 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306976 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306977 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006978 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306979 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306980 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306981 check_and_set_gapless_mode(adev, false);
6982 } else
6983 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006984
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306985 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006986 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6987 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306988 if (config->format == AUDIO_FORMAT_DSD) {
6989 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6990 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6991 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006992
6993 create_offload_callback_thread(out);
6994
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006995 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006996 switch (config->sample_rate) {
6997 case 0:
6998 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6999 break;
7000 case 8000:
7001 case 16000:
7002 case 48000:
7003 out->sample_rate = config->sample_rate;
7004 break;
7005 default:
7006 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7007 config->sample_rate);
7008 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7009 ret = -EINVAL;
7010 goto error_open;
7011 }
7012 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7013 switch (config->channel_mask) {
7014 case AUDIO_CHANNEL_NONE:
7015 case AUDIO_CHANNEL_OUT_STEREO:
7016 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7017 break;
7018 default:
7019 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7020 config->channel_mask);
7021 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7022 ret = -EINVAL;
7023 goto error_open;
7024 }
7025 switch (config->format) {
7026 case AUDIO_FORMAT_DEFAULT:
7027 case AUDIO_FORMAT_PCM_16_BIT:
7028 out->format = AUDIO_FORMAT_PCM_16_BIT;
7029 break;
7030 default:
7031 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7032 config->format);
7033 config->format = AUDIO_FORMAT_PCM_16_BIT;
7034 ret = -EINVAL;
7035 goto error_open;
7036 }
7037
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307038 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007039 if (ret != 0) {
7040 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007041 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007042 goto error_open;
7043 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007044 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007045 switch (config->sample_rate) {
7046 case 0:
7047 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7048 break;
7049 case 8000:
7050 case 16000:
7051 case 48000:
7052 out->sample_rate = config->sample_rate;
7053 break;
7054 default:
7055 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7056 config->sample_rate);
7057 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7058 ret = -EINVAL;
7059 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007060 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007061 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7062 switch (config->channel_mask) {
7063 case AUDIO_CHANNEL_NONE:
7064 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7065 break;
7066 case AUDIO_CHANNEL_OUT_STEREO:
7067 out->channel_mask = config->channel_mask;
7068 break;
7069 default:
7070 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7071 config->channel_mask);
7072 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7073 ret = -EINVAL;
7074 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007075 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007076 switch (config->format) {
7077 case AUDIO_FORMAT_DEFAULT:
7078 out->format = AUDIO_FORMAT_PCM_16_BIT;
7079 break;
7080 case AUDIO_FORMAT_PCM_16_BIT:
7081 out->format = config->format;
7082 break;
7083 default:
7084 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7085 config->format);
7086 config->format = AUDIO_FORMAT_PCM_16_BIT;
7087 ret = -EINVAL;
7088 break;
7089 }
7090 if (ret != 0)
7091 goto error_open;
7092
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007093 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7094 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007095 out->config.rate = out->sample_rate;
7096 out->config.channels =
7097 audio_channel_count_from_out_mask(out->channel_mask);
7098 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007099 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007100 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307101 unsigned int channels = 0;
7102 /*Update config params to default if not set by the caller*/
7103 if (config->sample_rate == 0)
7104 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7105 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7106 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7107 if (config->format == AUDIO_FORMAT_DEFAULT)
7108 config->format = AUDIO_FORMAT_PCM_16_BIT;
7109
7110 channels = audio_channel_count_from_out_mask(out->channel_mask);
7111
Varun Balaraje49253e2017-07-06 19:48:56 +05307112 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7113 out->usecase = get_interactive_usecase(adev);
7114 out->config = pcm_config_low_latency;
7115 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307116 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007117 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7118 out->flags);
7119 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007120 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7121 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7122 out->config = pcm_config_mmap_playback;
7123 out->stream.start = out_start;
7124 out->stream.stop = out_stop;
7125 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7126 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307127 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7128 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007129 out->hal_output_suspend_supported =
7130 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7131 out->dynamic_pm_qos_config_supported =
7132 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7133 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007134 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7135 } else {
7136 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7137 //the mixer path will be a string similar to "low-latency-playback resume"
7138 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7139 strlcat(out->pm_qos_mixer_path,
7140 " resume", MAX_MIXER_PATH_LEN);
7141 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7142 out->pm_qos_mixer_path);
7143 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307144 out->config = pcm_config_low_latency;
7145 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7146 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7147 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307148 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7149 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7150 if (out->config.period_size <= 0) {
7151 ALOGE("Invalid configuration period size is not valid");
7152 ret = -EINVAL;
7153 goto error_open;
7154 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007155 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7156 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7157 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007158 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7159 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7160 out->config = pcm_config_haptics_audio;
7161 if (force_haptic_path)
7162 adev->haptics_config = pcm_config_haptics_audio;
7163 else
7164 adev->haptics_config = pcm_config_haptics;
7165
7166 out->config.channels =
7167 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7168
7169 if (force_haptic_path) {
7170 out->config.channels = 1;
7171 adev->haptics_config.channels = 1;
7172 } else
7173 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307174 } else {
7175 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007176 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7177 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307178 }
7179 out->hal_ip_format = format = out->format;
7180 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7181 out->hal_op_format = pcm_format_to_hal(out->config.format);
7182 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7183 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007184 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307185 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307186 if (out->hal_ip_format != out->hal_op_format) {
7187 uint32_t buffer_size = out->config.period_size *
7188 format_to_bitwidth_table[out->hal_op_format] *
7189 out->config.channels;
7190 out->convert_buffer = calloc(1, buffer_size);
7191 if (out->convert_buffer == NULL){
7192 ALOGE("Allocation failed for convert buffer for size %d",
7193 out->compr_config.fragment_size);
7194 ret = -ENOMEM;
7195 goto error_open;
7196 }
7197 ALOGD("Convert buffer allocated of size %d", buffer_size);
7198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199 }
7200
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007201 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7202 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307203
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007204 /* TODO remove this hardcoding and check why width is zero*/
7205 if (out->bit_width == 0)
7206 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307207 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007208 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007209 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307210 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307211 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007212 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007213 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7214 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007215 if(adev->primary_output == NULL)
7216 adev->primary_output = out;
7217 else {
7218 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007219 ret = -EEXIST;
7220 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007221 }
7222 }
7223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 /* Check if this usecase is already existing */
7225 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007226 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7227 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007228 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007229 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007230 ret = -EEXIST;
7231 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007232 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007234 pthread_mutex_unlock(&adev->lock);
7235
7236 out->stream.common.get_sample_rate = out_get_sample_rate;
7237 out->stream.common.set_sample_rate = out_set_sample_rate;
7238 out->stream.common.get_buffer_size = out_get_buffer_size;
7239 out->stream.common.get_channels = out_get_channels;
7240 out->stream.common.get_format = out_get_format;
7241 out->stream.common.set_format = out_set_format;
7242 out->stream.common.standby = out_standby;
7243 out->stream.common.dump = out_dump;
7244 out->stream.common.set_parameters = out_set_parameters;
7245 out->stream.common.get_parameters = out_get_parameters;
7246 out->stream.common.add_audio_effect = out_add_audio_effect;
7247 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7248 out->stream.get_latency = out_get_latency;
7249 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007250#ifdef NO_AUDIO_OUT
7251 out->stream.write = out_write_for_no_output;
7252#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007253 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007254#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007255 out->stream.get_render_position = out_get_render_position;
7256 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007257 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007258
Haynes Mathew George16081042017-05-31 17:16:49 -07007259 if (out->realtime)
7260 out->af_period_multiplier = af_period_multiplier;
7261 else
7262 out->af_period_multiplier = 1;
7263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007264 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007265 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007266 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007267
7268 config->format = out->stream.common.get_format(&out->stream.common);
7269 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7270 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307271 register_format(out->format, out->supported_formats);
7272 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7273 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007274
Aalique Grahame22e49102018-12-18 14:23:57 -08007275 out->error_log = error_log_create(
7276 ERROR_LOG_ENTRIES,
7277 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7278
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307279 /*
7280 By locking output stream before registering, we allow the callback
7281 to update stream's state only after stream's initial state is set to
7282 adev state.
7283 */
7284 lock_output_stream(out);
7285 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7286 pthread_mutex_lock(&adev->lock);
7287 out->card_status = adev->card_status;
7288 pthread_mutex_unlock(&adev->lock);
7289 pthread_mutex_unlock(&out->lock);
7290
Aalique Grahame22e49102018-12-18 14:23:57 -08007291 stream_app_type_cfg_init(&out->app_type_cfg);
7292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007293 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307294 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007295 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007296
7297 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7298 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7299 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007300 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307301 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007302 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007303 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307304 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007305 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7306 out->usecase, PCM_PLAYBACK);
7307 hdlr_stream_cfg.flags = out->flags;
7308 hdlr_stream_cfg.type = PCM_PLAYBACK;
7309 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7310 &hdlr_stream_cfg);
7311 if (ret) {
7312 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7313 out->adsp_hdlr_stream_handle = NULL;
7314 }
7315 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307316 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007317 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007318 if (ret < 0) {
7319 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7320 out->ip_hdlr_handle = NULL;
7321 }
7322 }
Derek Chenf939fb72018-11-13 13:34:41 -08007323
7324 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7325 calloc(1, sizeof(streams_output_ctxt_t));
7326 if (out_ctxt == NULL) {
7327 ALOGE("%s fail to allocate output ctxt", __func__);
7328 ret = -ENOMEM;
7329 goto error_open;
7330 }
7331 out_ctxt->output = out;
7332
7333 pthread_mutex_lock(&adev->lock);
7334 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7335 pthread_mutex_unlock(&adev->lock);
7336
Eric Laurent994a6932013-07-17 11:51:42 -07007337 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007338 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007339
7340error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307341 if (out->convert_buffer)
7342 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007343 free(out);
7344 *stream_out = NULL;
7345 ALOGD("%s: exit: ret %d", __func__, ret);
7346 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007347}
7348
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307349void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007350 struct audio_stream_out *stream)
7351{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007352 struct stream_out *out = (struct stream_out *)stream;
7353 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007354 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007355
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007356 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307357
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307358 // must deregister from sndmonitor first to prevent races
7359 // between the callback and close_stream
7360 audio_extn_snd_mon_unregister_listener(out);
7361
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007362 /* close adsp hdrl session before standby */
7363 if (out->adsp_hdlr_stream_handle) {
7364 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7365 if (ret)
7366 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7367 out->adsp_hdlr_stream_handle = NULL;
7368 }
7369
Manish Dewangan21a850a2017-08-14 12:03:55 +05307370 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007371 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7372 out->ip_hdlr_handle = NULL;
7373 }
7374
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007375 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307376 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007377 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307378 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307379 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007380 if(ret != 0)
7381 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7382 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007383 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007384 out_standby(&stream->common);
7385
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007386 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007387 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007388 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007389 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007390 if (out->compr_config.codec != NULL)
7391 free(out->compr_config.codec);
7392 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007393
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307394 out->a2dp_compress_mute = false;
7395
Varun Balaraje49253e2017-07-06 19:48:56 +05307396 if (is_interactive_usecase(out->usecase))
7397 free_interactive_usecase(adev, out->usecase);
7398
Ashish Jain83a6cc22016-06-28 14:34:17 +05307399 if (out->convert_buffer != NULL) {
7400 free(out->convert_buffer);
7401 out->convert_buffer = NULL;
7402 }
7403
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007404 if (adev->voice_tx_output == out)
7405 adev->voice_tx_output = NULL;
7406
Aalique Grahame22e49102018-12-18 14:23:57 -08007407 error_log_destroy(out->error_log);
7408 out->error_log = NULL;
7409
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307410 if (adev->primary_output == out)
7411 adev->primary_output = NULL;
7412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007413 pthread_cond_destroy(&out->cond);
7414 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007415
7416 pthread_mutex_lock(&adev->lock);
7417 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7418 if (out_ctxt != NULL) {
7419 list_remove(&out_ctxt->list);
7420 free(out_ctxt);
7421 } else {
7422 ALOGW("%s, output stream already closed", __func__);
7423 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007424 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007425 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007426 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007427}
7428
7429static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7430{
7431 struct audio_device *adev = (struct audio_device *)dev;
7432 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007433 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007434 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007435 int ret;
7436 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007437 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007438
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007439 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007440 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007441
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307442 if (!parms)
7443 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307444
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307445 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7446 if (ret >= 0) {
7447 /* When set to false, HAL should disable EC and NS */
7448 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7449 adev->bt_sco_on = true;
7450 else
7451 adev->bt_sco_on = false;
7452 }
7453
Naresh Tanniru4c630392014-05-12 01:05:52 +05307454 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007455 status = voice_set_parameters(adev, parms);
7456 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007457 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007458
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007459 status = platform_set_parameters(adev->platform, parms);
7460 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007461 goto done;
7462
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007463 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7464 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007465 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007466 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7467 adev->bluetooth_nrec = true;
7468 else
7469 adev->bluetooth_nrec = false;
7470 }
7471
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007472 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7473 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007474 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7475 adev->screen_off = false;
7476 else
7477 adev->screen_off = true;
7478 }
7479
Aalique Grahame22e49102018-12-18 14:23:57 -08007480#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007481 ret = str_parms_get_int(parms, "rotation", &val);
7482 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007483 bool reverse_speakers = false;
7484 switch(val) {
7485 // FIXME: note that the code below assumes that the speakers are in the correct placement
7486 // relative to the user when the device is rotated 90deg from its default rotation. This
7487 // assumption is device-specific, not platform-specific like this code.
7488 case 270:
7489 reverse_speakers = true;
7490 break;
7491 case 0:
7492 case 90:
7493 case 180:
7494 break;
7495 default:
7496 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007497 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007498 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007499 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007500 // check and set swap
7501 // - check if orientation changed and speaker active
7502 // - set rotation and cache the rotation value
7503 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007504 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007505 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007506#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007507
Mingming Yin514a8bc2014-07-29 15:22:21 -07007508 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7509 if (ret >= 0) {
7510 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7511 adev->bt_wb_speech_enabled = true;
7512 else
7513 adev->bt_wb_speech_enabled = false;
7514 }
7515
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7517 if (ret >= 0) {
7518 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307519 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007520 if (audio_is_output_device(val) &&
7521 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007522 ALOGV("cache new ext disp type and edid");
7523 ret = platform_get_ext_disp_type(adev->platform);
7524 if (ret < 0) {
7525 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307526 } else {
7527 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007528 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307529 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007530 /*
7531 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7532 * Per AudioPolicyManager, USB device is higher priority than WFD.
7533 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7534 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7535 * starting voice call on USB
7536 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007537 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307538 if (ret >= 0)
7539 audio_extn_usb_add_device(device, atoi(value));
7540
Zhou Song6f862822017-11-06 17:27:57 +08007541 if (!audio_extn_usb_is_tunnel_supported()) {
7542 ALOGV("detected USB connect .. disable proxy");
7543 adev->allow_afe_proxy_usage = false;
7544 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007545 }
7546 }
7547
7548 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7549 if (ret >= 0) {
7550 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307551 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007552 /*
7553 * The HDMI / Displayport disconnect handling has been moved to
7554 * audio extension to ensure that its parameters are not
7555 * invalidated prior to updating sysfs of the disconnect event
7556 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7557 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307558 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007559 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307560 if (ret >= 0)
7561 audio_extn_usb_remove_device(device, atoi(value));
7562
Zhou Song6f862822017-11-06 17:27:57 +08007563 if (!audio_extn_usb_is_tunnel_supported()) {
7564 ALOGV("detected USB disconnect .. enable proxy");
7565 adev->allow_afe_proxy_usage = true;
7566 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007567 }
7568 }
7569
Aalique Grahame22e49102018-12-18 14:23:57 -08007570 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007571 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007572
7573 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007574 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307575 struct audio_usecase *usecase;
7576 struct listnode *node;
7577 list_for_each(node, &adev->usecase_list) {
7578 usecase = node_to_item(node, struct audio_usecase, list);
7579 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007580 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307581 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007582
7583 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307584 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007585 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307586 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307587 //force device switch to re configure encoder
7588 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307589 audio_extn_a2dp_set_handoff_mode(false);
7590 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307591 break;
7592 }
7593 }
7594 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007595
7596 //handle vr audio setparam
7597 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7598 value, sizeof(value));
7599 if (ret >= 0) {
7600 ALOGI("Setting vr mode to be %s", value);
7601 if (!strncmp(value, "true", 4)) {
7602 adev->vr_audio_mode_enabled = true;
7603 ALOGI("Setting vr mode to true");
7604 } else if (!strncmp(value, "false", 5)) {
7605 adev->vr_audio_mode_enabled = false;
7606 ALOGI("Setting vr mode to false");
7607 } else {
7608 ALOGI("wrong vr mode set");
7609 }
7610 }
7611
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307612 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007613done:
7614 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007615 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307616error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007617 ALOGV("%s: exit with code(%d)", __func__, status);
7618 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007619}
7620
7621static char* adev_get_parameters(const struct audio_hw_device *dev,
7622 const char *keys)
7623{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307624 ALOGD("%s:%s", __func__, keys);
7625
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007626 struct audio_device *adev = (struct audio_device *)dev;
7627 struct str_parms *reply = str_parms_create();
7628 struct str_parms *query = str_parms_create_str(keys);
7629 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307630 char value[256] = {0};
7631 int ret = 0;
7632
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007633 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007634 if (reply) {
7635 str_parms_destroy(reply);
7636 }
7637 if (query) {
7638 str_parms_destroy(query);
7639 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007640 ALOGE("adev_get_parameters: failed to create query or reply");
7641 return NULL;
7642 }
7643
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007644 //handle vr audio getparam
7645
7646 ret = str_parms_get_str(query,
7647 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7648 value, sizeof(value));
7649
7650 if (ret >= 0) {
7651 bool vr_audio_enabled = false;
7652 pthread_mutex_lock(&adev->lock);
7653 vr_audio_enabled = adev->vr_audio_mode_enabled;
7654 pthread_mutex_unlock(&adev->lock);
7655
7656 ALOGI("getting vr mode to %d", vr_audio_enabled);
7657
7658 if (vr_audio_enabled) {
7659 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7660 "true");
7661 goto exit;
7662 } else {
7663 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7664 "false");
7665 goto exit;
7666 }
7667 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007668
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007669 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007670 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007671 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007672 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007673 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307674 pthread_mutex_unlock(&adev->lock);
7675
Naresh Tannirud7205b62014-06-20 02:54:48 +05307676exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007677 str = str_parms_to_str(reply);
7678 str_parms_destroy(query);
7679 str_parms_destroy(reply);
7680
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307681 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007682 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007683}
7684
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007685static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007686{
7687 return 0;
7688}
7689
7690static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7691{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007692 int ret;
7693 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007694
7695 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7696
Haynes Mathew George5191a852013-09-11 14:19:36 -07007697 pthread_mutex_lock(&adev->lock);
7698 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007699 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007700 pthread_mutex_unlock(&adev->lock);
7701 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702}
7703
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007704static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7705 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007706{
7707 return -ENOSYS;
7708}
7709
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007710static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7711 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007712{
7713 return -ENOSYS;
7714}
7715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007716static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7717 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007718{
7719 return -ENOSYS;
7720}
7721
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007722static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7723 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007724{
7725 return -ENOSYS;
7726}
7727
7728static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7729{
7730 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007731 struct listnode *node;
7732 struct audio_usecase *usecase = NULL;
7733 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007734 pthread_mutex_lock(&adev->lock);
7735 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007736 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007737 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007738 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007739 list_for_each(node, &adev->usecase_list) {
7740 usecase = node_to_item(node, struct audio_usecase, list);
7741 if (usecase->type == VOICE_CALL)
7742 break;
7743 }
7744 if (usecase &&
7745 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7746 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7747 true);
7748 if (ret != 0) {
7749 /* default service interval was successfully updated,
7750 reopen USB backend with new service interval */
7751 check_usecases_codec_backend(adev,
7752 usecase,
7753 usecase->out_snd_device);
7754 }
7755 }
7756
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007757 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007758 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007759 adev->current_call_output = NULL;
7760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007761 }
7762 pthread_mutex_unlock(&adev->lock);
7763 return 0;
7764}
7765
7766static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7767{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007768 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007769 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007770
7771 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007772 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007773 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007774
Derek Chend2530072014-11-24 12:39:14 -08007775 if (adev->ext_hw_plugin)
7776 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007777
7778 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007779 pthread_mutex_unlock(&adev->lock);
7780
7781 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007782}
7783
7784static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7785{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007786 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007787 return 0;
7788}
7789
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007790static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007791 const struct audio_config *config)
7792{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007793 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007794
Aalique Grahame22e49102018-12-18 14:23:57 -08007795 /* Don't know if USB HIFI in this context so use true to be conservative */
7796 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7797 true /*is_usb_hifi */) != 0)
7798 return 0;
7799
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007800 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7801 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007802}
7803
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007804static bool adev_input_allow_hifi_record(struct audio_device *adev,
7805 audio_devices_t devices,
7806 audio_input_flags_t flags,
7807 audio_source_t source) {
7808 const bool allowed = true;
7809
7810 if (!audio_is_usb_in_device(devices))
7811 return !allowed;
7812
7813 switch (flags) {
7814 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007815 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007816 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7817 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007818 default:
7819 return !allowed;
7820 }
7821
7822 switch (source) {
7823 case AUDIO_SOURCE_DEFAULT:
7824 case AUDIO_SOURCE_MIC:
7825 case AUDIO_SOURCE_UNPROCESSED:
7826 break;
7827 default:
7828 return !allowed;
7829 }
7830
7831 switch (adev->mode) {
7832 case 0:
7833 break;
7834 default:
7835 return !allowed;
7836 }
7837
7838 return allowed;
7839}
7840
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007841static int adev_update_voice_comm_input_stream(struct stream_in *in,
7842 struct audio_config *config)
7843{
7844 bool valid_rate = (config->sample_rate == 8000 ||
7845 config->sample_rate == 16000 ||
7846 config->sample_rate == 32000 ||
7847 config->sample_rate == 48000);
7848 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7849
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007850 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08007851 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007852 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7853 in->config = default_pcm_config_voip_copp;
7854 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7855 DEFAULT_VOIP_BUF_DURATION_MS,
7856 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007857 } else {
7858 ALOGW("%s No valid input in voip, use defaults"
7859 "sample rate %u, channel mask 0x%X",
7860 __func__, config->sample_rate, in->channel_mask);
7861 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007862 in->config.rate = config->sample_rate;
7863 in->sample_rate = config->sample_rate;
7864 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007865 //XXX needed for voice_extn_compress_voip_open_input_stream
7866 in->config.rate = config->sample_rate;
7867 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7868 voice_extn_compress_voip_is_active(in->dev)) &&
7869 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7870 valid_rate && valid_ch) {
7871 voice_extn_compress_voip_open_input_stream(in);
7872 // update rate entries to match config from AF
7873 in->config.rate = config->sample_rate;
7874 in->sample_rate = config->sample_rate;
7875 } else {
7876 ALOGW("%s compress voip not active, use defaults", __func__);
7877 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007878 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007879 return 0;
7880}
7881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007882static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007883 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007884 audio_devices_t devices,
7885 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007886 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307887 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007888 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007889 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007890{
7891 struct audio_device *adev = (struct audio_device *)dev;
7892 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007893 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007894 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007895 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307896 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007897 bool is_usb_dev = audio_is_usb_in_device(devices);
7898 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7899 devices,
7900 flags,
7901 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307902
kunleizdff872d2018-08-20 14:40:33 +08007903 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007904 is_usb_dev = false;
7905 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7906 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7907 __func__, devices);
7908 }
7909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007910 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007911
7912 if (!(is_usb_dev && may_use_hifi_record)) {
7913 if (config->sample_rate == 0)
7914 config->sample_rate = 48000;
7915 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7916 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7917 if (config->format == AUDIO_FORMAT_DEFAULT)
7918 config->format = AUDIO_FORMAT_PCM_16_BIT;
7919
7920 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7921
Aalique Grahame22e49102018-12-18 14:23:57 -08007922 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7923 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007924 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007926
7927 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007928
7929 if (!in) {
7930 ALOGE("failed to allocate input stream");
7931 return -ENOMEM;
7932 }
7933
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307934 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307935 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7936 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007937 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007938 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007940 in->stream.common.get_sample_rate = in_get_sample_rate;
7941 in->stream.common.set_sample_rate = in_set_sample_rate;
7942 in->stream.common.get_buffer_size = in_get_buffer_size;
7943 in->stream.common.get_channels = in_get_channels;
7944 in->stream.common.get_format = in_get_format;
7945 in->stream.common.set_format = in_set_format;
7946 in->stream.common.standby = in_standby;
7947 in->stream.common.dump = in_dump;
7948 in->stream.common.set_parameters = in_set_parameters;
7949 in->stream.common.get_parameters = in_get_parameters;
7950 in->stream.common.add_audio_effect = in_add_audio_effect;
7951 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7952 in->stream.set_gain = in_set_gain;
7953 in->stream.read = in_read;
7954 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08007955 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307956 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007957
7958 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007959 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007960 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007961 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007962 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007963 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007964 in->bit_width = 16;
7965 in->af_period_multiplier = 1;
7966
Aalique Grahame22e49102018-12-18 14:23:57 -08007967 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
7968 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
7969 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
7970 /* Force channel config requested to mono if incall
7971 record is being requested for only uplink/downlink */
7972 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
7973 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7974 ret = -EINVAL;
7975 goto err_open;
7976 }
7977 }
7978
Haynes Mathew George46740472017-10-27 18:40:12 -07007979 /* Update config params with the requested sample rate and channels */
7980 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7981 (adev->mode != AUDIO_MODE_IN_CALL)) {
7982 ret = -EINVAL;
7983 goto err_open;
7984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007985
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007986 if (is_usb_dev && may_use_hifi_record) {
7987 /* HiFi record selects an appropriate format, channel, rate combo
7988 depending on sink capabilities*/
7989 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7990 &config->format,
7991 &in->supported_formats[0],
7992 MAX_SUPPORTED_FORMATS,
7993 &config->channel_mask,
7994 &in->supported_channel_masks[0],
7995 MAX_SUPPORTED_CHANNEL_MASKS,
7996 &config->sample_rate,
7997 &in->supported_sample_rates[0],
7998 MAX_SUPPORTED_SAMPLE_RATES);
7999 if (ret != 0) {
8000 ret = -EINVAL;
8001 goto err_open;
8002 }
8003 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008004 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308005 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308006 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8007 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8008 in->config.format = PCM_FORMAT_S32_LE;
8009 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308010 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8011 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8012 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8013 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8014 bool ret_error = false;
8015 in->bit_width = 24;
8016 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8017 from HAL is 24_packed and 8_24
8018 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8019 24_packed return error indicating supported format is 24_packed
8020 *> In case of any other source requesting 24 bit or float return error
8021 indicating format supported is 16 bit only.
8022
8023 on error flinger will retry with supported format passed
8024 */
8025 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8026 (source != AUDIO_SOURCE_CAMCORDER)) {
8027 config->format = AUDIO_FORMAT_PCM_16_BIT;
8028 if (config->sample_rate > 48000)
8029 config->sample_rate = 48000;
8030 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008031 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8032 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308033 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8034 ret_error = true;
8035 }
8036
8037 if (ret_error) {
8038 ret = -EINVAL;
8039 goto err_open;
8040 }
8041 }
8042
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008043 in->channel_mask = config->channel_mask;
8044 in->format = config->format;
8045
8046 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308047
8048 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8049 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8050 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8051 else {
8052 ret = -EINVAL;
8053 goto err_open;
8054 }
8055 }
8056
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008057 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8058 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8059 is_low_latency = true;
8060#if LOW_LATENCY_CAPTURE_USE_CASE
8061 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8062#endif
8063 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008064 if (!in->realtime) {
8065 in->config = pcm_config_audio_capture;
8066 frame_size = audio_stream_in_frame_size(&in->stream);
8067 buffer_size = get_input_buffer_size(config->sample_rate,
8068 config->format,
8069 channel_count,
8070 is_low_latency);
8071 in->config.period_size = buffer_size / frame_size;
8072 in->config.rate = config->sample_rate;
8073 in->af_period_multiplier = 1;
8074 } else {
8075 // period size is left untouched for rt mode playback
8076 in->config = pcm_config_audio_capture_rt;
8077 in->af_period_multiplier = af_period_multiplier;
8078 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008079 }
8080
8081 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8082 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8083 in->realtime = 0;
8084 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8085 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008086 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08008087 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008088 in->stream.start = in_start;
8089 in->stream.stop = in_stop;
8090 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8091 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008092 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008093 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8094 } else if (in->realtime) {
8095 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008096 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008097 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008098 in->sample_rate = in->config.rate;
8099 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008100 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008101 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8102 in->config = pcm_config_audio_capture;
8103 frame_size = audio_stream_in_frame_size(&in->stream);
8104 buffer_size = get_input_buffer_size(config->sample_rate,
8105 config->format,
8106 channel_count,
8107 false /*is_low_latency*/);
8108 in->config.period_size = buffer_size / frame_size;
8109 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008110 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008111 switch (config->format) {
8112 case AUDIO_FORMAT_PCM_32_BIT:
8113 in->bit_width = 32;
8114 break;
8115 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8116 case AUDIO_FORMAT_PCM_8_24_BIT:
8117 in->bit_width = 24;
8118 break;
8119 default:
8120 in->bit_width = 16;
8121 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008122 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008123 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008124 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308125 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008126 if (config->sample_rate == 0)
8127 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8128 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8129 config->sample_rate != 8000) {
8130 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8131 ret = -EINVAL;
8132 goto err_open;
8133 }
8134 if (config->format == AUDIO_FORMAT_DEFAULT)
8135 config->format = AUDIO_FORMAT_PCM_16_BIT;
8136 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8137 config->format = AUDIO_FORMAT_PCM_16_BIT;
8138 ret = -EINVAL;
8139 goto err_open;
8140 }
8141
8142 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8143 in->config = pcm_config_afe_proxy_record;
8144 in->config.channels = channel_count;
8145 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308146 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008147 in->af_period_multiplier = 1;
8148 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8149 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8150 (config->sample_rate == 8000 ||
8151 config->sample_rate == 16000 ||
8152 config->sample_rate == 32000 ||
8153 config->sample_rate == 48000) &&
8154 channel_count == 1) {
8155 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8156 in->config = pcm_config_audio_capture;
8157 frame_size = audio_stream_in_frame_size(&in->stream);
8158 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8159 config->sample_rate,
8160 config->format,
8161 channel_count, false /*is_low_latency*/);
8162 in->config.period_size = buffer_size / frame_size;
8163 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8164 in->config.rate = config->sample_rate;
8165 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008166 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308167 int ret_val;
8168 pthread_mutex_lock(&adev->lock);
8169 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8170 in, config, &channel_mask_updated);
8171 pthread_mutex_unlock(&adev->lock);
8172
8173 if (!ret_val) {
8174 if (channel_mask_updated == true) {
8175 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8176 __func__, config->channel_mask);
8177 ret = -EINVAL;
8178 goto err_open;
8179 }
8180 ALOGD("%s: created multi-channel session succesfully",__func__);
8181 } else if (audio_extn_compr_cap_enabled() &&
8182 audio_extn_compr_cap_format_supported(config->format) &&
8183 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8184 audio_extn_compr_cap_init(in);
8185 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05308186 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05308187 ret = audio_extn_cin_configure_input_stream(in);
8188 if (ret)
8189 goto err_open;
8190 } else {
8191 in->config = pcm_config_audio_capture;
8192 in->config.rate = config->sample_rate;
8193 in->config.format = pcm_format_from_audio_format(config->format);
8194 in->config.channels = channel_count;
8195 in->sample_rate = config->sample_rate;
8196 in->format = config->format;
8197 frame_size = audio_stream_in_frame_size(&in->stream);
8198 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008199 config->format,
8200 channel_count,
8201 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008202 /* prevent division-by-zero */
8203 if (frame_size == 0) {
8204 ALOGE("%s: Error frame_size==0", __func__);
8205 ret = -EINVAL;
8206 goto err_open;
8207 }
8208
Revathi Uddarajud2634032017-12-07 14:42:34 +05308209 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008210 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008211
Revathi Uddarajud2634032017-12-07 14:42:34 +05308212 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8213 /* optionally use VOIP usecase depending on config(s) */
8214 ret = adev_update_voice_comm_input_stream(in, config);
8215 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008216
Revathi Uddarajud2634032017-12-07 14:42:34 +05308217 if (ret) {
8218 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8219 goto err_open;
8220 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008221 }
kunleiz28c73e72019-03-27 17:24:04 +08008222#ifdef CONCURRENT_CAPTURE_ENABLED
8223 /* Acquire lock to avoid two concurrent use cases initialized to
8224 same pcm record use case */
8225
8226 pthread_mutex_lock(&adev->lock);
8227 if (in->usecase == USECASE_AUDIO_RECORD) {
8228 if (!(adev->pcm_record_uc_state)) {
8229 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8230 adev->pcm_record_uc_state = 1;
8231 } else {
8232 /* Assign compress record use case for second record */
8233 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8234 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8235 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8236 }
8237 }
8238 pthread_mutex_unlock(&adev->lock);
8239#endif
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008240 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308241 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8242 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008243 devices, flags, in->format,
8244 in->sample_rate, in->bit_width,
8245 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308246 register_format(in->format, in->supported_formats);
8247 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8248 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308249
Aalique Grahame22e49102018-12-18 14:23:57 -08008250 in->error_log = error_log_create(
8251 ERROR_LOG_ENTRIES,
8252 1000000000 /* aggregate consecutive identical errors within one second */);
8253
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008254 /* This stream could be for sound trigger lab,
8255 get sound trigger pcm if present */
8256 audio_extn_sound_trigger_check_and_get_session(in);
8257
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308258 lock_input_stream(in);
8259 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8260 pthread_mutex_lock(&adev->lock);
8261 in->card_status = adev->card_status;
8262 pthread_mutex_unlock(&adev->lock);
8263 pthread_mutex_unlock(&in->lock);
8264
Aalique Grahame22e49102018-12-18 14:23:57 -08008265 stream_app_type_cfg_init(&in->app_type_cfg);
8266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008267 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008268
8269 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8270 calloc(1, sizeof(streams_input_ctxt_t));
8271 if (in_ctxt == NULL) {
8272 ALOGE("%s fail to allocate input ctxt", __func__);
8273 ret = -ENOMEM;
8274 goto err_open;
8275 }
8276 in_ctxt->input = in;
8277
8278 pthread_mutex_lock(&adev->lock);
8279 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8280 pthread_mutex_unlock(&adev->lock);
8281
Eric Laurent994a6932013-07-17 11:51:42 -07008282 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008283 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008284
8285err_open:
8286 free(in);
8287 *stream_in = NULL;
8288 return ret;
8289}
8290
8291static void adev_close_input_stream(struct audio_hw_device *dev,
8292 struct audio_stream_in *stream)
8293{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008294 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008295 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008296 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308297
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308298 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008299
kunleiz70e57612018-12-28 17:50:23 +08008300 /* must deregister from sndmonitor first to prevent races
8301 * between the callback and close_stream
8302 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308303 audio_extn_snd_mon_unregister_listener(stream);
8304
kunleiz70e57612018-12-28 17:50:23 +08008305 /* Disable echo reference if there are no active input, hfp call
8306 * and sound trigger while closing input stream
8307 */
8308 if (!adev->active_input &&
8309 !audio_extn_hfp_is_active(adev) &&
8310 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008311 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008312 else
8313 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308314
Aalique Grahame22e49102018-12-18 14:23:57 -08008315 error_log_destroy(in->error_log);
8316 in->error_log = NULL;
8317
Pallavid7c7a272018-01-16 11:22:55 +05308318 if (in == NULL) {
8319 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8320 return;
8321 }
8322
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008323 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308324 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008325 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308326 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008327 if (ret != 0)
8328 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8329 __func__, ret);
8330 } else
8331 in_standby(&stream->common);
8332
Revathi Uddarajud2634032017-12-07 14:42:34 +05308333 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308334 if (in->usecase == USECASE_AUDIO_RECORD) {
8335 adev->pcm_record_uc_state = 0;
8336 }
8337
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008338 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008339 audio_extn_ssr_deinit();
8340 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008341
Garmond Leunge2433c32017-09-28 21:51:22 -07008342 if (audio_extn_ffv_get_stream() == in) {
8343 audio_extn_ffv_stream_deinit();
8344 }
8345
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308346 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008347 audio_extn_compr_cap_format_supported(in->config.format))
8348 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308349
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308350 if (audio_extn_cin_attached_usecase(in->usecase))
8351 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008352
Mingming Yinfd7607b2016-01-22 12:48:44 -08008353 if (in->is_st_session) {
8354 ALOGV("%s: sound trigger pcm stop lab", __func__);
8355 audio_extn_sound_trigger_stop_lab(in);
8356 }
Derek Chenf939fb72018-11-13 13:34:41 -08008357 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8358 if (in_ctxt != NULL) {
8359 list_remove(&in_ctxt->list);
8360 free(in_ctxt);
8361 } else {
8362 ALOGW("%s, input stream already closed", __func__);
8363 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008364 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308365 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008366 return;
8367}
8368
Aalique Grahame22e49102018-12-18 14:23:57 -08008369/* verifies input and output devices and their capabilities.
8370 *
8371 * This verification is required when enabling extended bit-depth or
8372 * sampling rates, as not all qcom products support it.
8373 *
8374 * Suitable for calling only on initialization such as adev_open().
8375 * It fills the audio_device use_case_table[] array.
8376 *
8377 * Has a side-effect that it needs to configure audio routing / devices
8378 * in order to power up the devices and read the device parameters.
8379 * It does not acquire any hw device lock. Should restore the devices
8380 * back to "normal state" upon completion.
8381 */
8382static int adev_verify_devices(struct audio_device *adev)
8383{
8384 /* enumeration is a bit difficult because one really wants to pull
8385 * the use_case, device id, etc from the hidden pcm_device_table[].
8386 * In this case there are the following use cases and device ids.
8387 *
8388 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8389 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8390 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8391 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8392 * [USECASE_AUDIO_RECORD] = {0, 0},
8393 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8394 * [USECASE_VOICE_CALL] = {2, 2},
8395 *
8396 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8397 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8398 */
8399
8400 /* should be the usecases enabled in adev_open_input_stream() */
8401 static const int test_in_usecases[] = {
8402 USECASE_AUDIO_RECORD,
8403 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8404 };
8405 /* should be the usecases enabled in adev_open_output_stream()*/
8406 static const int test_out_usecases[] = {
8407 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8408 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8409 };
8410 static const usecase_type_t usecase_type_by_dir[] = {
8411 PCM_PLAYBACK,
8412 PCM_CAPTURE,
8413 };
8414 static const unsigned flags_by_dir[] = {
8415 PCM_OUT,
8416 PCM_IN,
8417 };
8418
8419 size_t i;
8420 unsigned dir;
8421 const unsigned card_id = adev->snd_card;
8422
8423 for (dir = 0; dir < 2; ++dir) {
8424 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8425 const unsigned flags_dir = flags_by_dir[dir];
8426 const size_t testsize =
8427 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8428 const int *testcases =
8429 dir ? test_in_usecases : test_out_usecases;
8430 const audio_devices_t audio_device =
8431 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8432
8433 for (i = 0; i < testsize; ++i) {
8434 const audio_usecase_t audio_usecase = testcases[i];
8435 int device_id;
8436 struct pcm_params **pparams;
8437 struct stream_out out;
8438 struct stream_in in;
8439 struct audio_usecase uc_info;
8440 int retval;
8441
8442 pparams = &adev->use_case_table[audio_usecase];
8443 pcm_params_free(*pparams); /* can accept null input */
8444 *pparams = NULL;
8445
8446 /* find the device ID for the use case (signed, for error) */
8447 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8448 if (device_id < 0)
8449 continue;
8450
8451 /* prepare structures for device probing */
8452 memset(&uc_info, 0, sizeof(uc_info));
8453 uc_info.id = audio_usecase;
8454 uc_info.type = usecase_type;
8455 if (dir) {
8456 adev->active_input = &in;
8457 memset(&in, 0, sizeof(in));
8458 in.device = audio_device;
8459 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8460 uc_info.stream.in = &in;
8461 } else {
8462 adev->active_input = NULL;
8463 }
8464 memset(&out, 0, sizeof(out));
8465 out.devices = audio_device; /* only field needed in select_devices */
8466 uc_info.stream.out = &out;
8467 uc_info.devices = audio_device;
8468 uc_info.in_snd_device = SND_DEVICE_NONE;
8469 uc_info.out_snd_device = SND_DEVICE_NONE;
8470 list_add_tail(&adev->usecase_list, &uc_info.list);
8471
8472 /* select device - similar to start_(in/out)put_stream() */
8473 retval = select_devices(adev, audio_usecase);
8474 if (retval >= 0) {
8475 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8476#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008477 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008478 if (*pparams) {
8479 ALOGV("%s: (%s) card %d device %d", __func__,
8480 dir ? "input" : "output", card_id, device_id);
8481 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8482 } else {
8483 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8484 }
8485#endif
8486 }
8487
8488 /* deselect device - similar to stop_(in/out)put_stream() */
8489 /* 1. Get and set stream specific mixer controls */
8490 retval = disable_audio_route(adev, &uc_info);
8491 /* 2. Disable the rx device */
8492 retval = disable_snd_device(adev,
8493 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8494 list_remove(&uc_info.list);
8495 }
8496 }
8497 adev->active_input = NULL; /* restore adev state */
8498 return 0;
8499}
8500
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308501int adev_create_audio_patch(struct audio_hw_device *dev,
8502 unsigned int num_sources,
8503 const struct audio_port_config *sources,
8504 unsigned int num_sinks,
8505 const struct audio_port_config *sinks,
8506 audio_patch_handle_t *handle)
8507{
Derek Chenf939fb72018-11-13 13:34:41 -08008508 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308509
Derek Chenf939fb72018-11-13 13:34:41 -08008510 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8511 num_sources,
8512 sources,
8513 num_sinks,
8514 sinks,
8515 handle);
8516 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8517 num_sources,
8518 sources,
8519 num_sinks,
8520 sinks,
8521 handle);
8522 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308523}
8524
8525int adev_release_audio_patch(struct audio_hw_device *dev,
8526 audio_patch_handle_t handle)
8527{
Derek Chenf939fb72018-11-13 13:34:41 -08008528 int ret;
8529
8530 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8531 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8532 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308533}
8534
8535int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8536{
8537 return audio_extn_hw_loopback_get_audio_port(dev, config);
8538}
8539
8540int adev_set_audio_port_config(struct audio_hw_device *dev,
8541 const struct audio_port_config *config)
8542{
8543 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8544}
8545
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008546static int adev_dump(const audio_hw_device_t *device __unused,
8547 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008548{
8549 return 0;
8550}
8551
8552static int adev_close(hw_device_t *device)
8553{
Aalique Grahame22e49102018-12-18 14:23:57 -08008554 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008555 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008556
8557 if (!adev)
8558 return 0;
8559
8560 pthread_mutex_lock(&adev_init_lock);
8561
8562 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308563 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008564 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008565 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008566 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008567 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308568 audio_extn_utils_release_streams_cfg_lists(
8569 &adev->streams_output_cfg_list,
8570 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308571 if (audio_extn_qaf_is_enabled())
8572 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008573 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008574 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008575 free(adev->snd_dev_ref_cnt);
8576 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008577 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8578 pcm_params_free(adev->use_case_table[i]);
8579 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008580 if (adev->adm_deinit)
8581 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308582 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008583 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308584 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308585 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008586 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308587 if (adev->device_cfg_params) {
8588 free(adev->device_cfg_params);
8589 adev->device_cfg_params = NULL;
8590 }
Derek Chend2530072014-11-24 12:39:14 -08008591 if(adev->ext_hw_plugin)
8592 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008593 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008594 free(device);
8595 adev = NULL;
8596 }
8597 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308598 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008599 return 0;
8600}
8601
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008602/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8603 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8604 * just that it _might_ work.
8605 */
8606static int period_size_is_plausible_for_low_latency(int period_size)
8607{
8608 switch (period_size) {
8609 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008610 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008611 case 240:
8612 case 320:
8613 case 480:
8614 return 1;
8615 default:
8616 return 0;
8617 }
8618}
8619
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308620static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8621{
8622 bool is_snd_card_status = false;
8623 bool is_ext_device_status = false;
8624 char value[32];
8625 int card = -1;
8626 card_status_t status;
8627
8628 if (cookie != adev || !parms)
8629 return;
8630
8631 if (!parse_snd_card_status(parms, &card, &status)) {
8632 is_snd_card_status = true;
8633 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8634 is_ext_device_status = true;
8635 } else {
8636 // not a valid event
8637 return;
8638 }
8639
8640 pthread_mutex_lock(&adev->lock);
8641 if (card == adev->snd_card || is_ext_device_status) {
8642 if (is_snd_card_status && adev->card_status != status) {
8643 adev->card_status = status;
8644 platform_snd_card_update(adev->platform, status);
8645 audio_extn_fm_set_parameters(adev, parms);
8646 } else if (is_ext_device_status) {
8647 platform_set_parameters(adev->platform, parms);
8648 }
8649 }
8650 pthread_mutex_unlock(&adev->lock);
8651 return;
8652}
8653
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308654/* out and adev lock held */
8655static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8656{
8657 struct audio_usecase *uc_info;
8658 float left_p;
8659 float right_p;
8660 audio_devices_t devices;
8661
8662 uc_info = get_usecase_from_list(adev, out->usecase);
8663 if (uc_info == NULL) {
8664 ALOGE("%s: Could not find the usecase (%d) in the list",
8665 __func__, out->usecase);
8666 return -EINVAL;
8667 }
8668
8669 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8670 out->usecase, use_case_table[out->usecase]);
8671
8672 if (restore) {
8673 // restore A2DP device for active usecases and unmute if required
8674 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8675 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8676 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8677 select_devices(adev, uc_info->id);
8678 pthread_mutex_lock(&out->compr_mute_lock);
8679 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8680 (out->a2dp_compress_mute)) {
8681 out->a2dp_compress_mute = false;
8682 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8683 }
8684 pthread_mutex_unlock(&out->compr_mute_lock);
8685 }
8686 } else {
8687 // mute compress stream if suspended
8688 pthread_mutex_lock(&out->compr_mute_lock);
8689 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8690 (!out->a2dp_compress_mute)) {
8691 if (!out->standby) {
8692 ALOGD("%s: selecting speaker and muting stream", __func__);
8693 devices = out->devices;
8694 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8695 left_p = out->volume_l;
8696 right_p = out->volume_r;
8697 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8698 compress_pause(out->compr);
8699 out_set_compr_volume(&out->stream, (float)0, (float)0);
8700 out->a2dp_compress_mute = true;
8701 select_devices(adev, out->usecase);
8702 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8703 compress_resume(out->compr);
8704 out->devices = devices;
8705 out->volume_l = left_p;
8706 out->volume_r = right_p;
8707 }
8708 }
8709 pthread_mutex_unlock(&out->compr_mute_lock);
8710 }
8711 ALOGV("%s: exit", __func__);
8712 return 0;
8713}
8714
8715int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8716{
8717 int ret = 0;
8718
8719 lock_output_stream(out);
8720 pthread_mutex_lock(&adev->lock);
8721
8722 ret = check_a2dp_restore_l(adev, out, restore);
8723
8724 pthread_mutex_unlock(&adev->lock);
8725 pthread_mutex_unlock(&out->lock);
8726 return ret;
8727}
8728
Haynes Mathew George01156f92018-04-13 15:29:54 -07008729void adev_on_battery_status_changed(bool charging)
8730{
8731 pthread_mutex_lock(&adev->lock);
8732 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8733 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008734 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008735 pthread_mutex_unlock(&adev->lock);
8736}
8737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008738static int adev_open(const hw_module_t *module, const char *name,
8739 hw_device_t **device)
8740{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308741 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008742 char value[PROPERTY_VALUE_MAX] = {0};
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308743
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008744 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008745 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8746
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008747 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008748 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008749 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008750 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008751 ALOGD("%s: returning existing instance of adev", __func__);
8752 ALOGD("%s: exit", __func__);
8753 pthread_mutex_unlock(&adev_init_lock);
8754 return 0;
8755 }
8756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008757 adev = calloc(1, sizeof(struct audio_device));
8758
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008759 if (!adev) {
8760 pthread_mutex_unlock(&adev_init_lock);
8761 return -ENOMEM;
8762 }
8763
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008764 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8765
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008766 // register audio ext hidl at the earliest
8767 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308768#ifdef DYNAMIC_LOG_ENABLED
8769 register_for_dynamic_logging("hal");
8770#endif
8771
Derek Chenf939fb72018-11-13 13:34:41 -08008772 /* default audio HAL major version */
8773 uint32_t maj_version = 2;
8774 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8775 maj_version = atoi(value);
8776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008777 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008778 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779 adev->device.common.module = (struct hw_module_t *)module;
8780 adev->device.common.close = adev_close;
8781
8782 adev->device.init_check = adev_init_check;
8783 adev->device.set_voice_volume = adev_set_voice_volume;
8784 adev->device.set_master_volume = adev_set_master_volume;
8785 adev->device.get_master_volume = adev_get_master_volume;
8786 adev->device.set_master_mute = adev_set_master_mute;
8787 adev->device.get_master_mute = adev_get_master_mute;
8788 adev->device.set_mode = adev_set_mode;
8789 adev->device.set_mic_mute = adev_set_mic_mute;
8790 adev->device.get_mic_mute = adev_get_mic_mute;
8791 adev->device.set_parameters = adev_set_parameters;
8792 adev->device.get_parameters = adev_get_parameters;
8793 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8794 adev->device.open_output_stream = adev_open_output_stream;
8795 adev->device.close_output_stream = adev_close_output_stream;
8796 adev->device.open_input_stream = adev_open_input_stream;
8797 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308798 adev->device.create_audio_patch = adev_create_audio_patch;
8799 adev->device.release_audio_patch = adev_release_audio_patch;
8800 adev->device.get_audio_port = adev_get_audio_port;
8801 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008802 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308803 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008804
8805 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008806 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008807 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008808 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008809 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008810 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008811 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008812 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308813 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008814 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008815 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008816 /* Init audio feature manager */
8817 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008818 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008819 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08008820 list_init(&adev->active_inputs_list);
8821 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008822 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008823 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308824 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308825 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308826 adev->perf_lock_opts[0] = 0x101;
8827 adev->perf_lock_opts[1] = 0x20E;
8828 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008829 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07008830 adev->enable_hfp = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008832 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008833 adev->platform = platform_init(adev);
8834 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008835 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008836 free(adev->snd_dev_ref_cnt);
8837 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008838 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008839 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8840 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008841 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008842 return -EINVAL;
8843 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008844
Aalique Grahame22e49102018-12-18 14:23:57 -08008845 adev->extspk = audio_extn_extspk_init(adev);
8846
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308847 if (audio_extn_qaf_is_enabled()) {
8848 ret = audio_extn_qaf_init(adev);
8849 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008850 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308851 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008852 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308853 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8854 *device = NULL;
8855 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308856 return ret;
8857 }
8858
8859 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8860 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8861 }
8862
Derek Chenae7b0342019-02-08 15:17:04 -08008863 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08008864 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8865
Eric Laurentc4aef752013-09-12 17:45:53 -07008866 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8867 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8868 if (adev->visualizer_lib == NULL) {
8869 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8870 } else {
8871 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8872 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008873 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008874 "visualizer_hal_start_output");
8875 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008876 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008877 "visualizer_hal_stop_output");
8878 }
8879 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308880 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008881 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008882 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008883 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308884 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008885 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008886
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008887 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8888 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8889 if (adev->offload_effects_lib == NULL) {
8890 ALOGE("%s: DLOPEN failed for %s", __func__,
8891 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8892 } else {
8893 ALOGV("%s: DLOPEN successful for %s", __func__,
8894 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8895 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308896 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008897 "offload_effects_bundle_hal_start_output");
8898 adev->offload_effects_stop_output =
8899 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8900 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008901 adev->offload_effects_set_hpx_state =
8902 (int (*)(bool))dlsym(adev->offload_effects_lib,
8903 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308904 adev->offload_effects_get_parameters =
8905 (void (*)(struct str_parms *, struct str_parms *))
8906 dlsym(adev->offload_effects_lib,
8907 "offload_effects_bundle_get_parameters");
8908 adev->offload_effects_set_parameters =
8909 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8910 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008911 }
8912 }
8913
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008914 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8915 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8916 if (adev->adm_lib == NULL) {
8917 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8918 } else {
8919 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8920 adev->adm_init = (adm_init_t)
8921 dlsym(adev->adm_lib, "adm_init");
8922 adev->adm_deinit = (adm_deinit_t)
8923 dlsym(adev->adm_lib, "adm_deinit");
8924 adev->adm_register_input_stream = (adm_register_input_stream_t)
8925 dlsym(adev->adm_lib, "adm_register_input_stream");
8926 adev->adm_register_output_stream = (adm_register_output_stream_t)
8927 dlsym(adev->adm_lib, "adm_register_output_stream");
8928 adev->adm_deregister_stream = (adm_deregister_stream_t)
8929 dlsym(adev->adm_lib, "adm_deregister_stream");
8930 adev->adm_request_focus = (adm_request_focus_t)
8931 dlsym(adev->adm_lib, "adm_request_focus");
8932 adev->adm_abandon_focus = (adm_abandon_focus_t)
8933 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008934 adev->adm_set_config = (adm_set_config_t)
8935 dlsym(adev->adm_lib, "adm_set_config");
8936 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8937 dlsym(adev->adm_lib, "adm_request_focus_v2");
8938 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8939 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8940 adev->adm_on_routing_change = (adm_on_routing_change_t)
8941 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008942 }
8943 }
8944
Aalique Grahame22e49102018-12-18 14:23:57 -08008945 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008946 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008947 //initialize this to false for now,
8948 //this will be set to true through set param
8949 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008950
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008951 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008952 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08008953
8954 if (k_enable_extended_precision)
8955 adev_verify_devices(adev);
8956
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008957 adev->dsp_bit_width_enforce_mode =
8958 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008959
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308960 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8961 &adev->streams_output_cfg_list,
8962 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008963
Kiran Kandi910e1862013-10-29 13:29:42 -07008964 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008965
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008966 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08008967 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
8968 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008969 trial = atoi(value);
8970 if (period_size_is_plausible_for_low_latency(trial)) {
8971 pcm_config_low_latency.period_size = trial;
8972 pcm_config_low_latency.start_threshold = trial / 4;
8973 pcm_config_low_latency.avail_min = trial / 4;
8974 configured_low_latency_capture_period_size = trial;
8975 }
8976 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008977 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
8978 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008979 trial = atoi(value);
8980 if (period_size_is_plausible_for_low_latency(trial)) {
8981 configured_low_latency_capture_period_size = trial;
8982 }
8983 }
8984
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008985 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8986
Aalique Grahame22e49102018-12-18 14:23:57 -08008987 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
8988 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008989 af_period_multiplier = atoi(value);
8990 if (af_period_multiplier < 0)
8991 af_period_multiplier = 2;
8992 else if (af_period_multiplier > 4)
8993 af_period_multiplier = 4;
8994
8995 ALOGV("new period_multiplier = %d", af_period_multiplier);
8996 }
8997
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008998 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008999
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009000 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009001 pthread_mutex_unlock(&adev_init_lock);
9002
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009003 if (adev->adm_init)
9004 adev->adm_data = adev->adm_init();
9005
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309006 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309007 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009008 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309009
9010 audio_extn_snd_mon_init();
9011 pthread_mutex_lock(&adev->lock);
9012 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9013 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009014 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9015 /*
9016 * if the battery state callback happens before charging can be queried,
9017 * it will be guarded with the adev->lock held in the cb function and so
9018 * the callback value will reflect the latest state
9019 */
9020 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309021 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009022 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
9023 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309024 /* Allocate memory for Device config params */
9025 adev->device_cfg_params = (struct audio_device_config_param*)
9026 calloc(platform_get_max_codec_backend(),
9027 sizeof(struct audio_device_config_param));
9028 if (adev->device_cfg_params == NULL)
9029 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309030
Eric Laurent994a6932013-07-17 11:51:42 -07009031 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009032 return 0;
9033}
9034
9035static struct hw_module_methods_t hal_module_methods = {
9036 .open = adev_open,
9037};
9038
9039struct audio_module HAL_MODULE_INFO_SYM = {
9040 .common = {
9041 .tag = HARDWARE_MODULE_TAG,
9042 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9043 .hal_api_version = HARDWARE_HAL_API_VERSION,
9044 .id = AUDIO_HARDWARE_MODULE_ID,
9045 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009046 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009047 .methods = &hal_module_methods,
9048 },
9049};