blob: 13574355388682e5ffa914586c137461e5fff647 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053076#include "ip_hdlr_intf.h"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080077#include "audio_feature_manager.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096
Aalique Grahame22e49102018-12-18 14:23:57 -080097#define RECORD_GAIN_MIN 0.0f
98#define RECORD_GAIN_MAX 1.0f
99#define RECORD_VOLUME_CTL_MAX 0x2000
100
101/* treat as unsigned Q1.13 */
102#define APP_TYPE_GAIN_DEFAULT 0x2000
103
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700104#define PROXY_OPEN_RETRY_COUNT 100
105#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800106
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800107#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
108 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
109 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
110#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800112
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700113#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700114#define DEFAULT_VOIP_BUF_DURATION_MS 20
115#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
116#define DEFAULT_VOIP_SAMP_RATE 48000
117
118#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
119
120struct pcm_config default_pcm_config_voip_copp = {
121 .channels = 1,
122 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
123 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
124 .period_count = 2,
125 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800126 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700128};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700130#define MIN_CHANNEL_COUNT 1
131#define DEFAULT_CHANNEL_COUNT 2
132#define MAX_HIFI_CHANNEL_COUNT 8
133
Aalique Grahame22e49102018-12-18 14:23:57 -0800134#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
135#define MAX_CHANNEL_COUNT 1
136#else
137#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
138#define XSTR(x) STR(x)
139#define STR(x) #x
140#endif
141
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700142static unsigned int configured_low_latency_capture_period_size =
143 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
144
Haynes Mathew George16081042017-05-31 17:16:49 -0700145#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
146#define MMAP_PERIOD_COUNT_MIN 32
147#define MMAP_PERIOD_COUNT_MAX 512
148#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
149
Aalique Grahame22e49102018-12-18 14:23:57 -0800150/* This constant enables extended precision handling.
151 * TODO The flag is off until more testing is done.
152 */
153static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700154extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800155
Eric Laurentb23d5282013-05-14 15:27:20 -0700156struct pcm_config pcm_config_deep_buffer = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
160 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
163 .stop_threshold = INT_MAX,
164 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165};
166
167struct pcm_config pcm_config_low_latency = {
168 .channels = 2,
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
170 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
171 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
172 .format = PCM_FORMAT_S16_LE,
173 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
174 .stop_threshold = INT_MAX,
175 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176};
177
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800178struct pcm_config pcm_config_haptics_audio = {
179 .channels = 1,
180 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
181 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
182 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185 .stop_threshold = INT_MAX,
186 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187};
188
189struct pcm_config pcm_config_haptics = {
190 .channels = 1,
191 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
192 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
193 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
198};
199
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700200static int af_period_multiplier = 4;
201struct pcm_config pcm_config_rt = {
202 .channels = 2,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = ULL_PERIOD_SIZE, //1 ms
205 .period_count = 512, //=> buffer size is 512ms
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
208 .stop_threshold = INT_MAX,
209 .silence_threshold = 0,
210 .silence_size = 0,
211 .avail_min = ULL_PERIOD_SIZE, //1 ms
212};
213
Eric Laurentb23d5282013-05-14 15:27:20 -0700214struct pcm_config pcm_config_hdmi_multi = {
215 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
216 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
217 .period_size = HDMI_MULTI_PERIOD_SIZE,
218 .period_count = HDMI_MULTI_PERIOD_COUNT,
219 .format = PCM_FORMAT_S16_LE,
220 .start_threshold = 0,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_playback = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = MMAP_PERIOD_SIZE*8,
232 .stop_threshold = INT32_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700238struct pcm_config pcm_config_hifi = {
239 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
240 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
241 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
242 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
243 .format = PCM_FORMAT_S24_3LE,
244 .start_threshold = 0,
245 .stop_threshold = INT_MAX,
246 .avail_min = 0,
247};
248
Eric Laurentb23d5282013-05-14 15:27:20 -0700249struct pcm_config pcm_config_audio_capture = {
250 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700251 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
252 .format = PCM_FORMAT_S16_LE,
253};
254
Haynes Mathew George16081042017-05-31 17:16:49 -0700255struct pcm_config pcm_config_mmap_capture = {
256 .channels = 2,
257 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
258 .period_size = MMAP_PERIOD_SIZE,
259 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
260 .format = PCM_FORMAT_S16_LE,
261 .start_threshold = 0,
262 .stop_threshold = INT_MAX,
263 .silence_threshold = 0,
264 .silence_size = 0,
265 .avail_min = MMAP_PERIOD_SIZE, //1 ms
266};
267
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700268#define AFE_PROXY_CHANNEL_COUNT 2
269#define AFE_PROXY_SAMPLING_RATE 48000
270
271#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
272#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
273
274struct pcm_config pcm_config_afe_proxy_playback = {
275 .channels = AFE_PROXY_CHANNEL_COUNT,
276 .rate = AFE_PROXY_SAMPLING_RATE,
277 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
278 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
279 .format = PCM_FORMAT_S16_LE,
280 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .stop_threshold = INT_MAX,
282 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283};
284
285#define AFE_PROXY_RECORD_PERIOD_SIZE 768
286#define AFE_PROXY_RECORD_PERIOD_COUNT 4
287
Aalique Grahame22e49102018-12-18 14:23:57 -0800288struct pcm_config pcm_config_audio_capture_rt = {
289 .channels = 2,
290 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
291 .period_size = ULL_PERIOD_SIZE,
292 .period_count = 512,
293 .format = PCM_FORMAT_S16_LE,
294 .start_threshold = 0,
295 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
296 .silence_threshold = 0,
297 .silence_size = 0,
298 .avail_min = ULL_PERIOD_SIZE, //1 ms
299};
300
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700301struct pcm_config pcm_config_afe_proxy_record = {
302 .channels = AFE_PROXY_CHANNEL_COUNT,
303 .rate = AFE_PROXY_SAMPLING_RATE,
304 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
305 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
306 .format = PCM_FORMAT_S16_LE,
307 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .stop_threshold = INT_MAX,
309 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
310};
311
Ashish Jainf1eaa582016-05-23 20:54:24 +0530312#define AUDIO_MAX_PCM_FORMATS 7
313
314const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
315 [AUDIO_FORMAT_DEFAULT] = 0,
316 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
317 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
318 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
319 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
321 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
322};
323
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800324const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700325 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
326 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800327 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700328 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
329 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700330 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700331 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
333 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700340 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
341 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700342 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800343 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700344
Eric Laurentb23d5282013-05-14 15:27:20 -0700345 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700346 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530347 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
348 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
349 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530350 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
351 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700352 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700353 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700354 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700355 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800357 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800358 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700359 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700360
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700361 [USECASE_VOICE2_CALL] = "voice2-call",
362 [USECASE_VOLTE_CALL] = "volte-call",
363 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800364 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800365 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
366 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800367 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700368 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
369 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
370 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800371 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
372 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
373 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
374
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700375 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
376 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700377 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
378 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700379
380 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
381 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530382 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700383
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530384 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530385 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
388 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
389 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530390 /* For Interactive Audio Streams */
391 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700399
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800400 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
401
402 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700403};
404
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700405static const audio_usecase_t offload_usecases[] = {
406 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700407 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
408 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700415};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800416
Varun Balaraje49253e2017-07-06 19:48:56 +0530417static const audio_usecase_t interactive_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
426};
427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428#define STRING_TO_ENUM(string) { #string, string }
429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430struct string_to_enum {
431 const char *name;
432 uint32_t value;
433};
434
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700435static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700444 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
445 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
446 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
447 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455};
456
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457static const struct string_to_enum formats_name_to_enum_table[] = {
458 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
459 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
460 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700461 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
462 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
463 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700464 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800465 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
466 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800468};
469
470//list of all supported sample rates by HDMI specification.
471static const int out_hdmi_sample_rates[] = {
472 32000, 44100, 48000, 88200, 96000, 176400, 192000,
473};
474
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700475static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(32000),
477 STRING_TO_ENUM(44100),
478 STRING_TO_ENUM(48000),
479 STRING_TO_ENUM(88200),
480 STRING_TO_ENUM(96000),
481 STRING_TO_ENUM(176400),
482 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700483};
484
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700485static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700486static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700487static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700488//cache last MBDRC cal step level
489static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700490
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530491static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
492static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700493static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800494static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530495static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530496
Vatsal Buchac09ae062018-11-14 13:25:08 +0530497#ifdef AUDIO_FEATURE_ENABLED_GCOV
498extern void __gcov_flush();
499static void enable_gcov()
500{
501 __gcov_flush();
502}
503#else
504static void enable_gcov()
505{
506}
507#endif
508
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700509static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
510 int flags __unused)
511{
512 int dir = 0;
513 switch (uc_id) {
514 case USECASE_AUDIO_RECORD_LOW_LATENCY:
515 dir = 1;
516 case USECASE_AUDIO_PLAYBACK_ULL:
517 break;
518 default:
519 return false;
520 }
521
522 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
523 PCM_PLAYBACK : PCM_CAPTURE);
524 if (adev->adm_is_noirq_avail)
525 return adev->adm_is_noirq_avail(adev->adm_data,
526 adev->snd_card, dev_id, dir);
527 return false;
528}
529
530static void register_out_stream(struct stream_out *out)
531{
532 struct audio_device *adev = out->dev;
533 if (is_offload_usecase(out->usecase) ||
534 !adev->adm_register_output_stream)
535 return;
536
537 // register stream first for backward compatibility
538 adev->adm_register_output_stream(adev->adm_data,
539 out->handle,
540 out->flags);
541
542 if (!adev->adm_set_config)
543 return;
544
545 if (out->realtime)
546 adev->adm_set_config(adev->adm_data,
547 out->handle,
548 out->pcm, &out->config);
549}
550
551static void register_in_stream(struct stream_in *in)
552{
553 struct audio_device *adev = in->dev;
554 if (!adev->adm_register_input_stream)
555 return;
556
557 adev->adm_register_input_stream(adev->adm_data,
558 in->capture_handle,
559 in->flags);
560
561 if (!adev->adm_set_config)
562 return;
563
564 if (in->realtime)
565 adev->adm_set_config(adev->adm_data,
566 in->capture_handle,
567 in->pcm,
568 &in->config);
569}
570
571static void request_out_focus(struct stream_out *out, long ns)
572{
573 struct audio_device *adev = out->dev;
574
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700575 if (adev->adm_request_focus_v2)
576 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
577 else if (adev->adm_request_focus)
578 adev->adm_request_focus(adev->adm_data, out->handle);
579}
580
581static void request_in_focus(struct stream_in *in, long ns)
582{
583 struct audio_device *adev = in->dev;
584
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700585 if (adev->adm_request_focus_v2)
586 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
587 else if (adev->adm_request_focus)
588 adev->adm_request_focus(adev->adm_data, in->capture_handle);
589}
590
591static void release_out_focus(struct stream_out *out)
592{
593 struct audio_device *adev = out->dev;
594
595 if (adev->adm_abandon_focus)
596 adev->adm_abandon_focus(adev->adm_data, out->handle);
597}
598
599static void release_in_focus(struct stream_in *in)
600{
601 struct audio_device *adev = in->dev;
602 if (adev->adm_abandon_focus)
603 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
604}
605
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530606static int parse_snd_card_status(struct str_parms *parms, int *card,
607 card_status_t *status)
608{
609 char value[32]={0};
610 char state[32]={0};
611
612 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
613 if (ret < 0)
614 return -1;
615
616 // sscanf should be okay as value is of max length 32.
617 // same as sizeof state.
618 if (sscanf(value, "%d,%s", card, state) < 2)
619 return -1;
620
621 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
622 CARD_STATUS_OFFLINE;
623 return 0;
624}
625
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700626static inline void adjust_frames_for_device_delay(struct stream_out *out,
627 uint32_t *dsp_frames) {
628 // Adjustment accounts for A2dp encoder latency with offload usecases
629 // Note: Encoder latency is returned in ms.
630 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
631 unsigned long offset =
632 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
633 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
634 }
635}
636
vivek mehtaa76401a2015-04-24 14:12:15 -0700637__attribute__ ((visibility ("default")))
638bool audio_hw_send_gain_dep_calibration(int level) {
639 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700640 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700641
642 pthread_mutex_lock(&adev_init_lock);
643
644 if (adev != NULL && adev->platform != NULL) {
645 pthread_mutex_lock(&adev->lock);
646 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700647
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530648 // cache level info for any of the use case which
649 // was not started.
650 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700651
vivek mehtaa76401a2015-04-24 14:12:15 -0700652 pthread_mutex_unlock(&adev->lock);
653 } else {
654 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
655 }
656
657 pthread_mutex_unlock(&adev_init_lock);
658
659 return ret_val;
660}
661
Ashish Jain5106d362016-05-11 19:23:33 +0530662static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
663{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800664 bool gapless_enabled = false;
665 const char *mixer_ctl_name = "Compress Gapless Playback";
666 struct mixer_ctl *ctl;
667
668 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700669 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530670
671 /*Disable gapless if its AV playback*/
672 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800673
674 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
675 if (!ctl) {
676 ALOGE("%s: Could not get ctl for mixer cmd - %s",
677 __func__, mixer_ctl_name);
678 return -EINVAL;
679 }
680
681 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
682 ALOGE("%s: Could not set gapless mode %d",
683 __func__, gapless_enabled);
684 return -EINVAL;
685 }
686 return 0;
687}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700688
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700689__attribute__ ((visibility ("default")))
690int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
691 int table_size) {
692 int ret_val = 0;
693 ALOGV("%s: enter ... ", __func__);
694
695 pthread_mutex_lock(&adev_init_lock);
696 if (adev == NULL) {
697 ALOGW("%s: adev is NULL .... ", __func__);
698 goto done;
699 }
700
701 pthread_mutex_lock(&adev->lock);
702 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
703 pthread_mutex_unlock(&adev->lock);
704done:
705 pthread_mutex_unlock(&adev_init_lock);
706 ALOGV("%s: exit ... ", __func__);
707 return ret_val;
708}
709
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800710bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800711{
712 bool ret = false;
713 ALOGV("%s: enter ...", __func__);
714
715 pthread_mutex_lock(&adev_init_lock);
716
717 if (adev != NULL && adev->platform != NULL) {
718 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800719 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800720 pthread_mutex_unlock(&adev->lock);
721 }
722
723 pthread_mutex_unlock(&adev_init_lock);
724
725 ALOGV("%s: exit with ret %d", __func__, ret);
726 return ret;
727}
Aalique Grahame22e49102018-12-18 14:23:57 -0800728
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700729static bool is_supported_format(audio_format_t format)
730{
Eric Laurent86e17132013-09-12 17:49:30 -0700731 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530732 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530733 format == AUDIO_FORMAT_AAC_LC ||
734 format == AUDIO_FORMAT_AAC_HE_V1 ||
735 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530736 format == AUDIO_FORMAT_AAC_ADTS_LC ||
737 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
738 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530739 format == AUDIO_FORMAT_AAC_LATM_LC ||
740 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
741 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530742 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
743 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530744 format == AUDIO_FORMAT_PCM_FLOAT ||
745 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700746 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530747 format == AUDIO_FORMAT_AC3 ||
748 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700749 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530750 format == AUDIO_FORMAT_DTS ||
751 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800752 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530753 format == AUDIO_FORMAT_ALAC ||
754 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530755 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530756 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800757 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530758 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700759 format == AUDIO_FORMAT_APTX ||
760 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800761 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700762
763 return false;
764}
765
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700766static inline bool is_mmap_usecase(audio_usecase_t uc_id)
767{
768 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
769 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
770}
771
Avinash Vaish71a8b972014-07-24 15:36:33 +0530772static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
773 struct audio_usecase *uc_info)
774{
775 struct listnode *node;
776 struct audio_usecase *usecase;
777
778 if (uc_info == NULL)
779 return -EINVAL;
780
781 /* Re-route all voice usecases on the shared backend other than the
782 specified usecase to new snd devices */
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800785 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530786 enable_audio_route(adev, usecase);
787 }
788 return 0;
789}
790
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530791static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530792{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530793 ALOGV("%s", __func__);
794 audio_route_apply_and_update_path(adev->audio_route,
795 "asrc-mode");
796 adev->asrc_mode_enabled = true;
797}
798
799static void disable_asrc_mode(struct audio_device *adev)
800{
801 ALOGV("%s", __func__);
802 audio_route_reset_and_update_path(adev->audio_route,
803 "asrc-mode");
804 adev->asrc_mode_enabled = false;
805}
806
807/*
808 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
809 * 44.1 or Native DSD backends are enabled for any of current use case.
810 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
811 * - Disable current mix path use case(Headphone backend) and re-enable it with
812 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
813 * e.g. Naitve DSD or Headphone 44.1 -> + 48
814 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530815static void check_and_set_asrc_mode(struct audio_device *adev,
816 struct audio_usecase *uc_info,
817 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530818{
819 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530820 int i, num_new_devices = 0;
821 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
822 /*
823 *Split snd device for new combo use case
824 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
825 */
826 if (platform_split_snd_device(adev->platform,
827 snd_device,
828 &num_new_devices,
829 split_new_snd_devices) == 0) {
830 for (i = 0; i < num_new_devices; i++)
831 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
832 } else {
833 int new_backend_idx = platform_get_backend_index(snd_device);
834 if (((new_backend_idx == HEADPHONE_BACKEND) ||
835 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
836 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
837 !adev->asrc_mode_enabled) {
838 struct listnode *node = NULL;
839 struct audio_usecase *uc = NULL;
840 struct stream_out *curr_out = NULL;
841 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
842 int i, num_devices, ret = 0;
843 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530844
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530845 list_for_each(node, &adev->usecase_list) {
846 uc = node_to_item(node, struct audio_usecase, list);
847 curr_out = (struct stream_out*) uc->stream.out;
848 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
849 /*
850 *Split snd device for existing combo use case
851 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
852 */
853 ret = platform_split_snd_device(adev->platform,
854 uc->out_snd_device,
855 &num_devices,
856 split_snd_devices);
857 if (ret < 0 || num_devices == 0) {
858 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
859 split_snd_devices[0] = uc->out_snd_device;
860 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800861 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530862 for (i = 0; i < num_devices; i++) {
863 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
864 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
865 if((new_backend_idx == HEADPHONE_BACKEND) &&
866 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
867 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
868 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
869 __func__);
870 enable_asrc_mode(adev);
871 break;
872 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
873 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
874 (usecase_backend_idx == HEADPHONE_BACKEND)) {
875 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
876 __func__);
877 disable_audio_route(adev, uc);
878 disable_snd_device(adev, uc->out_snd_device);
879 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
880 if (new_backend_idx == DSD_NATIVE_BACKEND)
881 audio_route_apply_and_update_path(adev->audio_route,
882 "hph-true-highquality-mode");
883 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
884 (curr_out->bit_width >= 24))
885 audio_route_apply_and_update_path(adev->audio_route,
886 "hph-highquality-mode");
887 enable_asrc_mode(adev);
888 enable_snd_device(adev, uc->out_snd_device);
889 enable_audio_route(adev, uc);
890 break;
891 }
892 }
893 // reset split devices count
894 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800895 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530896 if (adev->asrc_mode_enabled)
897 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530898 }
899 }
900 }
901}
902
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700903static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
904 struct audio_effect_config effect_config,
905 unsigned int param_value)
906{
907 char mixer_ctl_name[] = "Audio Effect";
908 struct mixer_ctl *ctl;
909 long set_values[6];
910 struct stream_in *in = adev->active_input;
911
912 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
913 if (!ctl) {
914 ALOGE("%s: Could not get mixer ctl - %s",
915 __func__, mixer_ctl_name);
916 return -EINVAL;
917 }
918
919 set_values[0] = 1; //0:Rx 1:Tx
920 set_values[1] = in->app_type_cfg.app_type;
921 set_values[2] = (long)effect_config.module_id;
922 set_values[3] = (long)effect_config.instance_id;
923 set_values[4] = (long)effect_config.param_id;
924 set_values[5] = param_value;
925
926 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
927
928 return 0;
929
930}
931
932static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
933 int effect_type, unsigned int *param_value)
934{
935 int ret = 0;
936 struct audio_effect_config other_effect_config;
937 struct audio_usecase *usecase = NULL;
938 struct stream_in *in = adev->active_input;
939
940 usecase = get_usecase_from_list(adev, in->usecase);
941 if (!usecase)
942 return -EINVAL;
943
944 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
945 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
946 if (ret < 0) {
947 ALOGE("%s Failed to get effect params %d", __func__, ret);
948 return ret;
949 }
950
951 if (module_id == other_effect_config.module_id) {
952 //Same module id for AEC/NS. Values need to be combined
953 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
954 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
955 *param_value |= other_effect_config.param_value;
956 }
957 }
958
959 return ret;
960}
961
962static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800963{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700964 struct audio_effect_config effect_config;
965 struct audio_usecase *usecase = NULL;
966 int ret = 0;
967 unsigned int param_value = 0;
968 struct stream_in *in = adev->active_input;
969
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800970 if(!voice_extn_is_dynamic_ecns_enabled())
971 return ENOSYS;
972
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700973 if (!in) {
974 ALOGE("%s: Invalid input stream", __func__);
975 return -EINVAL;
976 }
977
978 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
979
980 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800981 if (usecase == NULL) {
982 ALOGE("%s: Could not find the usecase (%d) in the list",
983 __func__, in->usecase);
984 return -EINVAL;
985 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700986
987 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
988 if (ret < 0) {
989 ALOGE("%s Failed to get module id %d", __func__, ret);
990 return ret;
991 }
992 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
993 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
994
995 if(enable)
996 param_value = effect_config.param_value;
997
998 /*Special handling for AEC & NS effects Param values need to be
999 updated if module ids are same*/
1000
1001 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1002 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1003 if (ret < 0)
1004 return ret;
1005 }
1006
1007 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1008
1009 return ret;
1010}
1011
1012static void check_and_enable_effect(struct audio_device *adev)
1013{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001014 if(!voice_extn_is_dynamic_ecns_enabled())
1015 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001016
1017 if (adev->active_input->enable_aec) {
1018 enable_disable_effect(adev, EFFECT_AEC, true);
1019 }
1020
1021 if (adev->active_input->enable_ns &&
1022 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1023 enable_disable_effect(adev, EFFECT_NS, true);
1024 }
1025}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001026
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001027int pcm_ioctl(struct pcm *pcm, int request, ...)
1028{
1029 va_list ap;
1030 void * arg;
1031 int pcm_fd = *(int*)pcm;
1032
1033 va_start(ap, request);
1034 arg = va_arg(ap, void *);
1035 va_end(ap);
1036
1037 return ioctl(pcm_fd, request, arg);
1038}
1039
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001040int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001041 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001044 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301045 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301046 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001047
1048 if (usecase == NULL)
1049 return -EINVAL;
1050
1051 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1052
Surendar Karka93cd25a2018-08-28 14:21:37 +05301053 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001055 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001057
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001058#ifdef DS1_DOLBY_DAP_ENABLED
1059 audio_extn_dolby_set_dmid(adev);
1060 audio_extn_dolby_set_endpoint(adev);
1061#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001062 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001063 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301064 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001065 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301066 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301067 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1068 out = usecase->stream.out;
1069 if (out && out->compr)
1070 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1071 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301072 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301073
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001074 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001075 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001076 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301077 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1078 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1079 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1080 if (parms) {
1081 audio_extn_fm_set_parameters(adev, parms);
1082 str_parms_destroy(parms);
1083 }
1084 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 ALOGV("%s: exit", __func__);
1086 return 0;
1087}
1088
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001089int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001090 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001093 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001094
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301095 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001096 return -EINVAL;
1097
1098 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301099 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 snd_device = usecase->in_snd_device;
1101 else
1102 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001103 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001104 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001105 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001106 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001107 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301108 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301109 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301110 if (usecase->stream.out != NULL)
1111 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 ALOGV("%s: exit", __func__);
1113 return 0;
1114}
1115
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001116int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001117 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301119 int i, num_devices = 0;
1120 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001121 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1122
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001123 if (snd_device < SND_DEVICE_MIN ||
1124 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001125 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001126 return -EINVAL;
1127 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001129 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001130 ALOGE("%s: Invalid sound device returned", __func__);
1131 return -EINVAL;
1132 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001133
1134 adev->snd_dev_ref_cnt[snd_device]++;
1135
1136 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1137 (platform_split_snd_device(adev->platform,
1138 snd_device,
1139 &num_devices,
1140 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001141 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001142 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001143 return 0;
1144 }
1145
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001146 if (audio_extn_spkr_prot_is_enabled())
1147 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001148
Aalique Grahame22e49102018-12-18 14:23:57 -08001149 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1150
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001151 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1152 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001153 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1154 goto err;
1155 }
1156 audio_extn_dev_arbi_acquire(snd_device);
1157 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001158 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001159 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001160 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001161 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001162 } else if (platform_split_snd_device(adev->platform,
1163 snd_device,
1164 &num_devices,
1165 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301166 for (i = 0; i < num_devices; i++) {
1167 enable_snd_device(adev, new_snd_devices[i]);
1168 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001169 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001170 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001171 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301172
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301173
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001174 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1175 (audio_extn_a2dp_start_playback() < 0)) {
1176 ALOGE(" fail to configure A2dp Source control path ");
1177 goto err;
1178 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001179
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001180 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1181 (audio_extn_a2dp_start_capture() < 0)) {
1182 ALOGE(" fail to configure A2dp Sink control path ");
1183 goto err;
1184 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301185
Zhou Song12c29502019-03-16 10:37:18 +08001186 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1187 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1188 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1189 (audio_extn_sco_start_configuration() < 0)) {
1190 ALOGE(" fail to configure sco control path ");
1191 goto err;
1192 }
1193
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001194 /* due to the possibility of calibration overwrite between listen
1195 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001196 audio_extn_sound_trigger_update_device_status(snd_device,
1197 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301198 audio_extn_listen_update_device_status(snd_device,
1199 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001200 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001201 audio_extn_sound_trigger_update_device_status(snd_device,
1202 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301203 audio_extn_listen_update_device_status(snd_device,
1204 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001205 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001206 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001207 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001208 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301209
1210 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1211 !adev->native_playback_enabled &&
1212 audio_is_true_native_stream_active(adev)) {
1213 ALOGD("%s: %d: napb: enabling native mode in hardware",
1214 __func__, __LINE__);
1215 audio_route_apply_and_update_path(adev->audio_route,
1216 "true-native-mode");
1217 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301218 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301219 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1220 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001221 (audio_extn_ffv_get_stream() == adev->active_input)) {
1222 ALOGD("%s: init ec ref loopback", __func__);
1223 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1224 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001227err:
1228 adev->snd_dev_ref_cnt[snd_device]--;
1229 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230}
1231
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001232int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001233 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301235 int i, num_devices = 0;
1236 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001237 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1238
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001239 if (snd_device < SND_DEVICE_MIN ||
1240 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001241 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001242 return -EINVAL;
1243 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001244
1245 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1246 ALOGE("%s: Invalid sound device returned", __func__);
1247 return -EINVAL;
1248 }
1249
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001250 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1251 ALOGE("%s: device ref cnt is already 0", __func__);
1252 return -EINVAL;
1253 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001254
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001256
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001257
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001259 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301260
Aalique Grahame22e49102018-12-18 14:23:57 -08001261 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1262
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001263 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1264 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001265 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001266
1267 // when speaker device is disabled, reset swap.
1268 // will be renabled on usecase start
1269 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001270 } else if (platform_split_snd_device(adev->platform,
1271 snd_device,
1272 &num_devices,
1273 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301274 for (i = 0; i < num_devices; i++) {
1275 disable_snd_device(adev, new_snd_devices[i]);
1276 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001277 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001278 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001279 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001280 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001281
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001282 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301283 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001284 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001285 audio_extn_a2dp_stop_capture();
Zhou Song12c29502019-03-16 10:37:18 +08001286 else if ((snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
1287 (snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC) ||
1288 (snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB)) {
1289 if ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_SCO_SWB] == 0) &&
1290 (adev->snd_dev_ref_cnt[SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC] == 0) &&
1291 (adev->snd_dev_ref_cnt[SND_DEVICE_IN_BT_SCO_MIC_SWB] == 0))
1292 audio_extn_sco_reset_configuration();
1293 } else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001294 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301295 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001296 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301297 adev->native_playback_enabled) {
1298 ALOGD("%s: %d: napb: disabling native mode in hardware",
1299 __func__, __LINE__);
1300 audio_route_reset_and_update_path(adev->audio_route,
1301 "true-native-mode");
1302 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001303 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301304 adev->asrc_mode_enabled) {
1305 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301306 disable_asrc_mode(adev);
1307 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001308 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301309 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001310 (audio_extn_ffv_get_stream() == adev->active_input)) {
1311 ALOGD("%s: deinit ec ref loopback", __func__);
1312 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1313 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001314
1315 audio_extn_utils_release_snd_device(snd_device);
1316 } else {
1317 if (platform_split_snd_device(adev->platform,
1318 snd_device,
1319 &num_devices,
1320 new_snd_devices) == 0) {
1321 for (i = 0; i < num_devices; i++) {
1322 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1323 }
1324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001327 return 0;
1328}
1329
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001330/*
1331 legend:
1332 uc - existing usecase
1333 new_uc - new usecase
1334 d1, d11, d2 - SND_DEVICE enums
1335 a1, a2 - corresponding ANDROID device enums
1336 B1, B2 - backend strings
1337
1338case 1
1339 uc->dev d1 (a1) B1
1340 new_uc->dev d1 (a1), d2 (a2) B1, B2
1341
1342 resolution: disable and enable uc->dev on d1
1343
1344case 2
1345 uc->dev d1 (a1) B1
1346 new_uc->dev d11 (a1) B1
1347
1348 resolution: need to switch uc since d1 and d11 are related
1349 (e.g. speaker and voice-speaker)
1350 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1351
1352case 3
1353 uc->dev d1 (a1) B1
1354 new_uc->dev d2 (a2) B2
1355
1356 resolution: no need to switch uc
1357
1358case 4
1359 uc->dev d1 (a1) B1
1360 new_uc->dev d2 (a2) B1
1361
1362 resolution: disable enable uc-dev on d2 since backends match
1363 we cannot enable two streams on two different devices if they
1364 share the same backend. e.g. if offload is on speaker device using
1365 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1366 using the same backend, offload must also be switched to voice-handset.
1367
1368case 5
1369 uc->dev d1 (a1) B1
1370 new_uc->dev d1 (a1), d2 (a2) B1
1371
1372 resolution: disable enable uc-dev on d2 since backends match
1373 we cannot enable two streams on two different devices if they
1374 share the same backend.
1375
1376case 6
1377 uc->dev d1 (a1) B1
1378 new_uc->dev d2 (a1) B2
1379
1380 resolution: no need to switch
1381
1382case 7
1383 uc->dev d1 (a1), d2 (a2) B1, B2
1384 new_uc->dev d1 (a1) B1
1385
1386 resolution: no need to switch
1387
Zhou Song4ba65882018-07-09 14:48:07 +08001388case 8
1389 uc->dev d1 (a1) B1
1390 new_uc->dev d11 (a1), d2 (a2) B1, B2
1391 resolution: compared to case 1, for this case, d1 and d11 are related
1392 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001393*/
1394static snd_device_t derive_playback_snd_device(void * platform,
1395 struct audio_usecase *uc,
1396 struct audio_usecase *new_uc,
1397 snd_device_t new_snd_device)
1398{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301399 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001400
1401 snd_device_t d1 = uc->out_snd_device;
1402 snd_device_t d2 = new_snd_device;
1403
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301404 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301405 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301406 a1 = uc->stream.inout->out_config.devices;
1407 a2 = new_uc->stream.inout->out_config.devices;
1408 break;
1409 default :
1410 a1 = uc->stream.out->devices;
1411 a2 = new_uc->stream.out->devices;
1412 break;
1413 }
1414
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001415 // Treat as a special case when a1 and a2 are not disjoint
1416 if ((a1 != a2) && (a1 & a2)) {
1417 snd_device_t d3[2];
1418 int num_devices = 0;
1419 int ret = platform_split_snd_device(platform,
1420 popcount(a1) > 1 ? d1 : d2,
1421 &num_devices,
1422 d3);
1423 if (ret < 0) {
1424 if (ret != -ENOSYS) {
1425 ALOGW("%s failed to split snd_device %d",
1426 __func__,
1427 popcount(a1) > 1 ? d1 : d2);
1428 }
1429 goto end;
1430 }
1431
1432 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1433 // But if it does happen, we need to give priority to d2 if
1434 // the combo devices active on the existing usecase share a backend.
1435 // This is because we cannot have a usecase active on a combo device
1436 // and a new usecase requests one device in this combo pair.
1437 if (platform_check_backends_match(d3[0], d3[1])) {
1438 return d2; // case 5
1439 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001440 // check if d1 is related to any of d3's
1441 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001442 return d1; // case 1
1443 else
1444 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001445 }
1446 } else {
1447 if (platform_check_backends_match(d1, d2)) {
1448 return d2; // case 2, 4
1449 } else {
1450 return d1; // case 6, 3
1451 }
1452 }
1453
1454end:
1455 return d2; // return whatever was calculated before.
1456}
1457
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301459 struct audio_usecase *uc_info,
1460 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461{
1462 struct listnode *node;
1463 struct audio_usecase *usecase;
1464 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301465 snd_device_t uc_derive_snd_device;
1466 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001467 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1468 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001469 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301470 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471 /*
1472 * This function is to make sure that all the usecases that are active on
1473 * the hardware codec backend are always routed to any one device that is
1474 * handled by the hardware codec.
1475 * For example, if low-latency and deep-buffer usecases are currently active
1476 * on speaker and out_set_parameters(headset) is received on low-latency
1477 * output, then we have to make sure deep-buffer is also switched to headset,
1478 * because of the limitation that both the devices cannot be enabled
1479 * at the same time as they share the same backend.
1480 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001481 /*
1482 * This call is to check if we need to force routing for a particular stream
1483 * If there is a backend configuration change for the device when a
1484 * new stream starts, then ADM needs to be closed and re-opened with the new
1485 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001486 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001487 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001488 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1489 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301490 /* For a2dp device reconfigure all active sessions
1491 * with new AFE encoder format based on a2dp state
1492 */
1493 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1494 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1495 audio_extn_a2dp_is_force_device_switch()) {
1496 force_routing = true;
1497 force_restart_session = true;
1498 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301499 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1500
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001502 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001503 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001504 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1505 switch_device[i] = false;
1506
1507 list_for_each(node, &adev->usecase_list) {
1508 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001509
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301510 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1511 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301512 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301513 platform_get_snd_device_name(usecase->out_snd_device),
1514 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301515 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1516 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1517 usecase, uc_info, snd_device);
1518 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1519 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1520 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1521 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001522 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301523 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1524 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1525 ((force_restart_session) ||
1526 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301527 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1528 __func__, use_case_table[usecase->id],
1529 platform_get_snd_device_name(usecase->out_snd_device));
1530 disable_audio_route(adev, usecase);
1531 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301532 /* Enable existing usecase on derived playback device */
1533 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301534 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 }
1537 }
1538
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301539 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1540 num_uc_to_switch);
1541
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001543 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301545 /* Make sure the previous devices to be disabled first and then enable the
1546 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001547 list_for_each(node, &adev->usecase_list) {
1548 usecase = node_to_item(node, struct audio_usecase, list);
1549 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001550 /* Check if output sound device to be switched can be split and if any
1551 of the split devices match with derived sound device */
1552 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1553 &num_devices, split_snd_devices) == 0) {
1554 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1555 for (i = 0; i < num_devices; i++) {
1556 /* Disable devices that do not match with derived sound device */
1557 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1558 disable_snd_device(adev, split_snd_devices[i]);
1559 }
1560 } else {
1561 disable_snd_device(adev, usecase->out_snd_device);
1562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 }
1564 }
1565
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001566 list_for_each(node, &adev->usecase_list) {
1567 usecase = node_to_item(node, struct audio_usecase, list);
1568 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001569 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1570 &num_devices, split_snd_devices) == 0) {
1571 /* Enable derived sound device only if it does not match with
1572 one of the split sound devices. This is because the matching
1573 sound device was not disabled */
1574 bool should_enable = true;
1575 for (i = 0; i < num_devices; i++) {
1576 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1577 should_enable = false;
1578 break;
1579 }
1580 }
1581 if (should_enable)
1582 enable_snd_device(adev, derive_snd_device[usecase->id]);
1583 } else {
1584 enable_snd_device(adev, derive_snd_device[usecase->id]);
1585 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001586 }
1587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 /* Re-route all the usecases on the shared backend other than the
1590 specified usecase to new snd devices */
1591 list_for_each(node, &adev->usecase_list) {
1592 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301593 /* Update the out_snd_device only before enabling the audio route */
1594 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301595 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301596 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301597 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301598 use_case_table[usecase->id],
1599 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001600 /* Update voc calibration before enabling VoIP route */
1601 if (usecase->type == VOIP_CALL)
1602 status = platform_switch_voice_call_device_post(adev->platform,
1603 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001604 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301605 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001606 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1607 out_set_voip_volume(&usecase->stream.out->stream,
1608 usecase->stream.out->volume_l,
1609 usecase->stream.out->volume_r);
1610 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301611 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001612 }
1613 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001614 }
1615}
1616
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301617static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001618 struct audio_usecase *uc_info,
1619 snd_device_t snd_device)
1620{
1621 struct listnode *node;
1622 struct audio_usecase *usecase;
1623 bool switch_device[AUDIO_USECASE_MAX];
1624 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301625 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001626 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001627
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301628 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1629 snd_device);
1630 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301631
1632 /*
1633 * Make sure out devices is checked against out codec backend device and
1634 * also in devices against in codec backend. Checking out device against in
1635 * codec backend or vice versa causes issues.
1636 */
1637 if (uc_info->type == PCM_CAPTURE)
1638 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001639 /*
1640 * This function is to make sure that all the active capture usecases
1641 * are always routed to the same input sound device.
1642 * For example, if audio-record and voice-call usecases are currently
1643 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1644 * is received for voice call then we have to make sure that audio-record
1645 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1646 * because of the limitation that two devices cannot be enabled
1647 * at the same time if they share the same backend.
1648 */
1649 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1650 switch_device[i] = false;
1651
1652 list_for_each(node, &adev->usecase_list) {
1653 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301654 /*
1655 * TODO: Enhance below condition to handle BT sco/USB multi recording
1656 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001657 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001658 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301659 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301660 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301661 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301662 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001663 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001664 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1665 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001666 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001667 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001668 switch_device[usecase->id] = true;
1669 num_uc_to_switch++;
1670 }
1671 }
1672
1673 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001674 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001675
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301676 /* Make sure the previous devices to be disabled first and then enable the
1677 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001678 list_for_each(node, &adev->usecase_list) {
1679 usecase = node_to_item(node, struct audio_usecase, list);
1680 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001681 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001682 }
1683 }
1684
1685 list_for_each(node, &adev->usecase_list) {
1686 usecase = node_to_item(node, struct audio_usecase, list);
1687 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001688 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001689 }
1690 }
1691
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001692 /* Re-route all the usecases on the shared backend other than the
1693 specified usecase to new snd devices */
1694 list_for_each(node, &adev->usecase_list) {
1695 usecase = node_to_item(node, struct audio_usecase, list);
1696 /* Update the in_snd_device only before enabling the audio route */
1697 if (switch_device[usecase->id] ) {
1698 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001699 if (usecase->type != VOICE_CALL) {
1700 /* Update voc calibration before enabling VoIP route */
1701 if (usecase->type == VOIP_CALL)
1702 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001703 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001704 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301705 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001706 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001707 }
1708 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001709 }
1710}
1711
Mingming Yin3a941d42016-02-17 18:08:05 -08001712static void reset_hdmi_sink_caps(struct stream_out *out) {
1713 int i = 0;
1714
1715 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1716 out->supported_channel_masks[i] = 0;
1717 }
1718 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1719 out->supported_formats[i] = 0;
1720 }
1721 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1722 out->supported_sample_rates[i] = 0;
1723 }
1724}
1725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001727static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728{
Mingming Yin3a941d42016-02-17 18:08:05 -08001729 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001730 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731
Mingming Yin3a941d42016-02-17 18:08:05 -08001732 reset_hdmi_sink_caps(out);
1733
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001734 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001735 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001736 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001737 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001738 }
1739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001742 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001743 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001744 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1745 case 6:
1746 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1747 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1748 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1749 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1750 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1751 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 break;
1753 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001754 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001755 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756 break;
1757 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001758
1759 // check channel format caps
1760 i = 0;
1761 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1762 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1763 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1764 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1765 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1766 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1767 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1768 }
1769
Ben Romberger1aaaf862017-04-06 17:49:46 -07001770 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1771 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1772 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1773 }
1774
Mingming Yin3a941d42016-02-17 18:08:05 -08001775 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1776 ALOGV(":%s HDMI supports DTS format", __func__);
1777 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1778 }
1779
1780 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1781 ALOGV(":%s HDMI supports DTS HD format", __func__);
1782 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1783 }
1784
Naresh Tanniru928f0862017-04-07 16:44:23 -07001785 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1786 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1787 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1788 }
1789
Mingming Yin3a941d42016-02-17 18:08:05 -08001790
1791 // check sample rate caps
1792 i = 0;
1793 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1794 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1795 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1796 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1797 }
1798 }
1799
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001800 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801}
1802
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001803static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1804 uint32_t *supported_sample_rates __unused,
1805 uint32_t max_rates __unused)
1806{
1807 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1808 supported_sample_rates,
1809 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301810 ssize_t i = 0;
1811
1812 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001813 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1814 supported_sample_rates[i]);
1815 }
1816 return count;
1817}
1818
1819static inline int read_usb_sup_channel_masks(bool is_playback,
1820 audio_channel_mask_t *supported_channel_masks,
1821 uint32_t max_masks)
1822{
1823 int channels = audio_extn_usb_get_max_channels(is_playback);
1824 int channel_count;
1825 uint32_t num_masks = 0;
1826 if (channels > MAX_HIFI_CHANNEL_COUNT)
1827 channels = MAX_HIFI_CHANNEL_COUNT;
1828
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301829 channel_count = DEFAULT_CHANNEL_COUNT;
1830
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001831 if (is_playback) {
1832 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001833 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301834 // above 2 but we want indexed masks here.
1835 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001836 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001837 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1838 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301839 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001840 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301841
1842 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1843 (num_masks < max_masks)); channel_count--) {
1844 supported_channel_masks[num_masks++] =
1845 audio_channel_mask_for_index_assignment_from_count(channel_count);
1846 }
1847
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001848 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1849 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1850 return num_masks;
1851}
1852
1853static inline int read_usb_sup_formats(bool is_playback __unused,
1854 audio_format_t *supported_formats,
1855 uint32_t max_formats __unused)
1856{
1857 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1858 switch (bitwidth) {
1859 case 24:
1860 // XXX : usb.c returns 24 for s24 and s24_le?
1861 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1862 break;
1863 case 32:
1864 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1865 break;
1866 case 16:
1867 default :
1868 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1869 break;
1870 }
1871 ALOGV("%s: %s supported format %d", __func__,
1872 is_playback ? "P" : "C", bitwidth);
1873 return 1;
1874}
1875
1876static inline int read_usb_sup_params_and_compare(bool is_playback,
1877 audio_format_t *format,
1878 audio_format_t *supported_formats,
1879 uint32_t max_formats,
1880 audio_channel_mask_t *mask,
1881 audio_channel_mask_t *supported_channel_masks,
1882 uint32_t max_masks,
1883 uint32_t *rate,
1884 uint32_t *supported_sample_rates,
1885 uint32_t max_rates) {
1886 int ret = 0;
1887 int num_formats;
1888 int num_masks;
1889 int num_rates;
1890 int i;
1891
1892 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1893 max_formats);
1894 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1895 max_masks);
1896
1897 num_rates = read_usb_sup_sample_rates(is_playback,
1898 supported_sample_rates, max_rates);
1899
1900#define LUT(table, len, what, dflt) \
1901 for (i=0; i<len && (table[i] != what); i++); \
1902 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1903
1904 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1905 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1906 LUT(supported_sample_rates, num_rates, *rate, 0);
1907
1908#undef LUT
1909 return ret < 0 ? -EINVAL : 0; // HACK TBD
1910}
1911
Alexy Josephb1379942016-01-29 15:49:38 -08001912audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001913 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001914{
1915 struct audio_usecase *usecase;
1916 struct listnode *node;
1917
1918 list_for_each(node, &adev->usecase_list) {
1919 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001920 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001921 ALOGV("%s: usecase id %d", __func__, usecase->id);
1922 return usecase->id;
1923 }
1924 }
1925 return USECASE_INVALID;
1926}
1927
Alexy Josephb1379942016-01-29 15:49:38 -08001928struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001929 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930{
1931 struct audio_usecase *usecase;
1932 struct listnode *node;
1933
1934 list_for_each(node, &adev->usecase_list) {
1935 usecase = node_to_item(node, struct audio_usecase, list);
1936 if (usecase->id == uc_id)
1937 return usecase;
1938 }
1939 return NULL;
1940}
1941
Dhananjay Kumard4833242016-10-06 22:09:12 +05301942struct stream_in *get_next_active_input(const struct audio_device *adev)
1943{
1944 struct audio_usecase *usecase;
1945 struct listnode *node;
1946
1947 list_for_each_reverse(node, &adev->usecase_list) {
1948 usecase = node_to_item(node, struct audio_usecase, list);
1949 if (usecase->type == PCM_CAPTURE)
1950 return usecase->stream.in;
1951 }
1952 return NULL;
1953}
1954
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301955/*
1956 * is a true native playback active
1957 */
1958bool audio_is_true_native_stream_active(struct audio_device *adev)
1959{
1960 bool active = false;
1961 int i = 0;
1962 struct listnode *node;
1963
1964 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1965 ALOGV("%s:napb: not in true mode or non hdphones device",
1966 __func__);
1967 active = false;
1968 goto exit;
1969 }
1970
1971 list_for_each(node, &adev->usecase_list) {
1972 struct audio_usecase *uc;
1973 uc = node_to_item(node, struct audio_usecase, list);
1974 struct stream_out *curr_out =
1975 (struct stream_out*) uc->stream.out;
1976
1977 if (curr_out && PCM_PLAYBACK == uc->type) {
1978 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1979 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1980 uc->id, curr_out->sample_rate,
1981 curr_out->bit_width,
1982 platform_get_snd_device_name(uc->out_snd_device));
1983
1984 if (is_offload_usecase(uc->id) &&
1985 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1986 active = true;
1987 ALOGD("%s:napb:native stream detected", __func__);
1988 }
1989 }
1990 }
1991exit:
1992 return active;
1993}
1994
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001995uint32_t adev_get_dsp_bit_width_enforce_mode()
1996{
1997 if (adev == NULL) {
1998 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1999 return 0;
2000 }
2001 return adev->dsp_bit_width_enforce_mode;
2002}
2003
2004static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2005{
2006 char value[PROPERTY_VALUE_MAX];
2007 int trial;
2008 uint32_t dsp_bit_width_enforce_mode = 0;
2009
2010 if (!mixer) {
2011 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2012 __func__);
2013 return 0;
2014 }
2015
2016 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2017 value, NULL) > 0) {
2018 trial = atoi(value);
2019 switch (trial) {
2020 case 16:
2021 dsp_bit_width_enforce_mode = 16;
2022 break;
2023 case 24:
2024 dsp_bit_width_enforce_mode = 24;
2025 break;
2026 case 32:
2027 dsp_bit_width_enforce_mode = 32;
2028 break;
2029 default:
2030 dsp_bit_width_enforce_mode = 0;
2031 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2032 break;
2033 }
2034 }
2035
2036 return dsp_bit_width_enforce_mode;
2037}
2038
2039static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2040 uint32_t enforce_mode,
2041 bool enable)
2042{
2043 struct mixer_ctl *ctl = NULL;
2044 const char *mixer_ctl_name = "ASM Bit Width";
2045 uint32_t asm_bit_width_mode = 0;
2046
2047 if (enforce_mode == 0) {
2048 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2049 return;
2050 }
2051
2052 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2053 if (!ctl) {
2054 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2055 __func__, mixer_ctl_name);
2056 return;
2057 }
2058
2059 if (enable)
2060 asm_bit_width_mode = enforce_mode;
2061 else
2062 asm_bit_width_mode = 0;
2063
2064 ALOGV("%s DSP bit width feature status is %d width=%d",
2065 __func__, enable, asm_bit_width_mode);
2066 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2067 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2068 asm_bit_width_mode);
2069
2070 return;
2071}
2072
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302073/*
2074 * if native DSD playback active
2075 */
2076bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2077{
2078 bool active = false;
2079 struct listnode *node = NULL;
2080 struct audio_usecase *uc = NULL;
2081 struct stream_out *curr_out = NULL;
2082
2083 list_for_each(node, &adev->usecase_list) {
2084 uc = node_to_item(node, struct audio_usecase, list);
2085 curr_out = (struct stream_out*) uc->stream.out;
2086
2087 if (curr_out && PCM_PLAYBACK == uc->type &&
2088 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2089 active = true;
2090 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302091 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302092 }
2093 }
2094 return active;
2095}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302096
2097static bool force_device_switch(struct audio_usecase *usecase)
2098{
2099 bool ret = false;
2100 bool is_it_true_mode = false;
2101
Zhou Song30f2c3e2018-02-08 14:02:15 +08002102 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302103 usecase->type == TRANSCODE_LOOPBACK_RX ||
2104 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002105 return false;
2106 }
2107
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002108 if(usecase->stream.out == NULL) {
2109 ALOGE("%s: stream.out is NULL", __func__);
2110 return false;
2111 }
2112
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302113 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002114 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2115 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2116 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302117 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2118 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2119 (!is_it_true_mode && adev->native_playback_enabled)){
2120 ret = true;
2121 ALOGD("napb: time to toggle native mode");
2122 }
2123 }
2124
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302125 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302126 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2127 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002128 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302129 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302130 ALOGD("Force a2dp device switch to update new encoder config");
2131 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002132 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302133
Florian Pfister1a84f312018-07-19 14:38:18 +02002134 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302135 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2136 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002137 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302138 return ret;
2139}
2140
Aalique Grahame22e49102018-12-18 14:23:57 -08002141static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2142{
2143 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2144}
2145
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302146bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2147{
2148 bool ret=false;
2149 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2150 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2151 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2152 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2153 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2154 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2155 ret = true;
2156
2157 return ret;
2158}
2159
2160bool is_a2dp_device(snd_device_t out_snd_device)
2161{
2162 bool ret=false;
2163 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2164 ret = true;
2165
2166 return ret;
2167}
2168
2169bool is_bt_soc_on(struct audio_device *adev)
2170{
2171 struct mixer_ctl *ctl;
2172 char *mixer_ctl_name = "BT SOC status";
2173 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2174 bool bt_soc_status = true;
2175 if (!ctl) {
2176 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2177 __func__, mixer_ctl_name);
2178 /*This is to ensure we dont break targets which dont have the kernel change*/
2179 return true;
2180 }
2181 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2182 ALOGD("BT SOC status: %d",bt_soc_status);
2183 return bt_soc_status;
2184}
2185
2186int out_standby_l(struct audio_stream *stream);
2187
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002188int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002190 snd_device_t out_snd_device = SND_DEVICE_NONE;
2191 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002192 struct audio_usecase *usecase = NULL;
2193 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002194 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002195 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302196 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002197 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002198 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302200 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2201
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002202 usecase = get_usecase_from_list(adev, uc_id);
2203 if (usecase == NULL) {
2204 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2205 return -EINVAL;
2206 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002208 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002209 (usecase->type == VOIP_CALL) ||
2210 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302211 if(usecase->stream.out == NULL) {
2212 ALOGE("%s: stream.out is NULL", __func__);
2213 return -EINVAL;
2214 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002215 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002216 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002217 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002218 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302219 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302220 if (usecase->stream.inout == NULL) {
2221 ALOGE("%s: stream.inout is NULL", __func__);
2222 return -EINVAL;
2223 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302224 stream_out.devices = usecase->stream.inout->out_config.devices;
2225 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2226 stream_out.format = usecase->stream.inout->out_config.format;
2227 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2228 out_snd_device = platform_get_output_snd_device(adev->platform,
2229 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302230 usecase->devices = out_snd_device;
2231 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2232 if (usecase->stream.inout == NULL) {
2233 ALOGE("%s: stream.inout is NULL", __func__);
2234 return -EINVAL;
2235 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302236 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302237 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 } else {
2239 /*
2240 * If the voice call is active, use the sound devices of voice call usecase
2241 * so that it would not result any device switch. All the usecases will
2242 * be switched to new device when select_devices() is called for voice call
2243 * usecase. This is to avoid switching devices for voice call when
2244 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002245 * choose voice call device only if the use case device is
2246 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002248 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002249 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002250 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002251 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2252 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302253 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2254 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002255 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002256 in_snd_device = vc_usecase->in_snd_device;
2257 out_snd_device = vc_usecase->out_snd_device;
2258 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002259 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002260 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002261 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002262 if ((voip_usecase != NULL) &&
2263 (usecase->type == PCM_PLAYBACK) &&
2264 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002265 out_snd_device_backend_match = platform_check_backends_match(
2266 voip_usecase->out_snd_device,
2267 platform_get_output_snd_device(
2268 adev->platform,
2269 usecase->stream.out));
2270 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002271 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002272 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2273 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002274 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002275 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002276 in_snd_device = voip_usecase->in_snd_device;
2277 out_snd_device = voip_usecase->out_snd_device;
2278 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002279 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002280 hfp_ucid = audio_extn_hfp_get_usecase();
2281 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002282 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002283 in_snd_device = hfp_usecase->in_snd_device;
2284 out_snd_device = hfp_usecase->out_snd_device;
2285 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286 }
2287 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302288 if (usecase->stream.out == NULL) {
2289 ALOGE("%s: stream.out is NULL", __func__);
2290 return -EINVAL;
2291 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002292 usecase->devices = usecase->stream.out->devices;
2293 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002294 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002295 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002296 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002297 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002298 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002299 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2300
2301 if ((usecase->stream.out != NULL &&
2302 voip_usecase != NULL &&
2303 usecase->stream.out->usecase == voip_usecase->id) &&
2304 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002305 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2306 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002307 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002308 select_devices(adev, adev->active_input->usecase);
2309 }
2310 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002311 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302312 if (usecase->stream.in == NULL) {
2313 ALOGE("%s: stream.in is NULL", __func__);
2314 return -EINVAL;
2315 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002316 usecase->devices = usecase->stream.in->device;
2317 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002318 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002319 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002320 if (adev->active_input &&
2321 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302322 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002323 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2324 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2325 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2326 out_device = voip_usecase->stream.out->devices;
2327 else if (adev->primary_output && !adev->primary_output->standby)
2328 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002329 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002330 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2331 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002332 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002333 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002334 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002335 }
2336 }
2337
2338 if (out_snd_device == usecase->out_snd_device &&
2339 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302340
2341 if (!force_device_switch(usecase))
2342 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 }
2344
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302345 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002346 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302347 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2348 return 0;
2349 }
2350
Aalique Grahame22e49102018-12-18 14:23:57 -08002351 if (out_snd_device != SND_DEVICE_NONE &&
2352 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2353 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2354 __func__,
2355 use_case_table[uc_id],
2356 adev->last_logged_snd_device[uc_id][0],
2357 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2358 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2359 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2360 -1,
2361 out_snd_device,
2362 platform_get_snd_device_name(out_snd_device),
2363 platform_get_snd_device_acdb_id(out_snd_device));
2364 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2365 }
2366 if (in_snd_device != SND_DEVICE_NONE &&
2367 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2368 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2369 __func__,
2370 use_case_table[uc_id],
2371 adev->last_logged_snd_device[uc_id][1],
2372 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2373 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2374 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2375 -1,
2376 in_snd_device,
2377 platform_get_snd_device_name(in_snd_device),
2378 platform_get_snd_device_acdb_id(in_snd_device));
2379 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2380 }
2381
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 /*
2384 * Limitation: While in call, to do a device switch we need to disable
2385 * and enable both RX and TX devices though one of them is same as current
2386 * device.
2387 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002388 if ((usecase->type == VOICE_CALL) &&
2389 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2390 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002391 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002392 }
2393
2394 if (((usecase->type == VOICE_CALL) ||
2395 (usecase->type == VOIP_CALL)) &&
2396 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2397 /* Disable sidetone only if voice/voip call already exists */
2398 if (voice_is_call_state_active(adev) ||
2399 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002400 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002401
2402 /* Disable aanc only if voice call exists */
2403 if (voice_is_call_state_active(adev))
2404 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002405 }
2406
Aalique Grahame22e49102018-12-18 14:23:57 -08002407 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2408 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002409 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302410 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002411 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2412 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2413 else
2414 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302415 }
2416
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002417 /* Disable current sound devices */
2418 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002419 disable_audio_route(adev, usecase);
2420 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 }
2422
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002423 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002424 disable_audio_route(adev, usecase);
2425 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 }
2427
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002428 /* Applicable only on the targets that has external modem.
2429 * New device information should be sent to modem before enabling
2430 * the devices to reduce in-call device switch time.
2431 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002432 if ((usecase->type == VOICE_CALL) &&
2433 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2434 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002435 status = platform_switch_voice_call_enable_device_config(adev->platform,
2436 out_snd_device,
2437 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002438 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002439
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002440 /* Enable new sound devices */
2441 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002442 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302443 if (platform_check_codec_asrc_support(adev->platform))
2444 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002445 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 }
2447
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002448 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302449 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002450 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002451 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002452
Avinash Vaish71a8b972014-07-24 15:36:33 +05302453 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002454 status = platform_switch_voice_call_device_post(adev->platform,
2455 out_snd_device,
2456 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302457 enable_audio_route_for_voice_usecases(adev, usecase);
2458 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002459
sangwoo170731f2013-06-08 15:36:36 +09002460 usecase->in_snd_device = in_snd_device;
2461 usecase->out_snd_device = out_snd_device;
2462
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302463 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2464 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302465 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002466 if ((24 == usecase->stream.out->bit_width) &&
2467 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2468 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2469 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2470 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2471 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2472 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2473 /*
2474 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2475 * configured device sample rate, if not update the COPP rate to be equal to the
2476 * device sample rate, else open COPP at stream sample rate
2477 */
2478 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2479 usecase->stream.out->sample_rate,
2480 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302481 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2482 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002483 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2484 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2485 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2486 }
2487
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002488 /* Notify device change info to effect clients registered */
2489 audio_extn_gef_notify_device_config(
2490 usecase->stream.out->devices,
2491 usecase->stream.out->channel_mask,
2492 usecase->stream.out->app_type_cfg.sample_rate,
2493 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302494 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002495 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002496
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002497 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002498
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002499 /* If input stream is already running then effect needs to be
2500 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002501 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2502 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002503 check_and_enable_effect(adev);
2504
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002505 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002506 /* Enable aanc only if voice call exists */
2507 if (voice_is_call_state_active(adev))
2508 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2509
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002510 /* Enable sidetone only if other voice/voip call already exists */
2511 if (voice_is_call_state_active(adev) ||
2512 voice_extn_compress_voip_is_started(adev))
2513 voice_set_sidetone(adev, out_snd_device, true);
2514 }
2515
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002516 /* Applicable only on the targets that has external modem.
2517 * Enable device command should be sent to modem only after
2518 * enabling voice call mixer controls
2519 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002520 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002521 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2522 out_snd_device,
2523 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302524
2525 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2526
2527 if (usecase->type == VOIP_CALL) {
2528 if (adev->active_input != NULL &&
2529 !adev->active_input->standby) {
2530 if (is_bt_soc_on(adev) == false){
2531 ALOGD("BT SCO MIC disconnected while in connection");
2532 if (adev->active_input->pcm != NULL)
2533 pcm_stop(adev->active_input->pcm);
2534 }
2535 }
2536 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2537 && usecase->stream.out->started) {
2538 if (is_bt_soc_on(adev) == false) {
2539 ALOGD("BT SCO/A2DP disconnected while in connection");
2540 out_standby_l(&usecase->stream.out->stream.common);
2541 }
2542 }
2543 } else if ((usecase->stream.out != NULL) &&
2544 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302545 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2546 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302547 usecase->stream.out->started) {
2548 if (is_bt_soc_on(adev) == false) {
2549 ALOGD("BT SCO/A2dp disconnected while in connection");
2550 out_standby_l(&usecase->stream.out->stream.common);
2551 }
2552 }
2553 }
2554
Aalique Grahame22e49102018-12-18 14:23:57 -08002555 if (usecase == voip_usecase) {
2556 struct stream_out *voip_out = voip_usecase->stream.out;
2557 audio_extn_utils_send_app_type_gain(adev,
2558 voip_out->app_type_cfg.app_type,
2559 &voip_out->app_type_cfg.gain[0]);
2560 }
2561
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302562 ALOGD("%s: done",__func__);
2563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 return status;
2565}
2566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567static int stop_input_stream(struct stream_in *in)
2568{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302569 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302571
2572 if (in == NULL) {
2573 ALOGE("%s: stream_in ptr is NULL", __func__);
2574 return -EINVAL;
2575 }
2576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 struct audio_device *adev = in->dev;
2578
Eric Laurent994a6932013-07-17 11:51:42 -07002579 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002580 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 uc_info = get_usecase_from_list(adev, in->usecase);
2582 if (uc_info == NULL) {
2583 ALOGE("%s: Could not find the usecase (%d) in the list",
2584 __func__, in->usecase);
2585 return -EINVAL;
2586 }
2587
Derek Chenea197282019-01-07 17:35:01 -08002588 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2589 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002590
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002591 /* Close in-call recording streams */
2592 voice_check_and_stop_incall_rec_usecase(adev, in);
2593
Eric Laurent150dbfe2013-02-27 14:31:02 -08002594 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002595 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002596
2597 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002598 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002600 list_remove(&uc_info->list);
2601 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002603 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302604 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002605 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606 return ret;
2607}
2608
2609int start_input_stream(struct stream_in *in)
2610{
2611 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002612 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302614
2615 if (in == NULL) {
2616 ALOGE("%s: stream_in ptr is NULL", __func__);
2617 return -EINVAL;
2618 }
2619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002621 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002622 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623
Mingming Yin2664a5b2015-09-03 10:53:11 -07002624 if (get_usecase_from_list(adev, usecase) == NULL)
2625 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302626 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2627 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002628
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302629 if (CARD_STATUS_OFFLINE == in->card_status||
2630 CARD_STATUS_OFFLINE == adev->card_status) {
2631 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302632 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633 goto error_config;
2634 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302635
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302636 if (audio_is_bluetooth_sco_device(in->device)) {
2637 if (!adev->bt_sco_on) {
2638 ALOGE("%s: SCO profile is not ready, return error", __func__);
2639 ret = -EIO;
2640 goto error_config;
2641 }
2642 }
2643
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002644 /* Check if source matches incall recording usecase criteria */
2645 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2646 if (ret)
2647 goto error_config;
2648 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002649 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2650
2651 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2652 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2653 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002654 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002655 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002656
Eric Laurentb23d5282013-05-14 15:27:20 -07002657 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 if (in->pcm_device_id < 0) {
2659 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2660 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002661 ret = -EINVAL;
2662 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002664
2665 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002667
2668 if (!uc_info) {
2669 ret = -ENOMEM;
2670 goto error_config;
2671 }
2672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 uc_info->id = in->usecase;
2674 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002675 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 uc_info->devices = in->device;
2677 uc_info->in_snd_device = SND_DEVICE_NONE;
2678 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002680 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302681 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2682 adev->perf_lock_opts,
2683 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002684 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685
Derek Chenea197282019-01-07 17:35:01 -08002686 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2687 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002688
Haynes Mathew George16081042017-05-31 17:16:49 -07002689 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302690 ret = audio_extn_cin_start_input_stream(in);
2691 if (ret)
2692 goto error_open;
2693 else
2694 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002695 }
2696
Haynes Mathew George16081042017-05-31 17:16:49 -07002697 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002698 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002699 ALOGE("%s: pcm stream not ready", __func__);
2700 goto error_open;
2701 }
2702 ret = pcm_start(in->pcm);
2703 if (ret < 0) {
2704 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2705 goto error_open;
2706 }
2707 } else {
2708 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2709 unsigned int pcm_open_retry_count = 0;
2710
2711 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2712 flags |= PCM_MMAP | PCM_NOIRQ;
2713 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2714 } else if (in->realtime) {
2715 flags |= PCM_MMAP | PCM_NOIRQ;
2716 }
2717
Garmond Leunge2433c32017-09-28 21:51:22 -07002718 if (audio_extn_ffv_get_stream() == in) {
2719 ALOGD("%s: ffv stream, update pcm config", __func__);
2720 audio_extn_ffv_update_pcm_config(&config);
2721 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002722 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2723 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2724
2725 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002726 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002727 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002728 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002729 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302730 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302731 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2732 adev->card_status = CARD_STATUS_OFFLINE;
2733 in->card_status = CARD_STATUS_OFFLINE;
2734 ret = -EIO;
2735 goto error_open;
2736 }
2737
Haynes Mathew George16081042017-05-31 17:16:49 -07002738 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2739 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2740 if (in->pcm != NULL) {
2741 pcm_close(in->pcm);
2742 in->pcm = NULL;
2743 }
2744 if (pcm_open_retry_count-- == 0) {
2745 ret = -EIO;
2746 goto error_open;
2747 }
2748 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2749 continue;
2750 }
2751 break;
2752 }
2753
2754 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002755 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002756 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002757 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002758 if (ret < 0) {
2759 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2760 pcm_close(in->pcm);
2761 in->pcm = NULL;
2762 goto error_open;
2763 }
2764 register_in_stream(in);
2765 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002766 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002767 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002768 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002769 if (ret < 0) {
2770 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002771 pcm_close(in->pcm);
2772 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002773 goto error_open;
2774 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002775 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002776 }
2777
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002778 check_and_enable_effect(adev);
2779
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302780done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302781 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002782 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302783 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002784 return ret;
2785
2786error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302787 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002789error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302790 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302791 /*
2792 * sleep 50ms to allow sufficient time for kernel
2793 * drivers to recover incases like SSR.
2794 */
2795 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002796 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302797 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002798 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799}
2800
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002801void lock_input_stream(struct stream_in *in)
2802{
2803 pthread_mutex_lock(&in->pre_lock);
2804 pthread_mutex_lock(&in->lock);
2805 pthread_mutex_unlock(&in->pre_lock);
2806}
2807
2808void lock_output_stream(struct stream_out *out)
2809{
2810 pthread_mutex_lock(&out->pre_lock);
2811 pthread_mutex_lock(&out->lock);
2812 pthread_mutex_unlock(&out->pre_lock);
2813}
2814
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815/* must be called with out->lock locked */
2816static int send_offload_cmd_l(struct stream_out* out, int command)
2817{
2818 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2819
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002820 if (!cmd) {
2821 ALOGE("failed to allocate mem for command 0x%x", command);
2822 return -ENOMEM;
2823 }
2824
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 ALOGVV("%s %d", __func__, command);
2826
2827 cmd->cmd = command;
2828 list_add_tail(&out->offload_cmd_list, &cmd->node);
2829 pthread_cond_signal(&out->offload_cond);
2830 return 0;
2831}
2832
2833/* must be called iwth out->lock locked */
2834static void stop_compressed_output_l(struct stream_out *out)
2835{
2836 out->offload_state = OFFLOAD_STATE_IDLE;
2837 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002838 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002839 if (out->compr != NULL) {
2840 compress_stop(out->compr);
2841 while (out->offload_thread_blocked) {
2842 pthread_cond_wait(&out->cond, &out->lock);
2843 }
2844 }
2845}
2846
Varun Balaraje49253e2017-07-06 19:48:56 +05302847bool is_interactive_usecase(audio_usecase_t uc_id)
2848{
2849 unsigned int i;
2850 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2851 if (uc_id == interactive_usecases[i])
2852 return true;
2853 }
2854 return false;
2855}
2856
2857static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2858{
2859 audio_usecase_t ret_uc = USECASE_INVALID;
2860 unsigned int intract_uc_index;
2861 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2862
2863 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2864 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2865 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2866 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2867 ret_uc = interactive_usecases[intract_uc_index];
2868 break;
2869 }
2870 }
2871
2872 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2873 return ret_uc;
2874}
2875
2876static void free_interactive_usecase(struct audio_device *adev,
2877 audio_usecase_t uc_id)
2878{
2879 unsigned int interact_uc_index;
2880 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2881
2882 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2883 if (interactive_usecases[interact_uc_index] == uc_id) {
2884 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2885 break;
2886 }
2887 }
2888 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2889}
2890
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002891bool is_offload_usecase(audio_usecase_t uc_id)
2892{
2893 unsigned int i;
2894 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2895 if (uc_id == offload_usecases[i])
2896 return true;
2897 }
2898 return false;
2899}
2900
Dhananjay Kumarac341582017-02-23 23:42:25 +05302901static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002902{
vivek mehta446c3962015-09-14 10:57:35 -07002903 audio_usecase_t ret_uc = USECASE_INVALID;
2904 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002905 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002906 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302907 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002908 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2909 else
2910 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002911
vivek mehta446c3962015-09-14 10:57:35 -07002912 pthread_mutex_lock(&adev->lock);
2913 if (get_usecase_from_list(adev, ret_uc) != NULL)
2914 ret_uc = USECASE_INVALID;
2915 pthread_mutex_unlock(&adev->lock);
2916
2917 return ret_uc;
2918 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002919
2920 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002921 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2922 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2923 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2924 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002925 break;
2926 }
2927 }
vivek mehta446c3962015-09-14 10:57:35 -07002928
2929 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2930 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002931}
2932
2933static void free_offload_usecase(struct audio_device *adev,
2934 audio_usecase_t uc_id)
2935{
vivek mehta446c3962015-09-14 10:57:35 -07002936 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002937 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002938
2939 if (!adev->multi_offload_enable)
2940 return;
2941
2942 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2943 if (offload_usecases[offload_uc_index] == uc_id) {
2944 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002945 break;
2946 }
2947 }
2948 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2949}
2950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951static void *offload_thread_loop(void *context)
2952{
2953 struct stream_out *out = (struct stream_out *) context;
2954 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002955 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002958 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2960
2961 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002962 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 for (;;) {
2964 struct offload_cmd *cmd = NULL;
2965 stream_callback_event_t event;
2966 bool send_callback = false;
2967
2968 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2969 __func__, list_empty(&out->offload_cmd_list),
2970 out->offload_state);
2971 if (list_empty(&out->offload_cmd_list)) {
2972 ALOGV("%s SLEEPING", __func__);
2973 pthread_cond_wait(&out->offload_cond, &out->lock);
2974 ALOGV("%s RUNNING", __func__);
2975 continue;
2976 }
2977
2978 item = list_head(&out->offload_cmd_list);
2979 cmd = node_to_item(item, struct offload_cmd, node);
2980 list_remove(item);
2981
2982 ALOGVV("%s STATE %d CMD %d out->compr %p",
2983 __func__, out->offload_state, cmd->cmd, out->compr);
2984
2985 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2986 free(cmd);
2987 break;
2988 }
2989
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002990 // allow OFFLOAD_CMD_ERROR reporting during standby
2991 // this is needed to handle failures during compress_open
2992 // Note however that on a pause timeout, the stream is closed
2993 // and no offload usecase will be active. Therefore this
2994 // special case is needed for compress_open failures alone
2995 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2996 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002998 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002999 pthread_cond_signal(&out->cond);
3000 continue;
3001 }
3002 out->offload_thread_blocked = true;
3003 pthread_mutex_unlock(&out->lock);
3004 send_callback = false;
3005 switch(cmd->cmd) {
3006 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003007 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003009 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 send_callback = true;
3011 event = STREAM_CBK_EVENT_WRITE_READY;
3012 break;
3013 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003014 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303015 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003016 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303017 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003018 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303019 if (ret < 0)
3020 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303021 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303022 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003023 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003024 else
3025 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003026 if (-ENETRESET != ret && !(-EINTR == ret &&
3027 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303028 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303029 pthread_mutex_lock(&out->lock);
3030 out->send_new_metadata = 1;
3031 out->send_next_track_params = true;
3032 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303033 event = STREAM_CBK_EVENT_DRAIN_READY;
3034 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3035 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303036 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 break;
3038 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003039 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003040 ret = compress_drain(out->compr);
3041 ALOGD("copl(%p):out of compress_drain", out);
3042 // EINTR check avoids drain interruption due to SSR
3043 if (-ENETRESET != ret && !(-EINTR == ret &&
3044 CARD_STATUS_OFFLINE == out->card_status)) {
3045 send_callback = true;
3046 event = STREAM_CBK_EVENT_DRAIN_READY;
3047 } else
3048 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303050 case OFFLOAD_CMD_ERROR:
3051 ALOGD("copl(%p): sending error callback to AF", out);
3052 send_callback = true;
3053 event = STREAM_CBK_EVENT_ERROR;
3054 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 default:
3056 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3057 break;
3058 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003059 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 out->offload_thread_blocked = false;
3061 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003062 if (send_callback && out->client_callback) {
3063 ALOGVV("%s: sending client_callback event %d", __func__, event);
3064 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003065 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 free(cmd);
3067 }
3068
3069 pthread_cond_signal(&out->cond);
3070 while (!list_empty(&out->offload_cmd_list)) {
3071 item = list_head(&out->offload_cmd_list);
3072 list_remove(item);
3073 free(node_to_item(item, struct offload_cmd, node));
3074 }
3075 pthread_mutex_unlock(&out->lock);
3076
3077 return NULL;
3078}
3079
3080static int create_offload_callback_thread(struct stream_out *out)
3081{
3082 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3083 list_init(&out->offload_cmd_list);
3084 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3085 offload_thread_loop, out);
3086 return 0;
3087}
3088
3089static int destroy_offload_callback_thread(struct stream_out *out)
3090{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003091 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 stop_compressed_output_l(out);
3093 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3094
3095 pthread_mutex_unlock(&out->lock);
3096 pthread_join(out->offload_thread, (void **) NULL);
3097 pthread_cond_destroy(&out->offload_cond);
3098
3099 return 0;
3100}
3101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102static int stop_output_stream(struct stream_out *out)
3103{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303104 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 struct audio_usecase *uc_info;
3106 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003107 bool has_voip_usecase =
3108 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109
Eric Laurent994a6932013-07-17 11:51:42 -07003110 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003111 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 uc_info = get_usecase_from_list(adev, out->usecase);
3113 if (uc_info == NULL) {
3114 ALOGE("%s: Could not find the usecase (%d) in the list",
3115 __func__, out->usecase);
3116 return -EINVAL;
3117 }
3118
Derek Chenea197282019-01-07 17:35:01 -08003119 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3120 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003121
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003122 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303123 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003124 if (adev->visualizer_stop_output != NULL)
3125 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003126
3127 audio_extn_dts_remove_state_notifier_node(out->usecase);
3128
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003129 if (adev->offload_effects_stop_output != NULL)
3130 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3131 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003132
Arun Mirpurief53ce52018-09-11 18:00:09 -07003133 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3134 voice_set_device_mute_flag(adev, false);
3135
Eric Laurent150dbfe2013-02-27 14:31:02 -08003136 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003137 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003138
3139 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003140 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
Aalique Grahame22e49102018-12-18 14:23:57 -08003142 audio_extn_extspk_update(adev->extspk);
3143
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003144 if (is_offload_usecase(out->usecase)) {
3145 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3146 adev->dsp_bit_width_enforce_mode,
3147 false);
3148 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003149 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3150 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3151 false);
3152
3153 if (ret != 0)
3154 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3155 /* default service interval was successfully updated,
3156 reopen USB backend with new service interval */
3157 ret = 0;
3158 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003159
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003160 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303161 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003162 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303163 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003164 ALOGV("Disable passthrough , reset mixer to pcm");
3165 /* NO_PASSTHROUGH */
3166 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003167 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003168 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3169 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003170
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303171 /* Must be called after removing the usecase from list */
3172 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303173 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303174
Manish Dewangan21a850a2017-08-14 12:03:55 +05303175 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003176 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3177 if (ret < 0)
3178 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3179 }
3180
Aalique Grahame22e49102018-12-18 14:23:57 -08003181 if (has_voip_usecase ||
3182 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3183 struct listnode *node;
3184 struct audio_usecase *usecase;
3185 list_for_each(node, &adev->usecase_list) {
3186 usecase = node_to_item(node, struct audio_usecase, list);
3187 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3188 continue;
3189
3190 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3191 __func__, usecase->id, use_case_table[usecase->id],
3192 out->usecase, use_case_table[out->usecase]);
3193 select_devices(adev, usecase->id);
3194 }
3195 }
3196
Garmond Leung5fd0b552018-04-17 11:56:12 -07003197 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003198 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 return ret;
3200}
3201
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003202struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3203 unsigned int flags, unsigned int pcm_open_retry_count,
3204 struct pcm_config *config)
3205{
3206 struct pcm* pcm = NULL;
3207
3208 while (1) {
3209 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3210 if (pcm == NULL || !pcm_is_ready(pcm)) {
3211 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3212 if (pcm != NULL) {
3213 pcm_close(pcm);
3214 pcm = NULL;
3215 }
3216 if (pcm_open_retry_count-- == 0)
3217 return NULL;
3218
3219 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3220 continue;
3221 }
3222 break;
3223 }
3224
3225 if (pcm_is_ready(pcm)) {
3226 int ret = pcm_prepare(pcm);
3227 if (ret < 0) {
3228 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3229 pcm_close(pcm);
3230 pcm = NULL;
3231 }
3232 }
3233
3234 return pcm;
3235}
3236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237int start_output_stream(struct stream_out *out)
3238{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 struct audio_usecase *uc_info;
3241 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003242 char mixer_ctl_name[128];
3243 struct mixer_ctl *ctl = NULL;
3244 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303245 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003246 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247
Haynes Mathew George380745d2017-10-04 15:27:45 -07003248 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003249 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3250 ret = -EINVAL;
3251 goto error_config;
3252 }
3253
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003254 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303255 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003256 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303257
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303258 if (CARD_STATUS_OFFLINE == out->card_status ||
3259 CARD_STATUS_OFFLINE == adev->card_status) {
3260 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303261 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303262 goto error_config;
3263 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303264
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303265 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003266 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003267 if (out->devices &
3268 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303269 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303270 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303271 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3272 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3273 ret = -EAGAIN;
3274 goto error_config;
3275 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303276 }
3277 }
3278 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303279 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3280 if (!adev->bt_sco_on) {
3281 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3282 //combo usecase just by pass a2dp
3283 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3284 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3285 } else {
3286 ALOGE("%s: SCO profile is not ready, return error", __func__);
3287 ret = -EAGAIN;
3288 goto error_config;
3289 }
3290 }
3291 }
3292
Eric Laurentb23d5282013-05-14 15:27:20 -07003293 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294 if (out->pcm_device_id < 0) {
3295 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3296 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003297 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003298 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 }
3300
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003301 if (is_haptic_usecase) {
3302 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3303 if (adev->haptic_pcm_device_id < 0) {
3304 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3305 __func__, adev->haptic_pcm_device_id, out->usecase);
3306 ret = -EINVAL;
3307 goto error_config;
3308 }
3309 }
3310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003312
3313 if (!uc_info) {
3314 ret = -ENOMEM;
3315 goto error_config;
3316 }
3317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 uc_info->id = out->usecase;
3319 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003320 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003321 uc_info->devices = out->devices;
3322 uc_info->in_snd_device = SND_DEVICE_NONE;
3323 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003324
3325 /* This must be called before adding this usecase to the list */
3326 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3327 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3328 /* USB backend is not reopened immediately.
3329 This is eventually done as part of select_devices */
3330 }
3331
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003332 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303334 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3335 adev->perf_lock_opts,
3336 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303337
3338 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303339 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303340 if (audio_extn_passthru_is_enabled() &&
3341 audio_extn_passthru_is_passthrough_stream(out)) {
3342 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303343 }
3344 }
3345
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303346 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003347 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303348 if (!a2dp_combo) {
3349 check_a2dp_restore_l(adev, out, false);
3350 } else {
3351 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003352 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3353 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3354 else
3355 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303356 select_devices(adev, out->usecase);
3357 out->devices = dev;
3358 }
3359 } else {
3360 select_devices(adev, out->usecase);
3361 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003362
Arun Mirpurief53ce52018-09-11 18:00:09 -07003363 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3364 voice_set_device_mute_flag(adev, true);
3365
Derek Chenea197282019-01-07 17:35:01 -08003366 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3367 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003368
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003369 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3370 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003371
3372 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003373 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003374 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3375 ALOGE("%s: pcm stream not ready", __func__);
3376 goto error_open;
3377 }
3378 ret = pcm_start(out->pcm);
3379 if (ret < 0) {
3380 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3381 goto error_open;
3382 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003383 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003384 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003385 unsigned int flags = PCM_OUT;
3386 unsigned int pcm_open_retry_count = 0;
3387 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3388 flags |= PCM_MMAP | PCM_NOIRQ;
3389 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003390 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003391 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003392 } else
3393 flags |= PCM_MONOTONIC;
3394
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003395 if ((adev->vr_audio_mode_enabled) &&
3396 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3397 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3398 "PCM_Dev %d Topology", out->pcm_device_id);
3399 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3400 if (!ctl) {
3401 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3402 __func__, mixer_ctl_name);
3403 } else {
3404 //if success use ULLPP
3405 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3406 __func__, mixer_ctl_name, out->pcm_device_id);
3407 //There is a still a possibility that some sessions
3408 // that request for FAST|RAW when 3D audio is active
3409 //can go through ULLPP. Ideally we expects apps to
3410 //listen to audio focus and stop concurrent playback
3411 //Also, we will look for mode flag (voice_in_communication)
3412 //before enabling the realtime flag.
3413 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3414 }
3415 }
3416
Surendar Karka91fa3682018-07-02 18:12:12 +05303417 if (out->realtime)
3418 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3419 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3420
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003421 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3422 flags, pcm_open_retry_count,
3423 &(out->config));
3424 if (out->pcm == NULL) {
3425 ret = -EIO;
3426 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003427 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003428
3429 if (is_haptic_usecase) {
3430 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3431 adev->haptic_pcm_device_id,
3432 flags, pcm_open_retry_count,
3433 &(adev->haptics_config));
3434 // failure to open haptics pcm shouldnt stop audio,
3435 // so do not close audio pcm in case of error
3436 }
3437
Surendar Karka91fa3682018-07-02 18:12:12 +05303438 if (!out->realtime)
3439 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303440 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003441
Zhou Song2b8f28f2017-09-11 10:51:38 +08003442 // apply volume for voip playback after path is set up
3443 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3444 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303445 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3446 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303447 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3448 out->apply_volume = false;
3449 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003450 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003451 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303452 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003453 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3454 adev->dsp_bit_width_enforce_mode,
3455 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003457 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003458 out->compr = compress_open(adev->snd_card,
3459 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003460 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003461 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303462 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303463 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3464 adev->card_status = CARD_STATUS_OFFLINE;
3465 out->card_status = CARD_STATUS_OFFLINE;
3466 ret = -EIO;
3467 goto error_open;
3468 }
3469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003471 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003472 compress_close(out->compr);
3473 out->compr = NULL;
3474 ret = -EIO;
3475 goto error_open;
3476 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303477 /* compress_open sends params of the track, so reset the flag here */
3478 out->is_compr_metadata_avail = false;
3479
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003480 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003482
Fred Oh3f43e742015-03-04 18:42:34 -08003483 /* Since small bufs uses blocking writes, a write will be blocked
3484 for the default max poll time (20s) in the event of an SSR.
3485 Reduce the poll time to observe and deal with SSR faster.
3486 */
Ashish Jain5106d362016-05-11 19:23:33 +05303487 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003488 compress_set_max_poll_wait(out->compr, 1000);
3489 }
3490
Manish Dewangan69426c82017-01-30 17:35:36 +05303491 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303492 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303493
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003494 audio_extn_dts_create_state_notifier_node(out->usecase);
3495 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3496 popcount(out->channel_mask),
3497 out->playback_started);
3498
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003499#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303500 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003501 audio_extn_dolby_send_ddp_endp_params(adev);
3502#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303503 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3504 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003505 if (adev->visualizer_start_output != NULL)
3506 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3507 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303508 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003509 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003512
3513 if (ret == 0) {
3514 register_out_stream(out);
3515 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003516 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3517 ALOGE("%s: pcm stream not ready", __func__);
3518 goto error_open;
3519 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003520 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003521 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003522 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003523 if (ret < 0)
3524 goto error_open;
3525 }
3526 }
3527
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303528 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003529 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003530
Manish Dewangan21a850a2017-08-14 12:03:55 +05303531 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003532 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003533 if (ret < 0)
3534 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3535 }
3536
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003537 // consider a scenario where on pause lower layers are tear down.
3538 // so on resume, swap mixer control need to be sent only when
3539 // backend is active, hence rather than sending from enable device
3540 // sending it from start of streamtream
3541
3542 platform_set_swap_channels(adev, true);
3543
Haynes Mathew George380745d2017-10-04 15:27:45 -07003544 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303545 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003546 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003548 if (adev->haptic_pcm) {
3549 pcm_close(adev->haptic_pcm);
3550 adev->haptic_pcm = NULL;
3551 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303552 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003554error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303555 /*
3556 * sleep 50ms to allow sufficient time for kernel
3557 * drivers to recover incases like SSR.
3558 */
3559 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003560 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303561 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003562 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563}
3564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565static int check_input_parameters(uint32_t sample_rate,
3566 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003567 int channel_count,
3568 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003570 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303572 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3573 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3574 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003575 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003576 !audio_extn_compr_cap_format_supported(format) &&
3577 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003578 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003579
Aalique Grahame22e49102018-12-18 14:23:57 -08003580 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3581 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3582 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3583 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3584 return -EINVAL;
3585 }
3586
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003587 switch (channel_count) {
3588 case 1:
3589 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303590 case 3:
3591 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003592 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003593 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003594 break;
3595 default:
3596 ret = -EINVAL;
3597 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598
3599 switch (sample_rate) {
3600 case 8000:
3601 case 11025:
3602 case 12000:
3603 case 16000:
3604 case 22050:
3605 case 24000:
3606 case 32000:
3607 case 44100:
3608 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003609 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303610 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003611 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303612 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 break;
3614 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003615 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 }
3617
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003618 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619}
3620
Naresh Tanniru04f71882018-06-26 17:46:22 +05303621
3622/** Add a value in a list if not already present.
3623 * @return true if value was successfully inserted or already present,
3624 * false if the list is full and does not contain the value.
3625 */
3626static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3627 for (size_t i = 0; i < list_length; i++) {
3628 if (list[i] == value) return true; // value is already present
3629 if (list[i] == 0) { // no values in this slot
3630 list[i] = value;
3631 return true; // value inserted
3632 }
3633 }
3634 return false; // could not insert value
3635}
3636
3637/** Add channel_mask in supported_channel_masks if not already present.
3638 * @return true if channel_mask was successfully inserted or already present,
3639 * false if supported_channel_masks is full and does not contain channel_mask.
3640 */
3641static void register_channel_mask(audio_channel_mask_t channel_mask,
3642 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3643 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3644 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3645}
3646
3647/** Add format in supported_formats if not already present.
3648 * @return true if format was successfully inserted or already present,
3649 * false if supported_formats is full and does not contain format.
3650 */
3651static void register_format(audio_format_t format,
3652 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3653 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3654 "%s: stream can not declare supporting its format %x", __func__, format);
3655}
3656/** Add sample_rate in supported_sample_rates if not already present.
3657 * @return true if sample_rate was successfully inserted or already present,
3658 * false if supported_sample_rates is full and does not contain sample_rate.
3659 */
3660static void register_sample_rate(uint32_t sample_rate,
3661 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3662 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3663 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3664}
3665
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003666static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3667{
3668 uint32_t high = num1, low = num2, temp = 0;
3669
3670 if (!num1 || !num2)
3671 return 0;
3672
3673 if (num1 < num2) {
3674 high = num2;
3675 low = num1;
3676 }
3677
3678 while (low != 0) {
3679 temp = low;
3680 low = high % low;
3681 high = temp;
3682 }
3683 return (num1 * num2)/high;
3684}
3685
3686static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3687{
3688 uint32_t remainder = 0;
3689
3690 if (!multiplier)
3691 return num;
3692
3693 remainder = num % multiplier;
3694 if (remainder)
3695 num += (multiplier - remainder);
3696
3697 return num;
3698}
3699
Aalique Grahame22e49102018-12-18 14:23:57 -08003700static size_t get_stream_buffer_size(size_t duration_ms,
3701 uint32_t sample_rate,
3702 audio_format_t format,
3703 int channel_count,
3704 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705{
3706 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003707 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Aalique Grahame22e49102018-12-18 14:23:57 -08003709 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003710 if (is_low_latency)
3711 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303712
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003713 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003714 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Ralf Herzbd08d632018-09-28 15:50:49 +02003716 /* make sure the size is multiple of 32 bytes and additionally multiple of
3717 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003718 * At 48 kHz mono 16-bit PCM:
3719 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3720 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003721 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003722 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003723 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003724
3725 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726}
3727
Aalique Grahame22e49102018-12-18 14:23:57 -08003728static size_t get_input_buffer_size(uint32_t sample_rate,
3729 audio_format_t format,
3730 int channel_count,
3731 bool is_low_latency)
3732{
3733 /* Don't know if USB HIFI in this context so use true to be conservative */
3734 if (check_input_parameters(sample_rate, format, channel_count,
3735 true /*is_usb_hifi */) != 0)
3736 return 0;
3737
3738 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3739 sample_rate,
3740 format,
3741 channel_count,
3742 is_low_latency);
3743}
3744
Ashish Jain058165c2016-09-28 23:18:48 +05303745static size_t get_output_period_size(uint32_t sample_rate,
3746 audio_format_t format,
3747 int channel_count,
3748 int duration /*in millisecs*/)
3749{
3750 size_t size = 0;
3751 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3752
3753 if ((duration == 0) || (sample_rate == 0) ||
3754 (bytes_per_sample == 0) || (channel_count == 0)) {
3755 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3756 bytes_per_sample, channel_count);
3757 return -EINVAL;
3758 }
3759
3760 size = (sample_rate *
3761 duration *
3762 bytes_per_sample *
3763 channel_count) / 1000;
3764 /*
3765 * To have same PCM samples for all channels, the buffer size requires to
3766 * be multiple of (number of channels * bytes per sample)
3767 * For writes to succeed, the buffer must be written at address which is multiple of 32
3768 */
3769 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3770
3771 return (size/(channel_count * bytes_per_sample));
3772}
3773
Zhou Song48453a02018-01-10 17:50:59 +08003774static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303775{
3776 uint64_t actual_frames_rendered = 0;
3777 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3778
3779 /* This adjustment accounts for buffering after app processor.
3780 * It is based on estimated DSP latency per use case, rather than exact.
3781 */
3782 int64_t platform_latency = platform_render_latency(out->usecase) *
3783 out->sample_rate / 1000000LL;
3784
Zhou Song48453a02018-01-10 17:50:59 +08003785 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303786 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3787 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3788 * hence only estimate.
3789 */
3790 int64_t signed_frames = out->written - kernel_buffer_size;
3791
3792 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3793
Zhou Song48453a02018-01-10 17:50:59 +08003794 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303795 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003796 if (timestamp != NULL )
3797 *timestamp = out->writeAt;
3798 } else if (timestamp != NULL) {
3799 clock_gettime(CLOCK_MONOTONIC, timestamp);
3800 }
3801 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303802
3803 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3804 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3805 (long long int)out->written, (int)kernel_buffer_size,
3806 audio_bytes_per_sample(out->compr_config.codec->format),
3807 popcount(out->channel_mask));
3808
3809 return actual_frames_rendered;
3810}
3811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3813{
3814 struct stream_out *out = (struct stream_out *)stream;
3815
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003816 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817}
3818
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003819static int out_set_sample_rate(struct audio_stream *stream __unused,
3820 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821{
3822 return -ENOSYS;
3823}
3824
3825static size_t out_get_buffer_size(const struct audio_stream *stream)
3826{
3827 struct stream_out *out = (struct stream_out *)stream;
3828
Varun Balaraje49253e2017-07-06 19:48:56 +05303829 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303830 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303831 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303832 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3833 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3834 else
3835 return out->compr_config.fragment_size;
3836 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003837 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003838 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3839 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 +05303840 else if (is_offload_usecase(out->usecase) &&
3841 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303842 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003843
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003844 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003845 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846}
3847
3848static uint32_t out_get_channels(const struct audio_stream *stream)
3849{
3850 struct stream_out *out = (struct stream_out *)stream;
3851
3852 return out->channel_mask;
3853}
3854
3855static audio_format_t out_get_format(const struct audio_stream *stream)
3856{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003857 struct stream_out *out = (struct stream_out *)stream;
3858
3859 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860}
3861
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003862static int out_set_format(struct audio_stream *stream __unused,
3863 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864{
3865 return -ENOSYS;
3866}
3867
3868static int out_standby(struct audio_stream *stream)
3869{
3870 struct stream_out *out = (struct stream_out *)stream;
3871 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003872 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003873
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303874 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3875 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003877 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003879 if (adev->adm_deregister_stream)
3880 adev->adm_deregister_stream(adev->adm_data, out->handle);
3881
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003882 if (is_offload_usecase(out->usecase))
3883 stop_compressed_output_l(out);
3884
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003885 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003887 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3888 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303889 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003890 pthread_mutex_unlock(&adev->lock);
3891 pthread_mutex_unlock(&out->lock);
3892 ALOGD("VOIP output entered standby");
3893 return 0;
3894 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003895 if (out->pcm) {
3896 pcm_close(out->pcm);
3897 out->pcm = NULL;
3898 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003899 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3900 do_stop = out->playback_started;
3901 out->playback_started = false;
3902 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003903 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003904 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303905 out->send_next_track_params = false;
3906 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003907 out->gapless_mdata.encoder_delay = 0;
3908 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003909 if (out->compr != NULL) {
3910 compress_close(out->compr);
3911 out->compr = NULL;
3912 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003913 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003914 if (do_stop) {
3915 stop_output_stream(out);
3916 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003917 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 }
3919 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303920 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 return 0;
3922}
3923
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303924static int out_on_error(struct audio_stream *stream)
3925{
3926 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003927 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303928
3929 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003930 // always send CMD_ERROR for offload streams, this
3931 // is needed e.g. when SSR happens within compress_open
3932 // since the stream is active, offload_callback_thread is also active.
3933 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3934 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003935 }
3936 pthread_mutex_unlock(&out->lock);
3937
3938 status = out_standby(&out->stream.common);
3939
3940 lock_output_stream(out);
3941 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003942 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303943 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303944
3945 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3946 ALOGD("Setting previous card status if offline");
3947 out->prev_card_status_offline = true;
3948 }
3949
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303950 pthread_mutex_unlock(&out->lock);
3951
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003952 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303953}
3954
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303955/*
3956 *standby implementation without locks, assumes that the callee already
3957 *has taken adev and out lock.
3958 */
3959int out_standby_l(struct audio_stream *stream)
3960{
3961 struct stream_out *out = (struct stream_out *)stream;
3962 struct audio_device *adev = out->dev;
3963
3964 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3965 stream, out->usecase, use_case_table[out->usecase]);
3966
3967 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003968 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303969 if (adev->adm_deregister_stream)
3970 adev->adm_deregister_stream(adev->adm_data, out->handle);
3971
3972 if (is_offload_usecase(out->usecase))
3973 stop_compressed_output_l(out);
3974
3975 out->standby = true;
3976 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3977 voice_extn_compress_voip_close_output_stream(stream);
3978 out->started = 0;
3979 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003980 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303981 return 0;
3982 } else if (!is_offload_usecase(out->usecase)) {
3983 if (out->pcm) {
3984 pcm_close(out->pcm);
3985 out->pcm = NULL;
3986 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003987 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3988 if (adev->haptic_pcm) {
3989 pcm_close(adev->haptic_pcm);
3990 adev->haptic_pcm = NULL;
3991 }
3992
3993 if (adev->haptic_buffer != NULL) {
3994 free(adev->haptic_buffer);
3995 adev->haptic_buffer = NULL;
3996 adev->haptic_buffer_size = 0;
3997 }
3998 adev->haptic_pcm_device_id = 0;
3999 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304000 } else {
4001 ALOGD("copl(%p):standby", out);
4002 out->send_next_track_params = false;
4003 out->is_compr_metadata_avail = false;
4004 out->gapless_mdata.encoder_delay = 0;
4005 out->gapless_mdata.encoder_padding = 0;
4006 if (out->compr != NULL) {
4007 compress_close(out->compr);
4008 out->compr = NULL;
4009 }
4010 }
4011 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004012 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304013 }
4014 ALOGD("%s: exit", __func__);
4015 return 0;
4016}
4017
Aalique Grahame22e49102018-12-18 14:23:57 -08004018static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004019{
Aalique Grahame22e49102018-12-18 14:23:57 -08004020 struct stream_out *out = (struct stream_out *)stream;
4021
4022 // We try to get the lock for consistency,
4023 // but it isn't necessary for these variables.
4024 // If we're not in standby, we may be blocked on a write.
4025 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4026 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4027 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4028
4029 if (locked) {
4030 pthread_mutex_unlock(&out->lock);
4031 }
4032
4033 // dump error info
4034 (void)error_log_dump(
4035 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 return 0;
4038}
4039
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004040static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4041{
4042 int ret = 0;
4043 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004044
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004045 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004046 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004047 return -EINVAL;
4048 }
4049
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304050 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004051
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004052 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4053 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304054 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004055 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004056 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4057 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304058 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004059 }
4060
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004061 ALOGV("%s new encoder delay %u and padding %u", __func__,
4062 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4063
4064 return 0;
4065}
4066
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004067static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4068{
4069 return out == adev->primary_output || out == adev->voice_tx_output;
4070}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004071
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304072// note: this call is safe only if the stream_cb is
4073// removed first in close_output_stream (as is done now).
4074static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4075{
4076 if (!stream || !parms)
4077 return;
4078
4079 struct stream_out *out = (struct stream_out *)stream;
4080 struct audio_device *adev = out->dev;
4081
4082 card_status_t status;
4083 int card;
4084 if (parse_snd_card_status(parms, &card, &status) < 0)
4085 return;
4086
4087 pthread_mutex_lock(&adev->lock);
4088 bool valid_cb = (card == adev->snd_card);
4089 pthread_mutex_unlock(&adev->lock);
4090
4091 if (!valid_cb)
4092 return;
4093
4094 lock_output_stream(out);
4095 if (out->card_status != status)
4096 out->card_status = status;
4097 pthread_mutex_unlock(&out->lock);
4098
4099 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4100 use_case_table[out->usecase],
4101 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4102
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304103 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304104 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304105 if (voice_is_call_state_active(adev) &&
4106 out == adev->primary_output) {
4107 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4108 pthread_mutex_lock(&adev->lock);
4109 voice_stop_call(adev);
4110 adev->mode = AUDIO_MODE_NORMAL;
4111 pthread_mutex_unlock(&adev->lock);
4112 }
4113 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304114 return;
4115}
4116
Kevin Rocardfce19002017-08-07 19:21:36 -07004117static int get_alive_usb_card(struct str_parms* parms) {
4118 int card;
4119 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4120 !audio_extn_usb_alive(card)) {
4121 return card;
4122 }
4123 return -ENODEV;
4124}
4125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4127{
4128 struct stream_out *out = (struct stream_out *)stream;
4129 struct audio_device *adev = out->dev;
4130 struct str_parms *parms;
4131 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004132 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304133 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004134 bool reconfig = false;
4135 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136
sangwoobc677242013-08-08 16:53:43 +09004137 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004138 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304140 if (!parms)
4141 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004142 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4143 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004145 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004146 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004148 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004149 * When HDMI cable is unplugged the music playback is paused and
4150 * the policy manager sends routing=0. But the audioflinger continues
4151 * to write data until standby time (3sec). As the HDMI core is
4152 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004153 * Avoid this by routing audio to speaker until standby.
4154 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004155 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4156 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304157 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004158 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4159 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004160 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304161 /*
4162 * When A2DP is disconnected the
4163 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004164 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304165 * (3sec). As BT is turned off, the write gets blocked.
4166 * Avoid this by routing audio to speaker until standby.
4167 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004168 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004169 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004170 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304171 val = AUDIO_DEVICE_OUT_SPEAKER;
4172 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304173 /*
4174 * When USB headset is disconnected the music platback paused
4175 * and the policy manager send routing=0. But if the USB is connected
4176 * back before the standby time, AFE is not closed and opened
4177 * when USB is connected back. So routing to speker will guarantee
4178 * AFE reconfiguration and AFE will be opend once USB is connected again
4179 */
4180 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4181 (val == AUDIO_DEVICE_NONE) &&
4182 !audio_extn_usb_connected(parms)) {
4183 val = AUDIO_DEVICE_OUT_SPEAKER;
4184 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304185 /* To avoid a2dp to sco overlapping / BT device improper state
4186 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304187 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304188 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004189 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004190 if (val &
4191 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304192 //combo usecase just by pass a2dp
4193 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304194 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304195 } else {
4196 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4197 /* update device to a2dp and don't route as BT returned error
4198 * However it is still possible a2dp routing called because
4199 * of current active device disconnection (like wired headset)
4200 */
4201 out->devices = val;
4202 pthread_mutex_unlock(&out->lock);
4203 pthread_mutex_unlock(&adev->lock);
4204 goto error;
4205 }
4206 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304207 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004208
4209 audio_devices_t new_dev = val;
4210
4211 // Workaround: If routing to an non existing usb device, fail gracefully
4212 // The routing request will otherwise block during 10 second
4213 int card;
4214 if (audio_is_usb_out_device(new_dev) &&
4215 (card = get_alive_usb_card(parms)) >= 0) {
4216
4217 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4218 pthread_mutex_unlock(&adev->lock);
4219 pthread_mutex_unlock(&out->lock);
4220 ret = -ENOSYS;
4221 goto routing_fail;
4222 }
4223
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004224 /*
4225 * select_devices() call below switches all the usecases on the same
4226 * backend to the new device. Refer to check_usecases_codec_backend() in
4227 * the select_devices(). But how do we undo this?
4228 *
4229 * For example, music playback is active on headset (deep-buffer usecase)
4230 * and if we go to ringtones and select a ringtone, low-latency usecase
4231 * will be started on headset+speaker. As we can't enable headset+speaker
4232 * and headset devices at the same time, select_devices() switches the music
4233 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4234 * So when the ringtone playback is completed, how do we undo the same?
4235 *
4236 * We are relying on the out_set_parameters() call on deep-buffer output,
4237 * once the ringtone playback is ended.
4238 * NOTE: We should not check if the current devices are same as new devices.
4239 * Because select_devices() must be called to switch back the music
4240 * playback to headset.
4241 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004242 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004243 audio_devices_t new_dev = val;
4244 bool same_dev = out->devices == new_dev;
4245 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004246
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004247 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004248 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004249 if (adev->mode == AUDIO_MODE_IN_CALL) {
4250 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004251 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4252 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4253 audio_extn_usb_set_service_interval(true /*playback*/,
4254 service_interval,
4255 &reconfig);
4256 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4257 }
4258 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004259 }
4260 } else {
4261 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004262 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004263 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004264 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004265
4266 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004267 if (!same_dev) {
4268 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304269 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4270 adev->perf_lock_opts,
4271 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004272 if (adev->adm_on_routing_change)
4273 adev->adm_on_routing_change(adev->adm_data,
4274 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004275 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304276 if (!bypass_a2dp) {
4277 select_devices(adev, out->usecase);
4278 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004279 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4280 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4281 else
4282 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304283 select_devices(adev, out->usecase);
4284 out->devices = new_dev;
4285 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004286
4287 if (!same_dev) {
4288 // on device switch force swap, lower functions will make sure
4289 // to check if swap is allowed or not.
4290 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304291 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004292 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304293 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4294 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004295 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304296 pthread_mutex_lock(&out->compr_mute_lock);
4297 out->a2dp_compress_mute = false;
4298 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4299 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004300 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4301 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304302 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004303 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004304 }
4305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004307 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004308
4309 /*handles device and call state changes*/
4310 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004312 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004313
4314 if (out == adev->primary_output) {
4315 pthread_mutex_lock(&adev->lock);
4316 audio_extn_set_parameters(adev, parms);
4317 pthread_mutex_unlock(&adev->lock);
4318 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004319 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004320 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004321 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004322
4323 audio_extn_dts_create_state_notifier_node(out->usecase);
4324 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4325 popcount(out->channel_mask),
4326 out->playback_started);
4327
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004328 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004329 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004330
Surendar Karkaf51b5842018-04-26 11:28:38 +05304331 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4332 sizeof(value));
4333 if (err >= 0) {
4334 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4335 audio_extn_send_dual_mono_mixing_coefficients(out);
4336 }
4337
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304338 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4339 if (err >= 0) {
4340 strlcpy(out->profile, value, sizeof(out->profile));
4341 ALOGV("updating stream profile with value '%s'", out->profile);
4342 lock_output_stream(out);
4343 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4344 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004345 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304346 out->sample_rate, out->bit_width,
4347 out->channel_mask, out->profile,
4348 &out->app_type_cfg);
4349 pthread_mutex_unlock(&out->lock);
4350 }
4351
Alexy Joseph98988832017-01-13 14:56:59 -08004352 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004353 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4354 // and vendor.audio.hal.output.suspend.supported is set to true
4355 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004356 //check suspend parameter only for low latency and if the property
4357 //is enabled
4358 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4359 ALOGI("%s: got suspend_playback %s", __func__, value);
4360 lock_output_stream(out);
4361 if (!strncmp(value, "false", 5)) {
4362 //suspend_playback=false is supposed to set QOS value back to 75%
4363 //the mixer control sent with value Enable will achieve that
4364 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4365 } else if (!strncmp (value, "true", 4)) {
4366 //suspend_playback=true is supposed to remove QOS value
4367 //resetting the mixer control will set the default value
4368 //for the mixer control which is Disable and this removes the QOS vote
4369 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4370 } else {
4371 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4372 " got %s", __func__, value);
4373 ret = -1;
4374 }
4375
4376 if (ret != 0) {
4377 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4378 __func__, out->pm_qos_mixer_path, ret);
4379 }
4380
4381 pthread_mutex_unlock(&out->lock);
4382 }
4383 }
4384 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304386error:
Eric Laurent994a6932013-07-17 11:51:42 -07004387 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 return ret;
4389}
4390
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004391static bool stream_get_parameter_channels(struct str_parms *query,
4392 struct str_parms *reply,
4393 audio_channel_mask_t *supported_channel_masks) {
4394 int ret = -1;
4395 char value[512];
4396 bool first = true;
4397 size_t i, j;
4398
4399 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4400 ret = 0;
4401 value[0] = '\0';
4402 i = 0;
4403 while (supported_channel_masks[i] != 0) {
4404 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4405 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4406 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304407 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004408
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304409 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004410 first = false;
4411 break;
4412 }
4413 }
4414 i++;
4415 }
4416 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4417 }
4418 return ret == 0;
4419}
4420
4421static bool stream_get_parameter_formats(struct str_parms *query,
4422 struct str_parms *reply,
4423 audio_format_t *supported_formats) {
4424 int ret = -1;
4425 char value[256];
4426 size_t i, j;
4427 bool first = true;
4428
4429 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4430 ret = 0;
4431 value[0] = '\0';
4432 i = 0;
4433 while (supported_formats[i] != 0) {
4434 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4435 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4436 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304437 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004438 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304439 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004440 first = false;
4441 break;
4442 }
4443 }
4444 i++;
4445 }
4446 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4447 }
4448 return ret == 0;
4449}
4450
4451static bool stream_get_parameter_rates(struct str_parms *query,
4452 struct str_parms *reply,
4453 uint32_t *supported_sample_rates) {
4454
4455 int i;
4456 char value[256];
4457 int ret = -1;
4458 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4459 ret = 0;
4460 value[0] = '\0';
4461 i=0;
4462 int cursor = 0;
4463 while (supported_sample_rates[i]) {
4464 int avail = sizeof(value) - cursor;
4465 ret = snprintf(value + cursor, avail, "%s%d",
4466 cursor > 0 ? "|" : "",
4467 supported_sample_rates[i]);
4468 if (ret < 0 || ret >= avail) {
4469 // if cursor is at the last element of the array
4470 // overwrite with \0 is duplicate work as
4471 // snprintf already put a \0 in place.
4472 // else
4473 // we had space to write the '|' at value[cursor]
4474 // (which will be overwritten) or no space to fill
4475 // the first element (=> cursor == 0)
4476 value[cursor] = '\0';
4477 break;
4478 }
4479 cursor += ret;
4480 ++i;
4481 }
4482 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4483 value);
4484 }
4485 return ret >= 0;
4486}
4487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4489{
4490 struct stream_out *out = (struct stream_out *)stream;
4491 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004492 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 char value[256];
4494 struct str_parms *reply = str_parms_create();
4495 size_t i, j;
4496 int ret;
4497 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004498
4499 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004500 if (reply) {
4501 str_parms_destroy(reply);
4502 }
4503 if (query) {
4504 str_parms_destroy(query);
4505 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004506 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4507 return NULL;
4508 }
4509
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004510 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4512 if (ret >= 0) {
4513 value[0] = '\0';
4514 i = 0;
4515 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004516 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4517 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004519 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004521 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 first = false;
4523 break;
4524 }
4525 }
4526 i++;
4527 }
4528 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4529 str = str_parms_to_str(reply);
4530 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004531 voice_extn_out_get_parameters(out, query, reply);
4532 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004534
Alexy Joseph62142aa2015-11-16 15:10:34 -08004535
4536 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4537 if (ret >= 0) {
4538 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304539 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4540 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004541 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304542 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004543 } else {
4544 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304545 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004546 }
4547 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004548 if (str)
4549 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004550 str = str_parms_to_str(reply);
4551 }
4552
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004553 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4554 if (ret >= 0) {
4555 value[0] = '\0';
4556 i = 0;
4557 first = true;
4558 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004559 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4560 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004561 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004562 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004563 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004564 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004565 first = false;
4566 break;
4567 }
4568 }
4569 i++;
4570 }
4571 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004572 if (str)
4573 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004574 str = str_parms_to_str(reply);
4575 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004576
4577 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4578 if (ret >= 0) {
4579 value[0] = '\0';
4580 i = 0;
4581 first = true;
4582 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004583 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4584 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004585 if (!first) {
4586 strlcat(value, "|", sizeof(value));
4587 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004588 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004589 first = false;
4590 break;
4591 }
4592 }
4593 i++;
4594 }
4595 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4596 if (str)
4597 free(str);
4598 str = str_parms_to_str(reply);
4599 }
4600
Alexy Joseph98988832017-01-13 14:56:59 -08004601 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4602 //only low latency track supports suspend_resume
4603 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004604 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004605 if (str)
4606 free(str);
4607 str = str_parms_to_str(reply);
4608 }
4609
4610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 str_parms_destroy(query);
4612 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004613 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 return str;
4615}
4616
4617static uint32_t out_get_latency(const struct audio_stream_out *stream)
4618{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004619 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004621 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622
Alexy Josephaa54c872014-12-03 02:46:47 -08004623 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304624 lock_output_stream(out);
4625 latency = audio_extn_utils_compress_get_dsp_latency(out);
4626 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004627 } else if ((out->realtime) ||
4628 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004629 // since the buffer won't be filled up faster than realtime,
4630 // return a smaller number
4631 if (out->config.rate)
4632 period_ms = (out->af_period_multiplier * out->config.period_size *
4633 1000) / (out->config.rate);
4634 else
4635 period_ms = 0;
4636 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004637 } else {
4638 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004639 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004640 }
4641
yidongh0515e042017-07-06 15:00:34 +08004642 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004643 latency += audio_extn_a2dp_get_encoder_latency();
4644
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304645 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004646 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647}
4648
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304649static float AmpToDb(float amplification)
4650{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304651 float db = DSD_VOLUME_MIN_DB;
4652 if (amplification > 0) {
4653 db = 20 * log10(amplification);
4654 if(db < DSD_VOLUME_MIN_DB)
4655 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304656 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304657 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304658}
4659
Arun Mirpuri5d170872019-03-26 13:21:31 -07004660static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4661 float right)
4662{
4663 struct stream_out *out = (struct stream_out *)stream;
4664 long volume = 0;
4665 char mixer_ctl_name[128] = "";
4666 struct audio_device *adev = out->dev;
4667 struct mixer_ctl *ctl = NULL;
4668 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4669 PCM_PLAYBACK);
4670
4671 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4672 "Playback %d Volume", pcm_device_id);
4673 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4674 if (!ctl) {
4675 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4676 __func__, mixer_ctl_name);
4677 return -EINVAL;
4678 }
4679 if (left != right)
4680 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4681 __func__, left, right);
4682 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4683 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4684 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4685 __func__, mixer_ctl_name, volume);
4686 return -EINVAL;
4687 }
4688 return 0;
4689}
4690
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304691static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4692 float right)
4693{
4694 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304695 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304696 char mixer_ctl_name[128];
4697 struct audio_device *adev = out->dev;
4698 struct mixer_ctl *ctl;
4699 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4700 PCM_PLAYBACK);
4701
4702 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4703 "Compress Playback %d Volume", pcm_device_id);
4704 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4705 if (!ctl) {
4706 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4707 __func__, mixer_ctl_name);
4708 return -EINVAL;
4709 }
4710 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4711 __func__, mixer_ctl_name, left, right);
4712 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4713 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4714 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4715
4716 return 0;
4717}
4718
Zhou Song2b8f28f2017-09-11 10:51:38 +08004719static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4720 float right)
4721{
4722 struct stream_out *out = (struct stream_out *)stream;
4723 char mixer_ctl_name[] = "App Type Gain";
4724 struct audio_device *adev = out->dev;
4725 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304726 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004727
4728 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4729 if (!ctl) {
4730 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4731 __func__, mixer_ctl_name);
4732 return -EINVAL;
4733 }
4734
4735 set_values[0] = 0; //0: Rx Session 1:Tx Session
4736 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304737 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4738 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004739
4740 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4741 return 0;
4742}
4743
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304744static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4745 float right)
4746{
4747 struct stream_out *out = (struct stream_out *)stream;
4748 /* Volume control for pcm playback */
4749 if (left != right) {
4750 return -EINVAL;
4751 } else {
4752 char mixer_ctl_name[128];
4753 struct audio_device *adev = out->dev;
4754 struct mixer_ctl *ctl;
4755 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4756 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4757 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4758 if (!ctl) {
4759 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4760 return -EINVAL;
4761 }
4762
4763 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4764 int ret = mixer_ctl_set_value(ctl, 0, volume);
4765 if (ret < 0) {
4766 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4767 return -EINVAL;
4768 }
4769
4770 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4771
4772 return 0;
4773 }
4774}
4775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004776static int out_set_volume(struct audio_stream_out *stream, float left,
4777 float right)
4778{
Eric Laurenta9024de2013-04-04 09:19:12 -07004779 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004780 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304781 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004782
Arun Mirpuri5d170872019-03-26 13:21:31 -07004783 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004784 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4785 /* only take left channel into account: the API is for stereo anyway */
4786 out->muted = (left == 0.0f);
4787 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004788 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304789 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004790 /*
4791 * Set mute or umute on HDMI passthrough stream.
4792 * Only take left channel into account.
4793 * Mute is 0 and unmute 1
4794 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304795 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304796 } else if (out->format == AUDIO_FORMAT_DSD){
4797 char mixer_ctl_name[128] = "DSD Volume";
4798 struct audio_device *adev = out->dev;
4799 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4800
4801 if (!ctl) {
4802 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4803 __func__, mixer_ctl_name);
4804 return -EINVAL;
4805 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304806 volume[0] = (long)(AmpToDb(left));
4807 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304808 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4809 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004810 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304811 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004812 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304813 if (!out->a2dp_compress_mute)
4814 ret = out_set_compr_volume(stream, left, right);
4815 out->volume_l = left;
4816 out->volume_r = right;
4817 pthread_mutex_unlock(&out->compr_mute_lock);
4818 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004819 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004820 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004821 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4822 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4823 if (!out->standby) {
4824 audio_extn_utils_send_app_type_gain(out->dev,
4825 out->app_type_cfg.app_type,
4826 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004827 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004828 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004829 out->volume_l = left;
4830 out->volume_r = right;
4831 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004832 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4833 ALOGV("%s: MMAP set volume called", __func__);
4834 if (!out->standby)
4835 ret = out_set_mmap_volume(stream, left, right);
4836 out->volume_l = left;
4837 out->volume_r = right;
4838 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304839 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304840 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4841 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304842 /* Volume control for pcm playback */
4843 if (!out->standby)
4844 ret = out_set_pcm_volume(stream, left, right);
4845 else
4846 out->apply_volume = true;
4847
4848 out->volume_l = left;
4849 out->volume_r = right;
4850 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004851 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853 return -ENOSYS;
4854}
4855
Zhou Songc9672822017-08-16 16:01:39 +08004856static void update_frames_written(struct stream_out *out, size_t bytes)
4857{
4858 size_t bpf = 0;
4859
4860 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4861 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4862 bpf = 1;
4863 else if (!is_offload_usecase(out->usecase))
4864 bpf = audio_bytes_per_sample(out->format) *
4865 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004866
4867 pthread_mutex_lock(&out->position_query_lock);
4868 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004869 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004870 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4871 }
4872 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004873}
4874
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004875int split_and_write_audio_haptic_data(struct stream_out *out,
4876 const void *buffer, size_t bytes_to_write)
4877{
4878 struct audio_device *adev = out->dev;
4879
4880 int ret = 0;
4881 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4882 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4883 size_t frame_size = channel_count * bytes_per_sample;
4884 size_t frame_count = bytes_to_write / frame_size;
4885
4886 bool force_haptic_path =
4887 property_get_bool("vendor.audio.test_haptic", false);
4888
4889 // extract Haptics data from Audio buffer
4890 bool alloc_haptic_buffer = false;
4891 int haptic_channel_count = adev->haptics_config.channels;
4892 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4893 size_t audio_frame_size = frame_size - haptic_frame_size;
4894 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4895
4896 if (adev->haptic_buffer == NULL) {
4897 alloc_haptic_buffer = true;
4898 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4899 free(adev->haptic_buffer);
4900 adev->haptic_buffer_size = 0;
4901 alloc_haptic_buffer = true;
4902 }
4903
4904 if (alloc_haptic_buffer) {
4905 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4906 adev->haptic_buffer_size = total_haptic_buffer_size;
4907 }
4908
4909 size_t src_index = 0, aud_index = 0, hap_index = 0;
4910 uint8_t *audio_buffer = (uint8_t *)buffer;
4911 uint8_t *haptic_buffer = adev->haptic_buffer;
4912
4913 // This is required for testing only. This works for stereo data only.
4914 // One channel is fed to audio stream and other to haptic stream for testing.
4915 if (force_haptic_path)
4916 audio_frame_size = haptic_frame_size = bytes_per_sample;
4917
4918 for (size_t i = 0; i < frame_count; i++) {
4919 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4920 audio_frame_size);
4921 aud_index += audio_frame_size;
4922 src_index += audio_frame_size;
4923
4924 if (adev->haptic_pcm)
4925 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4926 haptic_frame_size);
4927 hap_index += haptic_frame_size;
4928 src_index += haptic_frame_size;
4929
4930 // This is required for testing only.
4931 // Discard haptic channel data.
4932 if (force_haptic_path)
4933 src_index += haptic_frame_size;
4934 }
4935
4936 // write to audio pipeline
4937 ret = pcm_write(out->pcm, (void *)audio_buffer,
4938 frame_count * audio_frame_size);
4939
4940 // write to haptics pipeline
4941 if (adev->haptic_pcm)
4942 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4943 frame_count * haptic_frame_size);
4944
4945 return ret;
4946}
4947
Aalique Grahame22e49102018-12-18 14:23:57 -08004948#ifdef NO_AUDIO_OUT
4949static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4950 const void *buffer __unused, size_t bytes)
4951{
4952 struct stream_out *out = (struct stream_out *)stream;
4953
4954 /* No Output device supported other than BT for playback.
4955 * Sleep for the amount of buffer duration
4956 */
4957 lock_output_stream(out);
4958 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4959 (const struct audio_stream_out *)&out->stream) /
4960 out_get_sample_rate(&out->stream.common));
4961 pthread_mutex_unlock(&out->lock);
4962 return bytes;
4963}
4964#endif
4965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4967 size_t bytes)
4968{
4969 struct stream_out *out = (struct stream_out *)stream;
4970 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004971 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304972 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004973 const size_t frame_size = audio_stream_out_frame_size(stream);
4974 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05304975 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976
Haynes Mathew George380745d2017-10-04 15:27:45 -07004977 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004978 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304979
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304980 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004981
Dhananjay Kumarac341582017-02-23 23:42:25 +05304982 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304983 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304984 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4985 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004986 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304987 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304988 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304989 ALOGD(" %s: sound card is not active/SSR state", __func__);
4990 ret= -EIO;
4991 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304992 }
4993 }
4994
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304995 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304996 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304997 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304998 goto exit;
4999 }
5000
Haynes Mathew George16081042017-05-31 17:16:49 -07005001 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5002 ret = -EINVAL;
5003 goto exit;
5004 }
5005
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305006 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5007 !out->is_iec61937_info_available) {
5008
5009 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5010 out->is_iec61937_info_available = true;
5011 } else if (audio_extn_passthru_is_enabled()) {
5012 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305013 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305014
5015 if((out->format == AUDIO_FORMAT_DTS) ||
5016 (out->format == AUDIO_FORMAT_DTS_HD)) {
5017 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5018 buffer, bytes);
5019 if (ret) {
5020 if (ret != -ENOSYS) {
5021 out->is_iec61937_info_available = false;
5022 ALOGD("iec61937 transmission info not yet updated retry");
5023 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305024 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305025 /* if stream has started and after that there is
5026 * stream config change (iec transmission config)
5027 * then trigger select_device to update backend configuration.
5028 */
5029 out->stream_config_changed = true;
5030 pthread_mutex_lock(&adev->lock);
5031 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305032 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
5033 ret = -EINVAL;
5034 goto exit;
5035 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305036 pthread_mutex_unlock(&adev->lock);
5037 out->stream_config_changed = false;
5038 out->is_iec61937_info_available = true;
5039 }
5040 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305041
Garmond Leung317cbf12017-09-13 16:20:50 -07005042 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305043 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5044 (out->is_iec61937_info_available == true)) {
5045 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5046 ret = -EINVAL;
5047 goto exit;
5048 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305049 }
5050 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305051
5052 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005053 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005054 if (!(out->devices &
5055 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305056 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305057 ret = -EIO;
5058 goto exit;
5059 }
5060 }
5061 }
5062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005064 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005065 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005066 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5067 ret = voice_extn_compress_voip_start_output_stream(out);
5068 else
5069 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005070 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005071 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005073 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005074 goto exit;
5075 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305076 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005077 if (last_known_cal_step != -1) {
5078 ALOGD("%s: retry previous failed cal level set", __func__);
5079 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305080 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005081 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305082
5083 if ((out->is_iec61937_info_available == true) &&
5084 (audio_extn_passthru_is_passthrough_stream(out))&&
5085 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5086 ret = -EINVAL;
5087 goto exit;
5088 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305089 if (out->set_dual_mono)
5090 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005092
Ashish Jain81eb2a82015-05-13 10:52:34 +05305093 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005094 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305095 adev->is_channel_status_set = true;
5096 }
5097
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305098 if ((adev->use_old_pspd_mix_ctrl == true) &&
5099 (out->pspd_coeff_sent == false)) {
5100 /*
5101 * Need to resend pspd coefficients after stream started for
5102 * older kernel version as it does not save the coefficients
5103 * and also stream has to be started for coeff to apply.
5104 */
5105 usecase = get_usecase_from_list(adev, out->usecase);
5106 if (usecase != NULL) {
5107 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5108 out->pspd_coeff_sent = true;
5109 }
5110 }
5111
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005112 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005113 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005114 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005115 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005116 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5117 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305118 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5119 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005120 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305121 out->send_next_track_params = false;
5122 out->is_compr_metadata_avail = false;
5123 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005124 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305125 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305126 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005127
Ashish Jain83a6cc22016-06-28 14:34:17 +05305128 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305129 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305130 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305131 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005132 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305133 return -EINVAL;
5134 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305135 audio_format_t dst_format = out->hal_op_format;
5136 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305137
Dieter Luecking5d57def2018-09-07 14:23:37 +02005138 /* prevent division-by-zero */
5139 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5140 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5141 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5142 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305143 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005144 ATRACE_END();
5145 return -EINVAL;
5146 }
5147
Ashish Jainf1eaa582016-05-23 20:54:24 +05305148 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5149 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5150
Ashish Jain83a6cc22016-06-28 14:34:17 +05305151 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305152 dst_format,
5153 buffer,
5154 src_format,
5155 frames);
5156
Ashish Jain83a6cc22016-06-28 14:34:17 +05305157 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305158 bytes_to_write);
5159
5160 /*Convert written bytes in audio flinger format*/
5161 if (ret > 0)
5162 ret = ((ret * format_to_bitwidth_table[out->format]) /
5163 format_to_bitwidth_table[dst_format]);
5164 }
5165 } else
5166 ret = compress_write(out->compr, buffer, bytes);
5167
Zhou Songc9672822017-08-16 16:01:39 +08005168 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5169 update_frames_written(out, bytes);
5170
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305171 if (ret < 0)
5172 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005173 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305174 /*msg to cb thread only if non blocking write is enabled*/
5175 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305176 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005177 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305178 } else if (-ENETRESET == ret) {
5179 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305180 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305181 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305182 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005183 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305184 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005185 }
Ashish Jain5106d362016-05-11 19:23:33 +05305186
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305187 /* Call compr start only when non-zero bytes of data is there to be rendered */
5188 if (!out->playback_started && ret > 0) {
5189 int status = compress_start(out->compr);
5190 if (status < 0) {
5191 ret = status;
5192 ALOGE("%s: compr start failed with err %d", __func__, errno);
5193 goto exit;
5194 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005195 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005196 out->playback_started = 1;
5197 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005198
5199 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5200 popcount(out->channel_mask),
5201 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005202 }
5203 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005204 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005205 return ret;
5206 } else {
5207 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005208 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005209 if (out->muted)
5210 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005211 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5212 __func__, frames, frame_size, bytes_to_write);
5213
Aalique Grahame22e49102018-12-18 14:23:57 -08005214 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005215 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005216 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5217 int16_t *src = (int16_t *)buffer;
5218 int16_t *dst = (int16_t *)buffer;
5219
5220 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5221 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005222 "out_write called for %s use case with wrong properties",
5223 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005224
5225 /*
5226 * FIXME: this can be removed once audio flinger mixer supports
5227 * mono output
5228 */
5229
5230 /*
5231 * Code below goes over each frame in the buffer and adds both
5232 * L and R samples and then divides by 2 to convert to mono
5233 */
5234 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5235 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5236 }
5237 bytes_to_write /= 2;
5238 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005239
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305240 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005241
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005242 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005243
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005244 if (out->config.rate)
5245 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5246 out->config.rate;
5247
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005248 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005249 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5250
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005251 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005252 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005253 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305254 out->convert_buffer != NULL) {
5255
5256 memcpy_by_audio_format(out->convert_buffer,
5257 out->hal_op_format,
5258 buffer,
5259 out->hal_ip_format,
5260 out->config.period_size * out->config.channels);
5261
5262 ret = pcm_write(out->pcm, out->convert_buffer,
5263 (out->config.period_size *
5264 out->config.channels *
5265 format_to_bitwidth_table[out->hal_op_format]));
5266 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305267 /*
5268 * To avoid underrun in DSP when the application is not pumping
5269 * data at required rate, check for the no. of bytes and ignore
5270 * pcm_write if it is less than actual buffer size.
5271 * It is a work around to a change in compress VOIP driver.
5272 */
5273 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5274 bytes < (out->config.period_size * out->config.channels *
5275 audio_bytes_per_sample(out->format))) {
5276 size_t voip_buf_size =
5277 out->config.period_size * out->config.channels *
5278 audio_bytes_per_sample(out->format);
5279 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5280 __func__, bytes, voip_buf_size);
5281 usleep(((uint64_t)voip_buf_size - bytes) *
5282 1000000 / audio_stream_out_frame_size(stream) /
5283 out_get_sample_rate(&out->stream.common));
5284 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005285 } else {
5286 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5287 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5288 else
5289 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5290 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305291 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005292
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005293 release_out_focus(out);
5294
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305295 if (ret < 0)
5296 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005297 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305298 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300 }
5301
5302exit:
Zhou Songc9672822017-08-16 16:01:39 +08005303 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305304 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305305 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005307 pthread_mutex_unlock(&out->lock);
5308
5309 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005310 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005311 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305312 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305313 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305314 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305315 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305316 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305317 out->standby = true;
5318 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305319 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005320 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5321 /* prevent division-by-zero */
5322 uint32_t stream_size = audio_stream_out_frame_size(stream);
5323 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005324
Dieter Luecking5d57def2018-09-07 14:23:37 +02005325 if ((stream_size == 0) || (srate == 0)) {
5326 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5327 ATRACE_END();
5328 return -EINVAL;
5329 }
5330 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5331 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005332 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305333 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005334 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005335 return ret;
5336 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005337 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005338 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339 return bytes;
5340}
5341
5342static int out_get_render_position(const struct audio_stream_out *stream,
5343 uint32_t *dsp_frames)
5344{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005345 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005346
5347 if (dsp_frames == NULL)
5348 return -EINVAL;
5349
5350 *dsp_frames = 0;
5351 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005352 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305353
5354 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5355 * this operation and adev_close_output_stream(where out gets reset).
5356 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305357 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005358 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305359 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005360 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305361 return 0;
5362 }
5363
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005364 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305365 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305366 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005367 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305368 if (ret < 0)
5369 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005370 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305371 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005372 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305373 if (-ENETRESET == ret) {
5374 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305375 out->card_status = CARD_STATUS_OFFLINE;
5376 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305377 } else if(ret < 0) {
5378 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305379 ret = -EINVAL;
5380 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305381 /*
5382 * Handle corner case where compress session is closed during SSR
5383 * and timestamp is queried
5384 */
5385 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305386 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305387 } else if (out->prev_card_status_offline) {
5388 ALOGE("ERROR: previously sound card was offline,return error");
5389 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305390 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305391 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005392 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305393 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305394 pthread_mutex_unlock(&out->lock);
5395 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005396 } else if (audio_is_linear_pcm(out->format)) {
5397 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005398 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005399 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005400 } else
5401 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402}
5403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005404static int out_add_audio_effect(const struct audio_stream *stream __unused,
5405 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005406{
5407 return 0;
5408}
5409
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005410static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5411 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005412{
5413 return 0;
5414}
5415
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005416static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5417 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005418{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305419 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420}
5421
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005422static int out_get_presentation_position(const struct audio_stream_out *stream,
5423 uint64_t *frames, struct timespec *timestamp)
5424{
5425 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305426 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005427 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005428
Ashish Jain5106d362016-05-11 19:23:33 +05305429 /* below piece of code is not guarded against any lock because audioFliner serializes
5430 * this operation and adev_close_output_stream( where out gets reset).
5431 */
5432 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305433 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005434 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305435 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5436 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5437 return 0;
5438 }
5439
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005440 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005441
Ashish Jain5106d362016-05-11 19:23:33 +05305442 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5443 ret = compress_get_tstamp(out->compr, &dsp_frames,
5444 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005445 // Adjustment accounts for A2dp encoder latency with offload usecases
5446 // Note: Encoder latency is returned in ms.
5447 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5448 unsigned long offset =
5449 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5450 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5451 }
Ashish Jain5106d362016-05-11 19:23:33 +05305452 ALOGVV("%s rendered frames %ld sample_rate %d",
5453 __func__, dsp_frames, out->sample_rate);
5454 *frames = dsp_frames;
5455 if (ret < 0)
5456 ret = -errno;
5457 if (-ENETRESET == ret) {
5458 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305459 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305460 ret = -EINVAL;
5461 } else
5462 ret = 0;
5463 /* this is the best we can do */
5464 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005465 } else {
5466 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005467 unsigned int avail;
5468 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5469 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5470 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5471 // This adjustment accounts for buffering after app processor.
5472 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005473 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005474 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005475
Weiyin Jiangd4633762018-03-16 12:05:03 +08005476 // Adjustment accounts for A2dp encoder latency with non offload usecases
5477 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5478 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5479 signed_frames -=
5480 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5481 }
5482
5483 // It would be unusual for this value to be negative, but check just in case ...
5484 if (signed_frames >= 0) {
5485 *frames = signed_frames;
5486 ret = 0;
5487 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005488 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305489 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305490 *frames = out->written;
5491 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305492 if (is_offload_usecase(out->usecase))
5493 ret = -EINVAL;
5494 else
5495 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005496 }
5497 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005498 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005499 return ret;
5500}
5501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005502static int out_set_callback(struct audio_stream_out *stream,
5503 stream_callback_t callback, void *cookie)
5504{
5505 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005506 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005507
5508 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005509 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005510 out->client_callback = callback;
5511 out->client_cookie = cookie;
5512 if (out->adsp_hdlr_stream_handle) {
5513 ret = audio_extn_adsp_hdlr_stream_set_callback(
5514 out->adsp_hdlr_stream_handle,
5515 callback,
5516 cookie);
5517 if (ret)
5518 ALOGW("%s:adsp hdlr callback registration failed %d",
5519 __func__, ret);
5520 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005521 pthread_mutex_unlock(&out->lock);
5522 return 0;
5523}
5524
5525static int out_pause(struct audio_stream_out* stream)
5526{
5527 struct stream_out *out = (struct stream_out *)stream;
5528 int status = -ENOSYS;
5529 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005530 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005531 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005532 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005533 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305534 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305535 status = compress_pause(out->compr);
5536
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005537 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005538
Mingming Yin21854652016-04-13 11:54:02 -07005539 if (audio_extn_passthru_is_active()) {
5540 ALOGV("offload use case, pause passthru");
5541 audio_extn_passthru_on_pause(out);
5542 }
5543
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305544 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005545 audio_extn_dts_notify_playback_state(out->usecase, 0,
5546 out->sample_rate, popcount(out->channel_mask),
5547 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005548 }
5549 pthread_mutex_unlock(&out->lock);
5550 }
5551 return status;
5552}
5553
5554static int out_resume(struct audio_stream_out* stream)
5555{
5556 struct stream_out *out = (struct stream_out *)stream;
5557 int status = -ENOSYS;
5558 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005559 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005560 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005561 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005562 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005563 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305564 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305565 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005566 }
5567 if (!status) {
5568 out->offload_state = OFFLOAD_STATE_PLAYING;
5569 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305570 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005571 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5572 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005573 }
5574 pthread_mutex_unlock(&out->lock);
5575 }
5576 return status;
5577}
5578
5579static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5580{
5581 struct stream_out *out = (struct stream_out *)stream;
5582 int status = -ENOSYS;
5583 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005584 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005585 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005586 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5587 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5588 else
5589 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5590 pthread_mutex_unlock(&out->lock);
5591 }
5592 return status;
5593}
5594
5595static int out_flush(struct audio_stream_out* stream)
5596{
5597 struct stream_out *out = (struct stream_out *)stream;
5598 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005599 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005600 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005601 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005602 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5603 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005604 } else {
5605 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5606 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005607 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005608 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005609 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 return 0;
5611 }
5612 return -ENOSYS;
5613}
5614
Haynes Mathew George16081042017-05-31 17:16:49 -07005615static int out_stop(const struct audio_stream_out* stream)
5616{
5617 struct stream_out *out = (struct stream_out *)stream;
5618 struct audio_device *adev = out->dev;
5619 int ret = -ENOSYS;
5620
5621 ALOGV("%s", __func__);
5622 pthread_mutex_lock(&adev->lock);
5623 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5624 out->playback_started && out->pcm != NULL) {
5625 pcm_stop(out->pcm);
5626 ret = stop_output_stream(out);
5627 out->playback_started = false;
5628 }
5629 pthread_mutex_unlock(&adev->lock);
5630 return ret;
5631}
5632
5633static int out_start(const struct audio_stream_out* stream)
5634{
5635 struct stream_out *out = (struct stream_out *)stream;
5636 struct audio_device *adev = out->dev;
5637 int ret = -ENOSYS;
5638
5639 ALOGV("%s", __func__);
5640 pthread_mutex_lock(&adev->lock);
5641 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5642 !out->playback_started && out->pcm != NULL) {
5643 ret = start_output_stream(out);
5644 if (ret == 0) {
5645 out->playback_started = true;
5646 }
5647 }
5648 pthread_mutex_unlock(&adev->lock);
5649 return ret;
5650}
5651
5652/*
5653 * Modify config->period_count based on min_size_frames
5654 */
5655static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5656{
5657 int periodCountRequested = (min_size_frames + config->period_size - 1)
5658 / config->period_size;
5659 int periodCount = MMAP_PERIOD_COUNT_MIN;
5660
5661 ALOGV("%s original config.period_size = %d config.period_count = %d",
5662 __func__, config->period_size, config->period_count);
5663
5664 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5665 periodCount *= 2;
5666 }
5667 config->period_count = periodCount;
5668
5669 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5670}
5671
5672static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5673 int32_t min_size_frames,
5674 struct audio_mmap_buffer_info *info)
5675{
5676 struct stream_out *out = (struct stream_out *)stream;
5677 struct audio_device *adev = out->dev;
5678 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005679 unsigned int offset1 = 0;
5680 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005681 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005682 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005683 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005684
Arun Mirpuri5d170872019-03-26 13:21:31 -07005685 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305686 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005687 pthread_mutex_lock(&adev->lock);
5688
Sharad Sanglec6f32552018-05-04 16:15:38 +05305689 if (CARD_STATUS_OFFLINE == out->card_status ||
5690 CARD_STATUS_OFFLINE == adev->card_status) {
5691 ALOGW("out->card_status or adev->card_status offline, try again");
5692 ret = -EIO;
5693 goto exit;
5694 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005695 if (info == NULL || min_size_frames == 0) {
5696 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5697 ret = -EINVAL;
5698 goto exit;
5699 }
5700 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5701 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5702 ret = -ENOSYS;
5703 goto exit;
5704 }
5705 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5706 if (out->pcm_device_id < 0) {
5707 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5708 __func__, out->pcm_device_id, out->usecase);
5709 ret = -EINVAL;
5710 goto exit;
5711 }
5712
5713 adjust_mmap_period_count(&out->config, min_size_frames);
5714
Arun Mirpuri5d170872019-03-26 13:21:31 -07005715 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005716 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5717 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5718 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305719 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305720 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5721 out->card_status = CARD_STATUS_OFFLINE;
5722 adev->card_status = CARD_STATUS_OFFLINE;
5723 ret = -EIO;
5724 goto exit;
5725 }
5726
Haynes Mathew George16081042017-05-31 17:16:49 -07005727 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5728 step = "open";
5729 ret = -ENODEV;
5730 goto exit;
5731 }
5732 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5733 if (ret < 0) {
5734 step = "begin";
5735 goto exit;
5736 }
5737 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005738 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005739 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005740 ret = platform_get_mmap_data_fd(adev->platform,
5741 out->pcm_device_id, 0 /*playback*/,
5742 &info->shared_memory_fd,
5743 &mmap_size);
5744 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005745 // Fall back to non exclusive mode
5746 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5747 } else {
5748 if (mmap_size < buffer_size) {
5749 step = "mmap";
5750 goto exit;
5751 }
5752 // FIXME: indicate exclusive mode support by returning a negative buffer size
5753 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005754 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005755 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005756 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005757
5758 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5759 if (ret < 0) {
5760 step = "commit";
5761 goto exit;
5762 }
5763
5764 out->standby = false;
5765 ret = 0;
5766
Arun Mirpuri5d170872019-03-26 13:21:31 -07005767 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005768 __func__, info->shared_memory_address, info->buffer_size_frames);
5769
5770exit:
5771 if (ret != 0) {
5772 if (out->pcm == NULL) {
5773 ALOGE("%s: %s - %d", __func__, step, ret);
5774 } else {
5775 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5776 pcm_close(out->pcm);
5777 out->pcm = NULL;
5778 }
5779 }
5780 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305781 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005782 return ret;
5783}
5784
5785static int out_get_mmap_position(const struct audio_stream_out *stream,
5786 struct audio_mmap_position *position)
5787{
5788 struct stream_out *out = (struct stream_out *)stream;
5789 ALOGVV("%s", __func__);
5790 if (position == NULL) {
5791 return -EINVAL;
5792 }
5793 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005794 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005795 return -ENOSYS;
5796 }
5797 if (out->pcm == NULL) {
5798 return -ENOSYS;
5799 }
5800
5801 struct timespec ts = { 0, 0 };
5802 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5803 if (ret < 0) {
5804 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5805 return ret;
5806 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005807 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005808 return 0;
5809}
5810
5811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005812/** audio_stream_in implementation **/
5813static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5814{
5815 struct stream_in *in = (struct stream_in *)stream;
5816
5817 return in->config.rate;
5818}
5819
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005820static int in_set_sample_rate(struct audio_stream *stream __unused,
5821 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005822{
5823 return -ENOSYS;
5824}
5825
5826static size_t in_get_buffer_size(const struct audio_stream *stream)
5827{
5828 struct stream_in *in = (struct stream_in *)stream;
5829
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005830 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5831 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005832 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5833 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 -07005834 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5835 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305836 else if(audio_extn_cin_attached_usecase(in->usecase))
5837 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005838
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005839 return in->config.period_size * in->af_period_multiplier *
5840 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005841}
5842
5843static uint32_t in_get_channels(const struct audio_stream *stream)
5844{
5845 struct stream_in *in = (struct stream_in *)stream;
5846
5847 return in->channel_mask;
5848}
5849
5850static audio_format_t in_get_format(const struct audio_stream *stream)
5851{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005852 struct stream_in *in = (struct stream_in *)stream;
5853
5854 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005855}
5856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005857static int in_set_format(struct audio_stream *stream __unused,
5858 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005859{
5860 return -ENOSYS;
5861}
5862
5863static int in_standby(struct audio_stream *stream)
5864{
5865 struct stream_in *in = (struct stream_in *)stream;
5866 struct audio_device *adev = in->dev;
5867 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305868 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5869 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005870 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305871
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005872 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005873 if (!in->standby && in->is_st_session) {
5874 ALOGD("%s: sound trigger pcm stop lab", __func__);
5875 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005876 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005877 in->standby = 1;
5878 }
5879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005880 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005881 if (adev->adm_deregister_stream)
5882 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5883
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005884 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005885 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005886 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005887 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005888 voice_extn_compress_voip_close_input_stream(stream);
5889 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005890 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5891 do_stop = in->capture_started;
5892 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005893 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305894 if (audio_extn_cin_attached_usecase(in->usecase))
5895 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005896 }
5897
Arun Mirpuri5d170872019-03-26 13:21:31 -07005898 if (in->pcm) {
5899 ATRACE_BEGIN("pcm_in_close");
5900 pcm_close(in->pcm);
5901 ATRACE_END();
5902 in->pcm = NULL;
5903 }
5904
5905 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005906 adev->enable_voicerx = false;
5907 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005908 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005909 }
Quinn Malef6050362019-01-30 15:55:40 -08005910
5911 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5912 adev->num_va_sessions--;
5913
Eric Laurent150dbfe2013-02-27 14:31:02 -08005914 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005915 }
5916 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005917 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918 return status;
5919}
5920
Aalique Grahame22e49102018-12-18 14:23:57 -08005921static int in_dump(const struct audio_stream *stream,
5922 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005923{
Aalique Grahame22e49102018-12-18 14:23:57 -08005924 struct stream_in *in = (struct stream_in *)stream;
5925
5926 // We try to get the lock for consistency,
5927 // but it isn't necessary for these variables.
5928 // If we're not in standby, we may be blocked on a read.
5929 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5930 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5931 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5932 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5933
5934 if (locked) {
5935 pthread_mutex_unlock(&in->lock);
5936 }
5937
5938 // dump error info
5939 (void)error_log_dump(
5940 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005942 return 0;
5943}
5944
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305945static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5946{
5947 if (!stream || !parms)
5948 return;
5949
5950 struct stream_in *in = (struct stream_in *)stream;
5951 struct audio_device *adev = in->dev;
5952
5953 card_status_t status;
5954 int card;
5955 if (parse_snd_card_status(parms, &card, &status) < 0)
5956 return;
5957
5958 pthread_mutex_lock(&adev->lock);
5959 bool valid_cb = (card == adev->snd_card);
5960 pthread_mutex_unlock(&adev->lock);
5961
5962 if (!valid_cb)
5963 return;
5964
5965 lock_input_stream(in);
5966 if (in->card_status != status)
5967 in->card_status = status;
5968 pthread_mutex_unlock(&in->lock);
5969
5970 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5971 use_case_table[in->usecase],
5972 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5973
5974 // a better solution would be to report error back to AF and let
5975 // it put the stream to standby
5976 if (status == CARD_STATUS_OFFLINE)
5977 in_standby(&in->stream.common);
5978
5979 return;
5980}
5981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005982static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5983{
5984 struct stream_in *in = (struct stream_in *)stream;
5985 struct audio_device *adev = in->dev;
5986 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005987 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005988 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005989
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305990 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005991 parms = str_parms_create_str(kvpairs);
5992
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305993 if (!parms)
5994 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005995 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005996 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005997
5998 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5999 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006000 val = atoi(value);
6001 /* no audio source uses val == 0 */
6002 if ((in->source != val) && (val != 0)) {
6003 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006004 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6005 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6006 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006007 (in->config.rate == 8000 || in->config.rate == 16000 ||
6008 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006009 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006010 err = voice_extn_compress_voip_open_input_stream(in);
6011 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006012 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006013 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006014 }
6015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006016 }
6017 }
6018
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006019 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6020 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006021 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006022 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6023
6024 // Workaround: If routing to an non existing usb device, fail gracefully
6025 // The routing request will otherwise block during 10 second
6026 int card;
6027 if (audio_is_usb_in_device(val) &&
6028 (card = get_alive_usb_card(parms)) >= 0) {
6029
6030 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6031 ret = -ENOSYS;
6032 } else {
6033
6034 in->device = val;
6035 /* If recording is in progress, change the tx device to new device */
6036 if (!in->standby && !in->is_st_session) {
6037 ALOGV("update input routing change");
6038 // inform adm before actual routing to prevent glitches.
6039 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006040 adev->adm_on_routing_change(adev->adm_data,
6041 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006042 ret = select_devices(adev, in->usecase);
6043 }
6044 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006045 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006046 }
6047 }
6048
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306049 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6050 if (err >= 0) {
6051 strlcpy(in->profile, value, sizeof(in->profile));
6052 ALOGV("updating stream profile with value '%s'", in->profile);
6053 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6054 &adev->streams_input_cfg_list,
6055 in->device, in->flags, in->format,
6056 in->sample_rate, in->bit_width,
6057 in->profile, &in->app_type_cfg);
6058 }
6059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006060 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006061 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006062
6063 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306064error:
Eric Laurent994a6932013-07-17 11:51:42 -07006065 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066 return ret;
6067}
6068
6069static char* in_get_parameters(const struct audio_stream *stream,
6070 const char *keys)
6071{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006072 struct stream_in *in = (struct stream_in *)stream;
6073 struct str_parms *query = str_parms_create_str(keys);
6074 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006075 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006076
6077 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006078 if (reply) {
6079 str_parms_destroy(reply);
6080 }
6081 if (query) {
6082 str_parms_destroy(query);
6083 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006084 ALOGE("in_get_parameters: failed to create query or reply");
6085 return NULL;
6086 }
6087
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006088 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006089
6090 voice_extn_in_get_parameters(in, query, reply);
6091
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006092 stream_get_parameter_channels(query, reply,
6093 &in->supported_channel_masks[0]);
6094 stream_get_parameter_formats(query, reply,
6095 &in->supported_formats[0]);
6096 stream_get_parameter_rates(query, reply,
6097 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006098 str = str_parms_to_str(reply);
6099 str_parms_destroy(query);
6100 str_parms_destroy(reply);
6101
6102 ALOGV("%s: exit: returns - %s", __func__, str);
6103 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006104}
6105
Aalique Grahame22e49102018-12-18 14:23:57 -08006106static int in_set_gain(struct audio_stream_in *stream,
6107 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006108{
Aalique Grahame22e49102018-12-18 14:23:57 -08006109 struct stream_in *in = (struct stream_in *)stream;
6110 char mixer_ctl_name[128];
6111 struct mixer_ctl *ctl;
6112 int ctl_value;
6113
6114 ALOGV("%s: gain %f", __func__, gain);
6115
6116 if (stream == NULL)
6117 return -EINVAL;
6118
6119 /* in_set_gain() only used to silence MMAP capture for now */
6120 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6121 return -ENOSYS;
6122
6123 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6124
6125 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6126 if (!ctl) {
6127 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6128 __func__, mixer_ctl_name);
6129 return -ENOSYS;
6130 }
6131
6132 if (gain < RECORD_GAIN_MIN)
6133 gain = RECORD_GAIN_MIN;
6134 else if (gain > RECORD_GAIN_MAX)
6135 gain = RECORD_GAIN_MAX;
6136 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6137
6138 mixer_ctl_set_value(ctl, 0, ctl_value);
6139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006140 return 0;
6141}
6142
6143static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6144 size_t bytes)
6145{
6146 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306147
6148 if (in == NULL) {
6149 ALOGE("%s: stream_in ptr is NULL", __func__);
6150 return -EINVAL;
6151 }
6152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306154 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306155 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006156
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006157 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306158
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006159 if (in->is_st_session) {
6160 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6161 /* Read from sound trigger HAL */
6162 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006163 if (in->standby) {
6164 adev->num_va_sessions++;
6165 in->standby = 0;
6166 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006167 pthread_mutex_unlock(&in->lock);
6168 return bytes;
6169 }
6170
Haynes Mathew George16081042017-05-31 17:16:49 -07006171 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6172 ret = -ENOSYS;
6173 goto exit;
6174 }
6175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006176 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006177 pthread_mutex_lock(&adev->lock);
6178 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6179 ret = voice_extn_compress_voip_start_input_stream(in);
6180 else
6181 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006182 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6183 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006184 pthread_mutex_unlock(&adev->lock);
6185 if (ret != 0) {
6186 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006187 }
6188 in->standby = 0;
6189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006190
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006191 // what's the duration requested by the client?
6192 long ns = 0;
6193
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306194 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006195 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6196 in->config.rate;
6197
6198 request_in_focus(in, ns);
6199 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006200
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306201 if (audio_extn_cin_attached_usecase(in->usecase)) {
6202 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6203 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306204 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006205 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306206 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006207 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006208 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006209 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006210 } else if (audio_extn_ffv_get_stream() == in) {
6211 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306212 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006213 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306214 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6215 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6216 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6217 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306218 ret = -EINVAL;
6219 goto exit;
6220 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306221 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306222 ret = -errno;
6223 }
6224 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306225 /* bytes read is always set to bytes for non compress usecases */
6226 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227 }
6228
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006229 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006231 /*
Quinn Malef6050362019-01-30 15:55:40 -08006232 * Instead of writing zeroes here, we could trust the hardware to always
6233 * provide zeroes when muted. This is also muted with voice recognition
6234 * usecases so that other clients do not have access to voice recognition
6235 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006236 */
Quinn Malef6050362019-01-30 15:55:40 -08006237 if ((ret == 0 && voice_get_mic_mute(adev) &&
6238 !voice_is_in_call_rec_stream(in) &&
6239 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6240 (adev->num_va_sessions &&
6241 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6242 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6243 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006244 memset(buffer, 0, bytes);
6245
6246exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006247 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306248 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006249 pthread_mutex_unlock(&in->lock);
6250
6251 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306252 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306253 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306254 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306255 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306256 in->standby = true;
6257 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306258 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6259 bytes_read = bytes;
6260 memset(buffer, 0, bytes);
6261 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006262 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006263 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306264 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306265 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306267 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268}
6269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006270static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006271{
6272 return 0;
6273}
6274
Aalique Grahame22e49102018-12-18 14:23:57 -08006275static int in_get_capture_position(const struct audio_stream_in *stream,
6276 int64_t *frames, int64_t *time)
6277{
6278 if (stream == NULL || frames == NULL || time == NULL) {
6279 return -EINVAL;
6280 }
6281 struct stream_in *in = (struct stream_in *)stream;
6282 int ret = -ENOSYS;
6283
6284 lock_input_stream(in);
6285 // note: ST sessions do not close the alsa pcm driver synchronously
6286 // on standby. Therefore, we may return an error even though the
6287 // pcm stream is still opened.
6288 if (in->standby) {
6289 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6290 "%s stream in standby but pcm not NULL for non ST session", __func__);
6291 goto exit;
6292 }
6293 if (in->pcm) {
6294 struct timespec timestamp;
6295 unsigned int avail;
6296 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6297 *frames = in->frames_read + avail;
6298 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6299 ret = 0;
6300 }
6301 }
6302exit:
6303 pthread_mutex_unlock(&in->lock);
6304 return ret;
6305}
6306
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006307static int add_remove_audio_effect(const struct audio_stream *stream,
6308 effect_handle_t effect,
6309 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006310{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006311 struct stream_in *in = (struct stream_in *)stream;
6312 int status = 0;
6313 effect_descriptor_t desc;
6314
6315 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006316 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6317
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006318 if (status != 0)
6319 return status;
6320
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006321 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006322 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006323 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006324 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006325 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006326 in->enable_aec != enable &&
6327 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6328 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006329 if (!enable)
6330 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6331 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6332 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6333 in->dev->enable_voicerx = enable;
6334 struct audio_usecase *usecase;
6335 struct listnode *node;
6336 list_for_each(node, &in->dev->usecase_list) {
6337 usecase = node_to_item(node, struct audio_usecase, list);
6338 if (usecase->type == PCM_PLAYBACK)
6339 select_devices(in->dev, usecase->id);
6340 }
6341 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006342 if (!in->standby) {
6343 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6344 select_devices(in->dev, in->usecase);
6345 }
6346
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006347 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006348 if (in->enable_ns != enable &&
6349 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6350 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006351 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006352 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6353 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006354 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6355 select_devices(in->dev, in->usecase);
6356 } else
6357 select_devices(in->dev, in->usecase);
6358 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006359 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006360 pthread_mutex_unlock(&in->dev->lock);
6361 pthread_mutex_unlock(&in->lock);
6362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006363 return 0;
6364}
6365
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006366static int in_add_audio_effect(const struct audio_stream *stream,
6367 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006368{
Eric Laurent994a6932013-07-17 11:51:42 -07006369 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006370 return add_remove_audio_effect(stream, effect, true);
6371}
6372
6373static int in_remove_audio_effect(const struct audio_stream *stream,
6374 effect_handle_t effect)
6375{
Eric Laurent994a6932013-07-17 11:51:42 -07006376 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006377 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006378}
6379
Derek Chenf939fb72018-11-13 13:34:41 -08006380streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6381 audio_io_handle_t input)
6382{
6383 struct listnode *node;
6384
6385 list_for_each(node, &dev->active_inputs_list) {
6386 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6387 streams_input_ctxt_t,
6388 list);
6389 if (in_ctxt->input->capture_handle == input) {
6390 return in_ctxt;
6391 }
6392 }
6393 return NULL;
6394}
6395
6396streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6397 audio_io_handle_t output)
6398{
6399 struct listnode *node;
6400
6401 list_for_each(node, &dev->active_outputs_list) {
6402 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6403 streams_output_ctxt_t,
6404 list);
6405 if (out_ctxt->output->handle == output) {
6406 return out_ctxt;
6407 }
6408 }
6409 return NULL;
6410}
6411
Haynes Mathew George16081042017-05-31 17:16:49 -07006412static int in_stop(const struct audio_stream_in* stream)
6413{
6414 struct stream_in *in = (struct stream_in *)stream;
6415 struct audio_device *adev = in->dev;
6416
6417 int ret = -ENOSYS;
6418 ALOGV("%s", __func__);
6419 pthread_mutex_lock(&adev->lock);
6420 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6421 in->capture_started && in->pcm != NULL) {
6422 pcm_stop(in->pcm);
6423 ret = stop_input_stream(in);
6424 in->capture_started = false;
6425 }
6426 pthread_mutex_unlock(&adev->lock);
6427 return ret;
6428}
6429
6430static int in_start(const struct audio_stream_in* stream)
6431{
6432 struct stream_in *in = (struct stream_in *)stream;
6433 struct audio_device *adev = in->dev;
6434 int ret = -ENOSYS;
6435
6436 ALOGV("%s in %p", __func__, in);
6437 pthread_mutex_lock(&adev->lock);
6438 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6439 !in->capture_started && in->pcm != NULL) {
6440 if (!in->capture_started) {
6441 ret = start_input_stream(in);
6442 if (ret == 0) {
6443 in->capture_started = true;
6444 }
6445 }
6446 }
6447 pthread_mutex_unlock(&adev->lock);
6448 return ret;
6449}
6450
6451static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6452 int32_t min_size_frames,
6453 struct audio_mmap_buffer_info *info)
6454{
6455 struct stream_in *in = (struct stream_in *)stream;
6456 struct audio_device *adev = in->dev;
6457 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006458 unsigned int offset1 = 0;
6459 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006460 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006461 uint32_t mmap_size = 0;
6462 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006463
6464 pthread_mutex_lock(&adev->lock);
6465 ALOGV("%s in %p", __func__, in);
6466
Sharad Sanglec6f32552018-05-04 16:15:38 +05306467 if (CARD_STATUS_OFFLINE == in->card_status||
6468 CARD_STATUS_OFFLINE == adev->card_status) {
6469 ALOGW("in->card_status or adev->card_status offline, try again");
6470 ret = -EIO;
6471 goto exit;
6472 }
6473
Haynes Mathew George16081042017-05-31 17:16:49 -07006474 if (info == NULL || min_size_frames == 0) {
6475 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6476 ret = -EINVAL;
6477 goto exit;
6478 }
6479 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6480 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6481 ALOGV("%s in %p", __func__, in);
6482 ret = -ENOSYS;
6483 goto exit;
6484 }
6485 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6486 if (in->pcm_device_id < 0) {
6487 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6488 __func__, in->pcm_device_id, in->usecase);
6489 ret = -EINVAL;
6490 goto exit;
6491 }
6492
6493 adjust_mmap_period_count(&in->config, min_size_frames);
6494
6495 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6496 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6497 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6498 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306499 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306500 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6501 in->card_status = CARD_STATUS_OFFLINE;
6502 adev->card_status = CARD_STATUS_OFFLINE;
6503 ret = -EIO;
6504 goto exit;
6505 }
6506
Haynes Mathew George16081042017-05-31 17:16:49 -07006507 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6508 step = "open";
6509 ret = -ENODEV;
6510 goto exit;
6511 }
6512
6513 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6514 if (ret < 0) {
6515 step = "begin";
6516 goto exit;
6517 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006518
Arun Mirpuri5d170872019-03-26 13:21:31 -07006519 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6520 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6521 info->burst_size_frames = in->config.period_size;
6522 ret = platform_get_mmap_data_fd(adev->platform,
6523 in->pcm_device_id, 1 /*capture*/,
6524 &info->shared_memory_fd,
6525 &mmap_size);
6526 if (ret < 0) {
6527 // Fall back to non exclusive mode
6528 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6529 } else {
6530 if (mmap_size < buffer_size) {
6531 step = "mmap";
6532 goto exit;
6533 }
6534 // FIXME: indicate exclusive mode support by returning a negative buffer size
6535 info->buffer_size_frames *= -1;
6536 }
6537
6538 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006539
6540 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6541 if (ret < 0) {
6542 step = "commit";
6543 goto exit;
6544 }
6545
6546 in->standby = false;
6547 ret = 0;
6548
6549 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6550 __func__, info->shared_memory_address, info->buffer_size_frames);
6551
6552exit:
6553 if (ret != 0) {
6554 if (in->pcm == NULL) {
6555 ALOGE("%s: %s - %d", __func__, step, ret);
6556 } else {
6557 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6558 pcm_close(in->pcm);
6559 in->pcm = NULL;
6560 }
6561 }
6562 pthread_mutex_unlock(&adev->lock);
6563 return ret;
6564}
6565
6566static int in_get_mmap_position(const struct audio_stream_in *stream,
6567 struct audio_mmap_position *position)
6568{
6569 struct stream_in *in = (struct stream_in *)stream;
6570 ALOGVV("%s", __func__);
6571 if (position == NULL) {
6572 return -EINVAL;
6573 }
6574 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6575 return -ENOSYS;
6576 }
6577 if (in->pcm == NULL) {
6578 return -ENOSYS;
6579 }
6580 struct timespec ts = { 0, 0 };
6581 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6582 if (ret < 0) {
6583 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6584 return ret;
6585 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306586 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006587 return 0;
6588}
6589
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306590static int in_get_active_microphones(const struct audio_stream_in *stream,
6591 struct audio_microphone_characteristic_t *mic_array,
6592 size_t *mic_count) {
6593 struct stream_in *in = (struct stream_in *)stream;
6594 struct audio_device *adev = in->dev;
6595 ALOGVV("%s", __func__);
6596
6597 lock_input_stream(in);
6598 pthread_mutex_lock(&adev->lock);
6599 int ret = platform_get_active_microphones(adev->platform,
6600 audio_channel_count_from_in_mask(in->channel_mask),
6601 in->usecase, mic_array, mic_count);
6602 pthread_mutex_unlock(&adev->lock);
6603 pthread_mutex_unlock(&in->lock);
6604
6605 return ret;
6606}
6607
6608static int adev_get_microphones(const struct audio_hw_device *dev,
6609 struct audio_microphone_characteristic_t *mic_array,
6610 size_t *mic_count) {
6611 struct audio_device *adev = (struct audio_device *)dev;
6612 ALOGVV("%s", __func__);
6613
6614 pthread_mutex_lock(&adev->lock);
6615 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6616 pthread_mutex_unlock(&adev->lock);
6617
6618 return ret;
6619}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306620int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006621 audio_io_handle_t handle,
6622 audio_devices_t devices,
6623 audio_output_flags_t flags,
6624 struct audio_config *config,
6625 struct audio_stream_out **stream_out,
6626 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006627{
6628 struct audio_device *adev = (struct audio_device *)dev;
6629 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306630 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006631 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006632 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306633 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006634 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6635 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6636 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6637 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006638 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006639 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006640 bool force_haptic_path =
6641 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006642
kunleizdff872d2018-08-20 14:40:33 +08006643 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006644 is_usb_dev = false;
6645 devices = AUDIO_DEVICE_OUT_SPEAKER;
6646 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6647 __func__, devices);
6648 }
6649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006650 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006652 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6653
Mingming Yin3a941d42016-02-17 18:08:05 -08006654 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6655 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306656 devices, flags, &out->stream);
6657
6658
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006659 if (!out) {
6660 return -ENOMEM;
6661 }
6662
Haynes Mathew George204045b2015-02-25 20:32:03 -08006663 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006664 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306665 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006666 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006667 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006669 if (devices == AUDIO_DEVICE_NONE)
6670 devices = AUDIO_DEVICE_OUT_SPEAKER;
6671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006672 out->flags = flags;
6673 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006674 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006675 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006676 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306677 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306678 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6679 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6680 else
6681 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006682 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006683 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006684 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306685 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306686 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306687 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006688 out->hal_output_suspend_supported = 0;
6689 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306690 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306691 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306692 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006693
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306694 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306695 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006696 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6697
Aalique Grahame22e49102018-12-18 14:23:57 -08006698 if (direct_dev &&
6699 (audio_is_linear_pcm(out->format) ||
6700 config->format == AUDIO_FORMAT_DEFAULT) &&
6701 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6702 audio_format_t req_format = config->format;
6703 audio_channel_mask_t req_channel_mask = config->channel_mask;
6704 uint32_t req_sample_rate = config->sample_rate;
6705
6706 pthread_mutex_lock(&adev->lock);
6707 if (is_hdmi) {
6708 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6709 ret = read_hdmi_sink_caps(out);
6710 if (config->sample_rate == 0)
6711 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6712 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6713 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6714 if (config->format == AUDIO_FORMAT_DEFAULT)
6715 config->format = AUDIO_FORMAT_PCM_16_BIT;
6716 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006717 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6718 &config->format,
6719 &out->supported_formats[0],
6720 MAX_SUPPORTED_FORMATS,
6721 &config->channel_mask,
6722 &out->supported_channel_masks[0],
6723 MAX_SUPPORTED_CHANNEL_MASKS,
6724 &config->sample_rate,
6725 &out->supported_sample_rates[0],
6726 MAX_SUPPORTED_SAMPLE_RATES);
6727 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006728 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006729
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006730 pthread_mutex_unlock(&adev->lock);
6731 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006732 if (ret == -ENOSYS) {
6733 /* ignore and go with default */
6734 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006735 }
6736 // For MMAP NO IRQ, allow conversions in ADSP
6737 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6738 goto error_open;
6739 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006740 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006741 goto error_open;
6742 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006743
6744 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6745 config->sample_rate = req_sample_rate;
6746 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6747 config->channel_mask = req_channel_mask;
6748 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6749 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006750 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006751
6752 out->sample_rate = config->sample_rate;
6753 out->channel_mask = config->channel_mask;
6754 out->format = config->format;
6755 if (is_hdmi) {
6756 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6757 out->config = pcm_config_hdmi_multi;
6758 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6759 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6760 out->config = pcm_config_mmap_playback;
6761 out->stream.start = out_start;
6762 out->stream.stop = out_stop;
6763 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6764 out->stream.get_mmap_position = out_get_mmap_position;
6765 } else {
6766 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6767 out->config = pcm_config_hifi;
6768 }
6769
6770 out->config.rate = out->sample_rate;
6771 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6772 if (is_hdmi) {
6773 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6774 audio_bytes_per_sample(out->format));
6775 }
6776 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006777 }
6778
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006779 /* Check for VOIP usecase */
6780 if(out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) {
6781 if (!voice_extn_is_compress_voip_supported()) {
6782 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6783 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006784 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006785 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6786 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006787
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006788 out->config = default_pcm_config_voip_copp;
6789 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6790 out->config.rate = out->sample_rate;
6791 }
6792 } else {
6793 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6794 voice_extn_compress_voip_is_active(out->dev)) &&
6795 (voice_extn_compress_voip_is_config_supported(config))) {
6796 ret = voice_extn_compress_voip_open_output_stream(out);
6797 if (ret != 0) {
6798 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6799 __func__, ret);
6800 goto error_open;
6801 }
6802 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006803 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006804 } else if (audio_is_linear_pcm(out->format) &&
6805 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6806 out->channel_mask = config->channel_mask;
6807 out->sample_rate = config->sample_rate;
6808 out->format = config->format;
6809 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6810 // does this change?
6811 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6812 out->config.rate = config->sample_rate;
6813 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6814 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6815 audio_bytes_per_sample(config->format));
6816 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006817 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306818 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306819 pthread_mutex_lock(&adev->lock);
6820 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6821 pthread_mutex_unlock(&adev->lock);
6822
6823 // reject offload during card offline to allow
6824 // fallback to s/w paths
6825 if (offline) {
6826 ret = -ENODEV;
6827 goto error_open;
6828 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006829
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006830 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6831 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6832 ALOGE("%s: Unsupported Offload information", __func__);
6833 ret = -EINVAL;
6834 goto error_open;
6835 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006836
Atul Khare3fa6e542017-08-09 00:56:17 +05306837 if (config->offload_info.format == 0)
6838 config->offload_info.format = config->format;
6839 if (config->offload_info.sample_rate == 0)
6840 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006841
Mingming Yin90310102013-11-13 16:57:00 -08006842 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306843 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006844 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006845 ret = -EINVAL;
6846 goto error_open;
6847 }
6848
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006849 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6850 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6851 (audio_extn_passthru_is_passthrough_stream(out)) &&
6852 !((config->sample_rate == 48000) ||
6853 (config->sample_rate == 96000) ||
6854 (config->sample_rate == 192000))) {
6855 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6856 __func__, config->sample_rate, config->offload_info.format);
6857 ret = -EINVAL;
6858 goto error_open;
6859 }
6860
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006861 out->compr_config.codec = (struct snd_codec *)
6862 calloc(1, sizeof(struct snd_codec));
6863
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006864 if (!out->compr_config.codec) {
6865 ret = -ENOMEM;
6866 goto error_open;
6867 }
6868
Dhananjay Kumarac341582017-02-23 23:42:25 +05306869 out->stream.pause = out_pause;
6870 out->stream.resume = out_resume;
6871 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306872 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306873 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006874 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306875 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006876 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306877 } else {
6878 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6879 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006880 }
vivek mehta446c3962015-09-14 10:57:35 -07006881
6882 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006883 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6884 config->format == 0 && config->sample_rate == 0 &&
6885 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006886 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006887 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6888 } else {
6889 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6890 ret = -EEXIST;
6891 goto error_open;
6892 }
vivek mehta446c3962015-09-14 10:57:35 -07006893 }
6894
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006895 if (config->offload_info.channel_mask)
6896 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006897 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006898 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006899 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006900 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306901 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006902 ret = -EINVAL;
6903 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006904 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006905
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006906 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006907 out->sample_rate = config->offload_info.sample_rate;
6908
Mingming Yin3ee55c62014-08-04 14:23:35 -07006909 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006910
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306911 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306912 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306913 audio_extn_dolby_send_ddp_endp_params(adev);
6914 audio_extn_dolby_set_dmid(adev);
6915 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006917 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006918 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006919 out->compr_config.codec->bit_rate =
6920 config->offload_info.bit_rate;
6921 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306922 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006923 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306924 /* Update bit width only for non passthrough usecases.
6925 * For passthrough usecases, the output will always be opened @16 bit
6926 */
6927 if (!audio_extn_passthru_is_passthrough_stream(out))
6928 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306929
6930 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6931 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6932 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6933
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006934 /*TODO: Do we need to change it for passthrough */
6935 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006936
Manish Dewangana6fc5442015-08-24 20:30:31 +05306937 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6938 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306939 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306940 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306941 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6942 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306943
6944 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6945 AUDIO_FORMAT_PCM) {
6946
6947 /*Based on platform support, configure appropriate alsa format for corresponding
6948 *hal input format.
6949 */
6950 out->compr_config.codec->format = hal_format_to_alsa(
6951 config->offload_info.format);
6952
Ashish Jain83a6cc22016-06-28 14:34:17 +05306953 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306954 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306955 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306956
Dhananjay Kumarac341582017-02-23 23:42:25 +05306957 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306958 *hal input format and alsa format might differ based on platform support.
6959 */
6960 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306961 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306962
6963 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6964
6965 /* Check if alsa session is configured with the same format as HAL input format,
6966 * if not then derive correct fragment size needed to accomodate the
6967 * conversion of HAL input format to alsa format.
6968 */
6969 audio_extn_utils_update_direct_pcm_fragment_size(out);
6970
6971 /*if hal input and output fragment size is different this indicates HAL input format is
6972 *not same as the alsa format
6973 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306974 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306975 /*Allocate a buffer to convert input data to the alsa configured format.
6976 *size of convert buffer is equal to the size required to hold one fragment size
6977 *worth of pcm data, this is because flinger does not write more than fragment_size
6978 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306979 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6980 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306981 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6982 ret = -ENOMEM;
6983 goto error_open;
6984 }
6985 }
6986 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6987 out->compr_config.fragment_size =
6988 audio_extn_passthru_get_buffer_size(&config->offload_info);
6989 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6990 } else {
6991 out->compr_config.fragment_size =
6992 platform_get_compress_offload_buffer_size(&config->offload_info);
6993 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6994 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006995
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306996 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6997 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6998 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006999 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307000 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007001
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307002 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7003 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7004 }
7005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007006 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7007 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007008
Manish Dewangan69426c82017-01-30 17:35:36 +05307009 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7010 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7011 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7012 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7013 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7014 } else {
7015 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7016 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007017
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307018 memset(&out->channel_map_param, 0,
7019 sizeof(struct audio_out_channel_map_param));
7020
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007021 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307022 out->send_next_track_params = false;
7023 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007024 out->offload_state = OFFLOAD_STATE_IDLE;
7025 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007026 out->writeAt.tv_sec = 0;
7027 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007028
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007029 audio_extn_dts_create_state_notifier_node(out->usecase);
7030
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007031 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7032 __func__, config->offload_info.version,
7033 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307034
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307035 /* Check if DSD audio format is supported in codec
7036 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307037 */
7038
7039 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307040 (!platform_check_codec_dsd_support(adev->platform) ||
7041 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307042 ret = -EINVAL;
7043 goto error_open;
7044 }
7045
Ashish Jain5106d362016-05-11 19:23:33 +05307046 /* Disable gapless if any of the following is true
7047 * passthrough playback
7048 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307049 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307050 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307051 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307052 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007053 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307054 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307055 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307056 check_and_set_gapless_mode(adev, false);
7057 } else
7058 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007059
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307060 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007061 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7062 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307063 if (config->format == AUDIO_FORMAT_DSD) {
7064 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7065 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7066 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007067
7068 create_offload_callback_thread(out);
7069
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007070 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007071 switch (config->sample_rate) {
7072 case 0:
7073 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7074 break;
7075 case 8000:
7076 case 16000:
7077 case 48000:
7078 out->sample_rate = config->sample_rate;
7079 break;
7080 default:
7081 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7082 config->sample_rate);
7083 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7084 ret = -EINVAL;
7085 goto error_open;
7086 }
7087 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7088 switch (config->channel_mask) {
7089 case AUDIO_CHANNEL_NONE:
7090 case AUDIO_CHANNEL_OUT_STEREO:
7091 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7092 break;
7093 default:
7094 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7095 config->channel_mask);
7096 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7097 ret = -EINVAL;
7098 goto error_open;
7099 }
7100 switch (config->format) {
7101 case AUDIO_FORMAT_DEFAULT:
7102 case AUDIO_FORMAT_PCM_16_BIT:
7103 out->format = AUDIO_FORMAT_PCM_16_BIT;
7104 break;
7105 default:
7106 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7107 config->format);
7108 config->format = AUDIO_FORMAT_PCM_16_BIT;
7109 ret = -EINVAL;
7110 goto error_open;
7111 }
7112
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307113 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007114 if (ret != 0) {
7115 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007116 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007117 goto error_open;
7118 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007119 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007120 switch (config->sample_rate) {
7121 case 0:
7122 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7123 break;
7124 case 8000:
7125 case 16000:
7126 case 48000:
7127 out->sample_rate = config->sample_rate;
7128 break;
7129 default:
7130 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7131 config->sample_rate);
7132 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7133 ret = -EINVAL;
7134 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007135 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007136 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7137 switch (config->channel_mask) {
7138 case AUDIO_CHANNEL_NONE:
7139 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7140 break;
7141 case AUDIO_CHANNEL_OUT_STEREO:
7142 out->channel_mask = config->channel_mask;
7143 break;
7144 default:
7145 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7146 config->channel_mask);
7147 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7148 ret = -EINVAL;
7149 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007150 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007151 switch (config->format) {
7152 case AUDIO_FORMAT_DEFAULT:
7153 out->format = AUDIO_FORMAT_PCM_16_BIT;
7154 break;
7155 case AUDIO_FORMAT_PCM_16_BIT:
7156 out->format = config->format;
7157 break;
7158 default:
7159 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7160 config->format);
7161 config->format = AUDIO_FORMAT_PCM_16_BIT;
7162 ret = -EINVAL;
7163 break;
7164 }
7165 if (ret != 0)
7166 goto error_open;
7167
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007168 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7169 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007170 out->config.rate = out->sample_rate;
7171 out->config.channels =
7172 audio_channel_count_from_out_mask(out->channel_mask);
7173 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007174 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007175 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307176 unsigned int channels = 0;
7177 /*Update config params to default if not set by the caller*/
7178 if (config->sample_rate == 0)
7179 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7180 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7181 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7182 if (config->format == AUDIO_FORMAT_DEFAULT)
7183 config->format = AUDIO_FORMAT_PCM_16_BIT;
7184
7185 channels = audio_channel_count_from_out_mask(out->channel_mask);
7186
Varun Balaraje49253e2017-07-06 19:48:56 +05307187 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7188 out->usecase = get_interactive_usecase(adev);
7189 out->config = pcm_config_low_latency;
7190 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307191 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007192 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7193 out->flags);
7194 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007195 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7196 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7197 out->config = pcm_config_mmap_playback;
7198 out->stream.start = out_start;
7199 out->stream.stop = out_stop;
7200 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7201 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307202 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7203 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007204 out->hal_output_suspend_supported =
7205 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7206 out->dynamic_pm_qos_config_supported =
7207 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7208 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007209 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7210 } else {
7211 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7212 //the mixer path will be a string similar to "low-latency-playback resume"
7213 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7214 strlcat(out->pm_qos_mixer_path,
7215 " resume", MAX_MIXER_PATH_LEN);
7216 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7217 out->pm_qos_mixer_path);
7218 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307219 out->config = pcm_config_low_latency;
7220 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7221 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7222 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307223 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7224 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7225 if (out->config.period_size <= 0) {
7226 ALOGE("Invalid configuration period size is not valid");
7227 ret = -EINVAL;
7228 goto error_open;
7229 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007230 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7231 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7232 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007233 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7234 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7235 out->config = pcm_config_haptics_audio;
7236 if (force_haptic_path)
7237 adev->haptics_config = pcm_config_haptics_audio;
7238 else
7239 adev->haptics_config = pcm_config_haptics;
7240
7241 out->config.channels =
7242 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7243
7244 if (force_haptic_path) {
7245 out->config.channels = 1;
7246 adev->haptics_config.channels = 1;
7247 } else
7248 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307249 } else {
7250 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007251 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7252 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307253 }
7254 out->hal_ip_format = format = out->format;
7255 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7256 out->hal_op_format = pcm_format_to_hal(out->config.format);
7257 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7258 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007259 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307260 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307261 if (out->hal_ip_format != out->hal_op_format) {
7262 uint32_t buffer_size = out->config.period_size *
7263 format_to_bitwidth_table[out->hal_op_format] *
7264 out->config.channels;
7265 out->convert_buffer = calloc(1, buffer_size);
7266 if (out->convert_buffer == NULL){
7267 ALOGE("Allocation failed for convert buffer for size %d",
7268 out->compr_config.fragment_size);
7269 ret = -ENOMEM;
7270 goto error_open;
7271 }
7272 ALOGD("Convert buffer allocated of size %d", buffer_size);
7273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007274 }
7275
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007276 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7277 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307278
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007279 /* TODO remove this hardcoding and check why width is zero*/
7280 if (out->bit_width == 0)
7281 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307282 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007283 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007284 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307285 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307286 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007287 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007288 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7289 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007290 if(adev->primary_output == NULL)
7291 adev->primary_output = out;
7292 else {
7293 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007294 ret = -EEXIST;
7295 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007296 }
7297 }
7298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007299 /* Check if this usecase is already existing */
7300 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007301 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7302 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007303 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007304 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007305 ret = -EEXIST;
7306 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007307 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007309 pthread_mutex_unlock(&adev->lock);
7310
7311 out->stream.common.get_sample_rate = out_get_sample_rate;
7312 out->stream.common.set_sample_rate = out_set_sample_rate;
7313 out->stream.common.get_buffer_size = out_get_buffer_size;
7314 out->stream.common.get_channels = out_get_channels;
7315 out->stream.common.get_format = out_get_format;
7316 out->stream.common.set_format = out_set_format;
7317 out->stream.common.standby = out_standby;
7318 out->stream.common.dump = out_dump;
7319 out->stream.common.set_parameters = out_set_parameters;
7320 out->stream.common.get_parameters = out_get_parameters;
7321 out->stream.common.add_audio_effect = out_add_audio_effect;
7322 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7323 out->stream.get_latency = out_get_latency;
7324 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007325#ifdef NO_AUDIO_OUT
7326 out->stream.write = out_write_for_no_output;
7327#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007328 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007329#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007330 out->stream.get_render_position = out_get_render_position;
7331 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007332 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333
Haynes Mathew George16081042017-05-31 17:16:49 -07007334 if (out->realtime)
7335 out->af_period_multiplier = af_period_multiplier;
7336 else
7337 out->af_period_multiplier = 1;
7338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007339 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007340 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007341 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007342
7343 config->format = out->stream.common.get_format(&out->stream.common);
7344 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7345 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307346 register_format(out->format, out->supported_formats);
7347 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7348 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007349
Aalique Grahame22e49102018-12-18 14:23:57 -08007350 out->error_log = error_log_create(
7351 ERROR_LOG_ENTRIES,
7352 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7353
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307354 /*
7355 By locking output stream before registering, we allow the callback
7356 to update stream's state only after stream's initial state is set to
7357 adev state.
7358 */
7359 lock_output_stream(out);
7360 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7361 pthread_mutex_lock(&adev->lock);
7362 out->card_status = adev->card_status;
7363 pthread_mutex_unlock(&adev->lock);
7364 pthread_mutex_unlock(&out->lock);
7365
Aalique Grahame22e49102018-12-18 14:23:57 -08007366 stream_app_type_cfg_init(&out->app_type_cfg);
7367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007368 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307369 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007370 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007371
7372 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7373 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7374 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007375 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307376 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007377 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007378 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307379 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007380 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7381 out->usecase, PCM_PLAYBACK);
7382 hdlr_stream_cfg.flags = out->flags;
7383 hdlr_stream_cfg.type = PCM_PLAYBACK;
7384 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7385 &hdlr_stream_cfg);
7386 if (ret) {
7387 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7388 out->adsp_hdlr_stream_handle = NULL;
7389 }
7390 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307391 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007392 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007393 if (ret < 0) {
7394 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7395 out->ip_hdlr_handle = NULL;
7396 }
7397 }
Derek Chenf939fb72018-11-13 13:34:41 -08007398
7399 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7400 calloc(1, sizeof(streams_output_ctxt_t));
7401 if (out_ctxt == NULL) {
7402 ALOGE("%s fail to allocate output ctxt", __func__);
7403 ret = -ENOMEM;
7404 goto error_open;
7405 }
7406 out_ctxt->output = out;
7407
7408 pthread_mutex_lock(&adev->lock);
7409 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7410 pthread_mutex_unlock(&adev->lock);
7411
Eric Laurent994a6932013-07-17 11:51:42 -07007412 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007413 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007414
7415error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307416 if (out->convert_buffer)
7417 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007418 free(out);
7419 *stream_out = NULL;
7420 ALOGD("%s: exit: ret %d", __func__, ret);
7421 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007422}
7423
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307424void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007425 struct audio_stream_out *stream)
7426{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007427 struct stream_out *out = (struct stream_out *)stream;
7428 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007429 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007430
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007431 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307432
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307433 // must deregister from sndmonitor first to prevent races
7434 // between the callback and close_stream
7435 audio_extn_snd_mon_unregister_listener(out);
7436
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007437 /* close adsp hdrl session before standby */
7438 if (out->adsp_hdlr_stream_handle) {
7439 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7440 if (ret)
7441 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7442 out->adsp_hdlr_stream_handle = NULL;
7443 }
7444
Manish Dewangan21a850a2017-08-14 12:03:55 +05307445 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007446 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7447 out->ip_hdlr_handle = NULL;
7448 }
7449
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007450 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307451 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007452 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307453 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307454 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007455 if(ret != 0)
7456 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7457 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007458 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007459 out_standby(&stream->common);
7460
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007461 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007462 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007463 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007464 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007465 if (out->compr_config.codec != NULL)
7466 free(out->compr_config.codec);
7467 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007468
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307469 out->a2dp_compress_mute = false;
7470
Varun Balaraje49253e2017-07-06 19:48:56 +05307471 if (is_interactive_usecase(out->usecase))
7472 free_interactive_usecase(adev, out->usecase);
7473
Ashish Jain83a6cc22016-06-28 14:34:17 +05307474 if (out->convert_buffer != NULL) {
7475 free(out->convert_buffer);
7476 out->convert_buffer = NULL;
7477 }
7478
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007479 if (adev->voice_tx_output == out)
7480 adev->voice_tx_output = NULL;
7481
Aalique Grahame22e49102018-12-18 14:23:57 -08007482 error_log_destroy(out->error_log);
7483 out->error_log = NULL;
7484
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307485 if (adev->primary_output == out)
7486 adev->primary_output = NULL;
7487
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007488 pthread_cond_destroy(&out->cond);
7489 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007490
7491 pthread_mutex_lock(&adev->lock);
7492 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7493 if (out_ctxt != NULL) {
7494 list_remove(&out_ctxt->list);
7495 free(out_ctxt);
7496 } else {
7497 ALOGW("%s, output stream already closed", __func__);
7498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007499 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007500 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007501 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007502}
7503
7504static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7505{
7506 struct audio_device *adev = (struct audio_device *)dev;
7507 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007508 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007509 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007510 int ret;
7511 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007512 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007513
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007514 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007515 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007516
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307517 if (!parms)
7518 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307519
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307520 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7521 if (ret >= 0) {
7522 /* When set to false, HAL should disable EC and NS */
7523 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7524 adev->bt_sco_on = true;
7525 else
7526 adev->bt_sco_on = false;
7527 }
7528
Naresh Tanniru4c630392014-05-12 01:05:52 +05307529 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007530 status = voice_set_parameters(adev, parms);
7531 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007532 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007533
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007534 status = platform_set_parameters(adev->platform, parms);
7535 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007536 goto done;
7537
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007538 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7539 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007540 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007541 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7542 adev->bluetooth_nrec = true;
7543 else
7544 adev->bluetooth_nrec = false;
7545 }
7546
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007547 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7548 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007549 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7550 adev->screen_off = false;
7551 else
7552 adev->screen_off = true;
7553 }
7554
Aalique Grahame22e49102018-12-18 14:23:57 -08007555#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007556 ret = str_parms_get_int(parms, "rotation", &val);
7557 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007558 bool reverse_speakers = false;
7559 switch(val) {
7560 // FIXME: note that the code below assumes that the speakers are in the correct placement
7561 // relative to the user when the device is rotated 90deg from its default rotation. This
7562 // assumption is device-specific, not platform-specific like this code.
7563 case 270:
7564 reverse_speakers = true;
7565 break;
7566 case 0:
7567 case 90:
7568 case 180:
7569 break;
7570 default:
7571 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007572 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007573 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007574 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007575 // check and set swap
7576 // - check if orientation changed and speaker active
7577 // - set rotation and cache the rotation value
7578 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007579 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007580 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007581#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007582
Mingming Yin514a8bc2014-07-29 15:22:21 -07007583 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7584 if (ret >= 0) {
7585 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7586 adev->bt_wb_speech_enabled = true;
7587 else
7588 adev->bt_wb_speech_enabled = false;
7589 }
7590
Zhou Song12c29502019-03-16 10:37:18 +08007591 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
7592 if (ret >= 0) {
7593 val = atoi(value);
7594 adev->swb_speech_mode = val;
7595 }
7596
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007597 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7598 if (ret >= 0) {
7599 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307600 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007601 if (audio_is_output_device(val) &&
7602 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007603 ALOGV("cache new ext disp type and edid");
7604 ret = platform_get_ext_disp_type(adev->platform);
7605 if (ret < 0) {
7606 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307607 } else {
7608 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007609 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307610 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007611 /*
7612 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7613 * Per AudioPolicyManager, USB device is higher priority than WFD.
7614 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7615 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7616 * starting voice call on USB
7617 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007618 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307619 if (ret >= 0)
7620 audio_extn_usb_add_device(device, atoi(value));
7621
Zhou Song6f862822017-11-06 17:27:57 +08007622 if (!audio_extn_usb_is_tunnel_supported()) {
7623 ALOGV("detected USB connect .. disable proxy");
7624 adev->allow_afe_proxy_usage = false;
7625 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007626 }
7627 }
7628
7629 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7630 if (ret >= 0) {
7631 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307632 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007633 /*
7634 * The HDMI / Displayport disconnect handling has been moved to
7635 * audio extension to ensure that its parameters are not
7636 * invalidated prior to updating sysfs of the disconnect event
7637 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7638 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307639 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007640 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307641 if (ret >= 0)
7642 audio_extn_usb_remove_device(device, atoi(value));
7643
Zhou Song6f862822017-11-06 17:27:57 +08007644 if (!audio_extn_usb_is_tunnel_supported()) {
7645 ALOGV("detected USB disconnect .. enable proxy");
7646 adev->allow_afe_proxy_usage = true;
7647 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007648 }
7649 }
7650
Aalique Grahame22e49102018-12-18 14:23:57 -08007651 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007652 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007653
7654 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007655 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307656 struct audio_usecase *usecase;
7657 struct listnode *node;
7658 list_for_each(node, &adev->usecase_list) {
7659 usecase = node_to_item(node, struct audio_usecase, list);
7660 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007661 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307662 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007663
7664 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307665 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007666 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307667 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307668 //force device switch to re configure encoder
7669 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307670 audio_extn_a2dp_set_handoff_mode(false);
7671 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307672 break;
7673 }
7674 }
7675 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007676
7677 //handle vr audio setparam
7678 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7679 value, sizeof(value));
7680 if (ret >= 0) {
7681 ALOGI("Setting vr mode to be %s", value);
7682 if (!strncmp(value, "true", 4)) {
7683 adev->vr_audio_mode_enabled = true;
7684 ALOGI("Setting vr mode to true");
7685 } else if (!strncmp(value, "false", 5)) {
7686 adev->vr_audio_mode_enabled = false;
7687 ALOGI("Setting vr mode to false");
7688 } else {
7689 ALOGI("wrong vr mode set");
7690 }
7691 }
7692
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307693 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007694done:
7695 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007696 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307697error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007698 ALOGV("%s: exit with code(%d)", __func__, status);
7699 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007700}
7701
7702static char* adev_get_parameters(const struct audio_hw_device *dev,
7703 const char *keys)
7704{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307705 ALOGD("%s:%s", __func__, keys);
7706
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007707 struct audio_device *adev = (struct audio_device *)dev;
7708 struct str_parms *reply = str_parms_create();
7709 struct str_parms *query = str_parms_create_str(keys);
7710 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307711 char value[256] = {0};
7712 int ret = 0;
7713
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007714 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007715 if (reply) {
7716 str_parms_destroy(reply);
7717 }
7718 if (query) {
7719 str_parms_destroy(query);
7720 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007721 ALOGE("adev_get_parameters: failed to create query or reply");
7722 return NULL;
7723 }
7724
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007725 //handle vr audio getparam
7726
7727 ret = str_parms_get_str(query,
7728 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7729 value, sizeof(value));
7730
7731 if (ret >= 0) {
7732 bool vr_audio_enabled = false;
7733 pthread_mutex_lock(&adev->lock);
7734 vr_audio_enabled = adev->vr_audio_mode_enabled;
7735 pthread_mutex_unlock(&adev->lock);
7736
7737 ALOGI("getting vr mode to %d", vr_audio_enabled);
7738
7739 if (vr_audio_enabled) {
7740 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7741 "true");
7742 goto exit;
7743 } else {
7744 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7745 "false");
7746 goto exit;
7747 }
7748 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007749
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007750 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007751 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007752 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007753 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007754 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307755 pthread_mutex_unlock(&adev->lock);
7756
Naresh Tannirud7205b62014-06-20 02:54:48 +05307757exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007758 str = str_parms_to_str(reply);
7759 str_parms_destroy(query);
7760 str_parms_destroy(reply);
7761
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307762 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007763 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007764}
7765
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007766static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007767{
7768 return 0;
7769}
7770
7771static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7772{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007773 int ret;
7774 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007775
7776 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7777
Haynes Mathew George5191a852013-09-11 14:19:36 -07007778 pthread_mutex_lock(&adev->lock);
7779 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007780 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007781 pthread_mutex_unlock(&adev->lock);
7782 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007783}
7784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007785static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7786 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007787{
7788 return -ENOSYS;
7789}
7790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007791static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7792 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007793{
7794 return -ENOSYS;
7795}
7796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007797static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7798 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007799{
7800 return -ENOSYS;
7801}
7802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007803static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7804 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007805{
7806 return -ENOSYS;
7807}
7808
7809static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7810{
7811 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007812 struct listnode *node;
7813 struct audio_usecase *usecase = NULL;
7814 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08007815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007816 pthread_mutex_lock(&adev->lock);
7817 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007818 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007819 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007820 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007821 list_for_each(node, &adev->usecase_list) {
7822 usecase = node_to_item(node, struct audio_usecase, list);
7823 if (usecase->type == VOICE_CALL)
7824 break;
7825 }
7826 if (usecase &&
7827 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7828 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7829 true);
7830 if (ret != 0) {
7831 /* default service interval was successfully updated,
7832 reopen USB backend with new service interval */
7833 check_usecases_codec_backend(adev,
7834 usecase,
7835 usecase->out_snd_device);
7836 }
7837 }
7838
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007839 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007840 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007841 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08007842 // restore device for other active usecases after stop call
7843 list_for_each(node, &adev->usecase_list) {
7844 usecase = node_to_item(node, struct audio_usecase, list);
7845 select_devices(adev, usecase->id);
7846 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007847 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007848 }
7849 pthread_mutex_unlock(&adev->lock);
7850 return 0;
7851}
7852
7853static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7854{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007855 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007856 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007857
7858 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007859 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007860 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007861
Derek Chend2530072014-11-24 12:39:14 -08007862 if (adev->ext_hw_plugin)
7863 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007864
7865 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007866 pthread_mutex_unlock(&adev->lock);
7867
7868 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007869}
7870
7871static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7872{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007873 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007874 return 0;
7875}
7876
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007877static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007878 const struct audio_config *config)
7879{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007880 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007881
Aalique Grahame22e49102018-12-18 14:23:57 -08007882 /* Don't know if USB HIFI in this context so use true to be conservative */
7883 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7884 true /*is_usb_hifi */) != 0)
7885 return 0;
7886
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007887 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7888 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007889}
7890
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007891static bool adev_input_allow_hifi_record(struct audio_device *adev,
7892 audio_devices_t devices,
7893 audio_input_flags_t flags,
7894 audio_source_t source) {
7895 const bool allowed = true;
7896
7897 if (!audio_is_usb_in_device(devices))
7898 return !allowed;
7899
7900 switch (flags) {
7901 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007902 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007903 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7904 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007905 default:
7906 return !allowed;
7907 }
7908
7909 switch (source) {
7910 case AUDIO_SOURCE_DEFAULT:
7911 case AUDIO_SOURCE_MIC:
7912 case AUDIO_SOURCE_UNPROCESSED:
7913 break;
7914 default:
7915 return !allowed;
7916 }
7917
7918 switch (adev->mode) {
7919 case 0:
7920 break;
7921 default:
7922 return !allowed;
7923 }
7924
7925 return allowed;
7926}
7927
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007928static int adev_update_voice_comm_input_stream(struct stream_in *in,
7929 struct audio_config *config)
7930{
7931 bool valid_rate = (config->sample_rate == 8000 ||
7932 config->sample_rate == 16000 ||
7933 config->sample_rate == 32000 ||
7934 config->sample_rate == 48000);
7935 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7936
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007937 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08007938 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007939 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7940 in->config = default_pcm_config_voip_copp;
7941 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7942 DEFAULT_VOIP_BUF_DURATION_MS,
7943 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007944 } else {
7945 ALOGW("%s No valid input in voip, use defaults"
7946 "sample rate %u, channel mask 0x%X",
7947 __func__, config->sample_rate, in->channel_mask);
7948 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007949 in->config.rate = config->sample_rate;
7950 in->sample_rate = config->sample_rate;
7951 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007952 //XXX needed for voice_extn_compress_voip_open_input_stream
7953 in->config.rate = config->sample_rate;
7954 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7955 voice_extn_compress_voip_is_active(in->dev)) &&
7956 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7957 valid_rate && valid_ch) {
7958 voice_extn_compress_voip_open_input_stream(in);
7959 // update rate entries to match config from AF
7960 in->config.rate = config->sample_rate;
7961 in->sample_rate = config->sample_rate;
7962 } else {
7963 ALOGW("%s compress voip not active, use defaults", __func__);
7964 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007965 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007966 return 0;
7967}
7968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007969static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007970 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007971 audio_devices_t devices,
7972 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007973 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307974 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007975 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007976 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007977{
7978 struct audio_device *adev = (struct audio_device *)dev;
7979 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007980 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007981 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007982 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307983 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007984 bool is_usb_dev = audio_is_usb_in_device(devices);
7985 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7986 devices,
7987 flags,
7988 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307989
kunleizdff872d2018-08-20 14:40:33 +08007990 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007991 is_usb_dev = false;
7992 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7993 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7994 __func__, devices);
7995 }
7996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007997 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007998
7999 if (!(is_usb_dev && may_use_hifi_record)) {
8000 if (config->sample_rate == 0)
8001 config->sample_rate = 48000;
8002 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8003 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8004 if (config->format == AUDIO_FORMAT_DEFAULT)
8005 config->format = AUDIO_FORMAT_PCM_16_BIT;
8006
8007 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8008
Aalique Grahame22e49102018-12-18 14:23:57 -08008009 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8010 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008011 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008013
8014 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008015
8016 if (!in) {
8017 ALOGE("failed to allocate input stream");
8018 return -ENOMEM;
8019 }
8020
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308021 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308022 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8023 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008024 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008025 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008027 in->stream.common.get_sample_rate = in_get_sample_rate;
8028 in->stream.common.set_sample_rate = in_set_sample_rate;
8029 in->stream.common.get_buffer_size = in_get_buffer_size;
8030 in->stream.common.get_channels = in_get_channels;
8031 in->stream.common.get_format = in_get_format;
8032 in->stream.common.set_format = in_set_format;
8033 in->stream.common.standby = in_standby;
8034 in->stream.common.dump = in_dump;
8035 in->stream.common.set_parameters = in_set_parameters;
8036 in->stream.common.get_parameters = in_get_parameters;
8037 in->stream.common.add_audio_effect = in_add_audio_effect;
8038 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8039 in->stream.set_gain = in_set_gain;
8040 in->stream.read = in_read;
8041 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008042 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308043 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008044
8045 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008046 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008047 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008048 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008049 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008050 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008051 in->bit_width = 16;
8052 in->af_period_multiplier = 1;
8053
Aalique Grahame22e49102018-12-18 14:23:57 -08008054 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
8055 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8056 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8057 /* Force channel config requested to mono if incall
8058 record is being requested for only uplink/downlink */
8059 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8060 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8061 ret = -EINVAL;
8062 goto err_open;
8063 }
8064 }
8065
Haynes Mathew George46740472017-10-27 18:40:12 -07008066 /* Update config params with the requested sample rate and channels */
8067 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
8068 (adev->mode != AUDIO_MODE_IN_CALL)) {
8069 ret = -EINVAL;
8070 goto err_open;
8071 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008072
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008073 if (is_usb_dev && may_use_hifi_record) {
8074 /* HiFi record selects an appropriate format, channel, rate combo
8075 depending on sink capabilities*/
8076 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8077 &config->format,
8078 &in->supported_formats[0],
8079 MAX_SUPPORTED_FORMATS,
8080 &config->channel_mask,
8081 &in->supported_channel_masks[0],
8082 MAX_SUPPORTED_CHANNEL_MASKS,
8083 &config->sample_rate,
8084 &in->supported_sample_rates[0],
8085 MAX_SUPPORTED_SAMPLE_RATES);
8086 if (ret != 0) {
8087 ret = -EINVAL;
8088 goto err_open;
8089 }
8090 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008091 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308092 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308093 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8094 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8095 in->config.format = PCM_FORMAT_S32_LE;
8096 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308097 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8098 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8099 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8100 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8101 bool ret_error = false;
8102 in->bit_width = 24;
8103 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8104 from HAL is 24_packed and 8_24
8105 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8106 24_packed return error indicating supported format is 24_packed
8107 *> In case of any other source requesting 24 bit or float return error
8108 indicating format supported is 16 bit only.
8109
8110 on error flinger will retry with supported format passed
8111 */
8112 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8113 (source != AUDIO_SOURCE_CAMCORDER)) {
8114 config->format = AUDIO_FORMAT_PCM_16_BIT;
8115 if (config->sample_rate > 48000)
8116 config->sample_rate = 48000;
8117 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008118 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8119 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308120 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8121 ret_error = true;
8122 }
8123
8124 if (ret_error) {
8125 ret = -EINVAL;
8126 goto err_open;
8127 }
8128 }
8129
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008130 in->channel_mask = config->channel_mask;
8131 in->format = config->format;
8132
8133 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308134
8135 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8136 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8137 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8138 else {
8139 ret = -EINVAL;
8140 goto err_open;
8141 }
8142 }
8143
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008144 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8145 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8146 is_low_latency = true;
8147#if LOW_LATENCY_CAPTURE_USE_CASE
8148 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8149#endif
8150 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008151 if (!in->realtime) {
8152 in->config = pcm_config_audio_capture;
8153 frame_size = audio_stream_in_frame_size(&in->stream);
8154 buffer_size = get_input_buffer_size(config->sample_rate,
8155 config->format,
8156 channel_count,
8157 is_low_latency);
8158 in->config.period_size = buffer_size / frame_size;
8159 in->config.rate = config->sample_rate;
8160 in->af_period_multiplier = 1;
8161 } else {
8162 // period size is left untouched for rt mode playback
8163 in->config = pcm_config_audio_capture_rt;
8164 in->af_period_multiplier = af_period_multiplier;
8165 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008166 }
8167
8168 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8169 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8170 in->realtime = 0;
8171 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8172 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008173 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiang7c30c612018-11-27 18:45:53 +08008174 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008175 in->stream.start = in_start;
8176 in->stream.stop = in_stop;
8177 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8178 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008179 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008180 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8181 } else if (in->realtime) {
8182 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008183 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008184 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008185 in->sample_rate = in->config.rate;
8186 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008187 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008188 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8189 in->config = pcm_config_audio_capture;
8190 frame_size = audio_stream_in_frame_size(&in->stream);
8191 buffer_size = get_input_buffer_size(config->sample_rate,
8192 config->format,
8193 channel_count,
8194 false /*is_low_latency*/);
8195 in->config.period_size = buffer_size / frame_size;
8196 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008197 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008198 switch (config->format) {
8199 case AUDIO_FORMAT_PCM_32_BIT:
8200 in->bit_width = 32;
8201 break;
8202 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8203 case AUDIO_FORMAT_PCM_8_24_BIT:
8204 in->bit_width = 24;
8205 break;
8206 default:
8207 in->bit_width = 16;
8208 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008209 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08008210 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008211 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308212 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008213 if (config->sample_rate == 0)
8214 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8215 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8216 config->sample_rate != 8000) {
8217 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8218 ret = -EINVAL;
8219 goto err_open;
8220 }
8221 if (config->format == AUDIO_FORMAT_DEFAULT)
8222 config->format = AUDIO_FORMAT_PCM_16_BIT;
8223 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8224 config->format = AUDIO_FORMAT_PCM_16_BIT;
8225 ret = -EINVAL;
8226 goto err_open;
8227 }
8228
8229 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8230 in->config = pcm_config_afe_proxy_record;
8231 in->config.channels = channel_count;
8232 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308233 in->sample_rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008234 in->af_period_multiplier = 1;
8235 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8236 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8237 (config->sample_rate == 8000 ||
8238 config->sample_rate == 16000 ||
8239 config->sample_rate == 32000 ||
8240 config->sample_rate == 48000) &&
8241 channel_count == 1) {
8242 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8243 in->config = pcm_config_audio_capture;
8244 frame_size = audio_stream_in_frame_size(&in->stream);
8245 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8246 config->sample_rate,
8247 config->format,
8248 channel_count, false /*is_low_latency*/);
8249 in->config.period_size = buffer_size / frame_size;
8250 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8251 in->config.rate = config->sample_rate;
8252 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008253 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308254 int ret_val;
8255 pthread_mutex_lock(&adev->lock);
8256 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8257 in, config, &channel_mask_updated);
8258 pthread_mutex_unlock(&adev->lock);
8259
8260 if (!ret_val) {
8261 if (channel_mask_updated == true) {
8262 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8263 __func__, config->channel_mask);
8264 ret = -EINVAL;
8265 goto err_open;
8266 }
8267 ALOGD("%s: created multi-channel session succesfully",__func__);
8268 } else if (audio_extn_compr_cap_enabled() &&
8269 audio_extn_compr_cap_format_supported(config->format) &&
8270 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8271 audio_extn_compr_cap_init(in);
8272 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05308273 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05308274 ret = audio_extn_cin_configure_input_stream(in);
8275 if (ret)
8276 goto err_open;
8277 } else {
8278 in->config = pcm_config_audio_capture;
8279 in->config.rate = config->sample_rate;
8280 in->config.format = pcm_format_from_audio_format(config->format);
8281 in->config.channels = channel_count;
8282 in->sample_rate = config->sample_rate;
8283 in->format = config->format;
8284 frame_size = audio_stream_in_frame_size(&in->stream);
8285 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008286 config->format,
8287 channel_count,
8288 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008289 /* prevent division-by-zero */
8290 if (frame_size == 0) {
8291 ALOGE("%s: Error frame_size==0", __func__);
8292 ret = -EINVAL;
8293 goto err_open;
8294 }
8295
Revathi Uddarajud2634032017-12-07 14:42:34 +05308296 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008297 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008298
Revathi Uddarajud2634032017-12-07 14:42:34 +05308299 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8300 /* optionally use VOIP usecase depending on config(s) */
8301 ret = adev_update_voice_comm_input_stream(in, config);
8302 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008303
Revathi Uddarajud2634032017-12-07 14:42:34 +05308304 if (ret) {
8305 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8306 goto err_open;
8307 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008308 }
kunleiz28c73e72019-03-27 17:24:04 +08008309#ifdef CONCURRENT_CAPTURE_ENABLED
8310 /* Acquire lock to avoid two concurrent use cases initialized to
8311 same pcm record use case */
8312
8313 pthread_mutex_lock(&adev->lock);
8314 if (in->usecase == USECASE_AUDIO_RECORD) {
8315 if (!(adev->pcm_record_uc_state)) {
8316 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8317 adev->pcm_record_uc_state = 1;
8318 } else {
8319 /* Assign compress record use case for second record */
8320 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8321 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8322 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8323 }
8324 }
8325 pthread_mutex_unlock(&adev->lock);
8326#endif
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008327 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308328 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8329 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008330 devices, flags, in->format,
8331 in->sample_rate, in->bit_width,
8332 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308333 register_format(in->format, in->supported_formats);
8334 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8335 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308336
Aalique Grahame22e49102018-12-18 14:23:57 -08008337 in->error_log = error_log_create(
8338 ERROR_LOG_ENTRIES,
8339 1000000000 /* aggregate consecutive identical errors within one second */);
8340
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008341 /* This stream could be for sound trigger lab,
8342 get sound trigger pcm if present */
8343 audio_extn_sound_trigger_check_and_get_session(in);
8344
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308345 lock_input_stream(in);
8346 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8347 pthread_mutex_lock(&adev->lock);
8348 in->card_status = adev->card_status;
8349 pthread_mutex_unlock(&adev->lock);
8350 pthread_mutex_unlock(&in->lock);
8351
Aalique Grahame22e49102018-12-18 14:23:57 -08008352 stream_app_type_cfg_init(&in->app_type_cfg);
8353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008354 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008355
8356 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8357 calloc(1, sizeof(streams_input_ctxt_t));
8358 if (in_ctxt == NULL) {
8359 ALOGE("%s fail to allocate input ctxt", __func__);
8360 ret = -ENOMEM;
8361 goto err_open;
8362 }
8363 in_ctxt->input = in;
8364
8365 pthread_mutex_lock(&adev->lock);
8366 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8367 pthread_mutex_unlock(&adev->lock);
8368
Eric Laurent994a6932013-07-17 11:51:42 -07008369 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008370 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008371
8372err_open:
8373 free(in);
8374 *stream_in = NULL;
8375 return ret;
8376}
8377
8378static void adev_close_input_stream(struct audio_hw_device *dev,
8379 struct audio_stream_in *stream)
8380{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008381 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008382 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008383 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308384
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308385 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008386
kunleiz70e57612018-12-28 17:50:23 +08008387 /* must deregister from sndmonitor first to prevent races
8388 * between the callback and close_stream
8389 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308390 audio_extn_snd_mon_unregister_listener(stream);
8391
kunleiz70e57612018-12-28 17:50:23 +08008392 /* Disable echo reference if there are no active input, hfp call
8393 * and sound trigger while closing input stream
8394 */
8395 if (!adev->active_input &&
8396 !audio_extn_hfp_is_active(adev) &&
8397 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008398 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008399 else
8400 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308401
Pallavid7c7a272018-01-16 11:22:55 +05308402 if (in == NULL) {
8403 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8404 return;
8405 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008406 error_log_destroy(in->error_log);
8407 in->error_log = NULL;
8408
Pallavid7c7a272018-01-16 11:22:55 +05308409
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008410 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308411 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008412 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308413 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008414 if (ret != 0)
8415 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8416 __func__, ret);
8417 } else
8418 in_standby(&stream->common);
8419
Revathi Uddarajud2634032017-12-07 14:42:34 +05308420 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308421 if (in->usecase == USECASE_AUDIO_RECORD) {
8422 adev->pcm_record_uc_state = 0;
8423 }
8424
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008425 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008426 audio_extn_ssr_deinit();
8427 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008428
Garmond Leunge2433c32017-09-28 21:51:22 -07008429 if (audio_extn_ffv_get_stream() == in) {
8430 audio_extn_ffv_stream_deinit();
8431 }
8432
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308433 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008434 audio_extn_compr_cap_format_supported(in->config.format))
8435 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308436
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308437 if (audio_extn_cin_attached_usecase(in->usecase))
8438 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008439
Mingming Yinfd7607b2016-01-22 12:48:44 -08008440 if (in->is_st_session) {
8441 ALOGV("%s: sound trigger pcm stop lab", __func__);
8442 audio_extn_sound_trigger_stop_lab(in);
8443 }
Derek Chenf939fb72018-11-13 13:34:41 -08008444 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8445 if (in_ctxt != NULL) {
8446 list_remove(&in_ctxt->list);
8447 free(in_ctxt);
8448 } else {
8449 ALOGW("%s, input stream already closed", __func__);
8450 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008451 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308452 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008453 return;
8454}
8455
Aalique Grahame22e49102018-12-18 14:23:57 -08008456/* verifies input and output devices and their capabilities.
8457 *
8458 * This verification is required when enabling extended bit-depth or
8459 * sampling rates, as not all qcom products support it.
8460 *
8461 * Suitable for calling only on initialization such as adev_open().
8462 * It fills the audio_device use_case_table[] array.
8463 *
8464 * Has a side-effect that it needs to configure audio routing / devices
8465 * in order to power up the devices and read the device parameters.
8466 * It does not acquire any hw device lock. Should restore the devices
8467 * back to "normal state" upon completion.
8468 */
8469static int adev_verify_devices(struct audio_device *adev)
8470{
8471 /* enumeration is a bit difficult because one really wants to pull
8472 * the use_case, device id, etc from the hidden pcm_device_table[].
8473 * In this case there are the following use cases and device ids.
8474 *
8475 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8476 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8477 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8478 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8479 * [USECASE_AUDIO_RECORD] = {0, 0},
8480 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8481 * [USECASE_VOICE_CALL] = {2, 2},
8482 *
8483 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8484 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8485 */
8486
8487 /* should be the usecases enabled in adev_open_input_stream() */
8488 static const int test_in_usecases[] = {
8489 USECASE_AUDIO_RECORD,
8490 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8491 };
8492 /* should be the usecases enabled in adev_open_output_stream()*/
8493 static const int test_out_usecases[] = {
8494 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8495 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8496 };
8497 static const usecase_type_t usecase_type_by_dir[] = {
8498 PCM_PLAYBACK,
8499 PCM_CAPTURE,
8500 };
8501 static const unsigned flags_by_dir[] = {
8502 PCM_OUT,
8503 PCM_IN,
8504 };
8505
8506 size_t i;
8507 unsigned dir;
8508 const unsigned card_id = adev->snd_card;
8509
8510 for (dir = 0; dir < 2; ++dir) {
8511 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8512 const unsigned flags_dir = flags_by_dir[dir];
8513 const size_t testsize =
8514 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8515 const int *testcases =
8516 dir ? test_in_usecases : test_out_usecases;
8517 const audio_devices_t audio_device =
8518 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8519
8520 for (i = 0; i < testsize; ++i) {
8521 const audio_usecase_t audio_usecase = testcases[i];
8522 int device_id;
8523 struct pcm_params **pparams;
8524 struct stream_out out;
8525 struct stream_in in;
8526 struct audio_usecase uc_info;
8527 int retval;
8528
8529 pparams = &adev->use_case_table[audio_usecase];
8530 pcm_params_free(*pparams); /* can accept null input */
8531 *pparams = NULL;
8532
8533 /* find the device ID for the use case (signed, for error) */
8534 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8535 if (device_id < 0)
8536 continue;
8537
8538 /* prepare structures for device probing */
8539 memset(&uc_info, 0, sizeof(uc_info));
8540 uc_info.id = audio_usecase;
8541 uc_info.type = usecase_type;
8542 if (dir) {
8543 adev->active_input = &in;
8544 memset(&in, 0, sizeof(in));
8545 in.device = audio_device;
8546 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8547 uc_info.stream.in = &in;
8548 } else {
8549 adev->active_input = NULL;
8550 }
8551 memset(&out, 0, sizeof(out));
8552 out.devices = audio_device; /* only field needed in select_devices */
8553 uc_info.stream.out = &out;
8554 uc_info.devices = audio_device;
8555 uc_info.in_snd_device = SND_DEVICE_NONE;
8556 uc_info.out_snd_device = SND_DEVICE_NONE;
8557 list_add_tail(&adev->usecase_list, &uc_info.list);
8558
8559 /* select device - similar to start_(in/out)put_stream() */
8560 retval = select_devices(adev, audio_usecase);
8561 if (retval >= 0) {
8562 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8563#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008564 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008565 if (*pparams) {
8566 ALOGV("%s: (%s) card %d device %d", __func__,
8567 dir ? "input" : "output", card_id, device_id);
8568 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8569 } else {
8570 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8571 }
8572#endif
8573 }
8574
8575 /* deselect device - similar to stop_(in/out)put_stream() */
8576 /* 1. Get and set stream specific mixer controls */
8577 retval = disable_audio_route(adev, &uc_info);
8578 /* 2. Disable the rx device */
8579 retval = disable_snd_device(adev,
8580 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8581 list_remove(&uc_info.list);
8582 }
8583 }
8584 adev->active_input = NULL; /* restore adev state */
8585 return 0;
8586}
8587
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308588int adev_create_audio_patch(struct audio_hw_device *dev,
8589 unsigned int num_sources,
8590 const struct audio_port_config *sources,
8591 unsigned int num_sinks,
8592 const struct audio_port_config *sinks,
8593 audio_patch_handle_t *handle)
8594{
Derek Chenf939fb72018-11-13 13:34:41 -08008595 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308596
Derek Chenf939fb72018-11-13 13:34:41 -08008597 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8598 num_sources,
8599 sources,
8600 num_sinks,
8601 sinks,
8602 handle);
8603 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8604 num_sources,
8605 sources,
8606 num_sinks,
8607 sinks,
8608 handle);
8609 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308610}
8611
8612int adev_release_audio_patch(struct audio_hw_device *dev,
8613 audio_patch_handle_t handle)
8614{
Derek Chenf939fb72018-11-13 13:34:41 -08008615 int ret;
8616
8617 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8618 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8619 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308620}
8621
8622int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8623{
8624 return audio_extn_hw_loopback_get_audio_port(dev, config);
8625}
8626
8627int adev_set_audio_port_config(struct audio_hw_device *dev,
8628 const struct audio_port_config *config)
8629{
8630 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8631}
8632
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008633static int adev_dump(const audio_hw_device_t *device __unused,
8634 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008635{
8636 return 0;
8637}
8638
8639static int adev_close(hw_device_t *device)
8640{
Aalique Grahame22e49102018-12-18 14:23:57 -08008641 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008642 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008643
8644 if (!adev)
8645 return 0;
8646
8647 pthread_mutex_lock(&adev_init_lock);
8648
8649 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308650 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008651 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008652 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008653 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008654 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308655 audio_extn_utils_release_streams_cfg_lists(
8656 &adev->streams_output_cfg_list,
8657 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308658 if (audio_extn_qaf_is_enabled())
8659 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008660 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008661 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008662 free(adev->snd_dev_ref_cnt);
8663 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008664 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8665 pcm_params_free(adev->use_case_table[i]);
8666 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008667 if (adev->adm_deinit)
8668 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308669 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008670 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308671 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308672 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008673 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308674 if (adev->device_cfg_params) {
8675 free(adev->device_cfg_params);
8676 adev->device_cfg_params = NULL;
8677 }
Derek Chend2530072014-11-24 12:39:14 -08008678 if(adev->ext_hw_plugin)
8679 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008680 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008681 free(device);
8682 adev = NULL;
8683 }
8684 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308685 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008686 return 0;
8687}
8688
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008689/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8690 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8691 * just that it _might_ work.
8692 */
8693static int period_size_is_plausible_for_low_latency(int period_size)
8694{
8695 switch (period_size) {
8696 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008697 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008698 case 240:
8699 case 320:
8700 case 480:
8701 return 1;
8702 default:
8703 return 0;
8704 }
8705}
8706
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308707static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8708{
8709 bool is_snd_card_status = false;
8710 bool is_ext_device_status = false;
8711 char value[32];
8712 int card = -1;
8713 card_status_t status;
8714
8715 if (cookie != adev || !parms)
8716 return;
8717
8718 if (!parse_snd_card_status(parms, &card, &status)) {
8719 is_snd_card_status = true;
8720 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8721 is_ext_device_status = true;
8722 } else {
8723 // not a valid event
8724 return;
8725 }
8726
8727 pthread_mutex_lock(&adev->lock);
8728 if (card == adev->snd_card || is_ext_device_status) {
8729 if (is_snd_card_status && adev->card_status != status) {
8730 adev->card_status = status;
8731 platform_snd_card_update(adev->platform, status);
8732 audio_extn_fm_set_parameters(adev, parms);
8733 } else if (is_ext_device_status) {
8734 platform_set_parameters(adev->platform, parms);
8735 }
8736 }
8737 pthread_mutex_unlock(&adev->lock);
8738 return;
8739}
8740
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308741/* out and adev lock held */
8742static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8743{
8744 struct audio_usecase *uc_info;
8745 float left_p;
8746 float right_p;
8747 audio_devices_t devices;
8748
8749 uc_info = get_usecase_from_list(adev, out->usecase);
8750 if (uc_info == NULL) {
8751 ALOGE("%s: Could not find the usecase (%d) in the list",
8752 __func__, out->usecase);
8753 return -EINVAL;
8754 }
8755
8756 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8757 out->usecase, use_case_table[out->usecase]);
8758
8759 if (restore) {
8760 // restore A2DP device for active usecases and unmute if required
8761 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8762 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8763 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8764 select_devices(adev, uc_info->id);
8765 pthread_mutex_lock(&out->compr_mute_lock);
8766 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8767 (out->a2dp_compress_mute)) {
8768 out->a2dp_compress_mute = false;
8769 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8770 }
8771 pthread_mutex_unlock(&out->compr_mute_lock);
8772 }
8773 } else {
8774 // mute compress stream if suspended
8775 pthread_mutex_lock(&out->compr_mute_lock);
8776 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8777 (!out->a2dp_compress_mute)) {
8778 if (!out->standby) {
8779 ALOGD("%s: selecting speaker and muting stream", __func__);
8780 devices = out->devices;
8781 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8782 left_p = out->volume_l;
8783 right_p = out->volume_r;
8784 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8785 compress_pause(out->compr);
8786 out_set_compr_volume(&out->stream, (float)0, (float)0);
8787 out->a2dp_compress_mute = true;
8788 select_devices(adev, out->usecase);
8789 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8790 compress_resume(out->compr);
8791 out->devices = devices;
8792 out->volume_l = left_p;
8793 out->volume_r = right_p;
8794 }
8795 }
8796 pthread_mutex_unlock(&out->compr_mute_lock);
8797 }
8798 ALOGV("%s: exit", __func__);
8799 return 0;
8800}
8801
8802int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8803{
8804 int ret = 0;
8805
8806 lock_output_stream(out);
8807 pthread_mutex_lock(&adev->lock);
8808
8809 ret = check_a2dp_restore_l(adev, out, restore);
8810
8811 pthread_mutex_unlock(&adev->lock);
8812 pthread_mutex_unlock(&out->lock);
8813 return ret;
8814}
8815
Haynes Mathew George01156f92018-04-13 15:29:54 -07008816void adev_on_battery_status_changed(bool charging)
8817{
8818 pthread_mutex_lock(&adev->lock);
8819 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8820 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008821 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008822 pthread_mutex_unlock(&adev->lock);
8823}
8824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008825static int adev_open(const hw_module_t *module, const char *name,
8826 hw_device_t **device)
8827{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308828 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008829 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308830 char mixer_ctl_name[128] = {0};
8831 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308832
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008833 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008834 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8835
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008836 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008837 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008838 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008839 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008840 ALOGD("%s: returning existing instance of adev", __func__);
8841 ALOGD("%s: exit", __func__);
8842 pthread_mutex_unlock(&adev_init_lock);
8843 return 0;
8844 }
8845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008846 adev = calloc(1, sizeof(struct audio_device));
8847
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008848 if (!adev) {
8849 pthread_mutex_unlock(&adev_init_lock);
8850 return -ENOMEM;
8851 }
8852
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008853 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8854
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008855 // register audio ext hidl at the earliest
8856 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308857#ifdef DYNAMIC_LOG_ENABLED
8858 register_for_dynamic_logging("hal");
8859#endif
8860
Derek Chenf939fb72018-11-13 13:34:41 -08008861 /* default audio HAL major version */
8862 uint32_t maj_version = 2;
8863 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8864 maj_version = atoi(value);
8865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008866 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008867 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008868 adev->device.common.module = (struct hw_module_t *)module;
8869 adev->device.common.close = adev_close;
8870
8871 adev->device.init_check = adev_init_check;
8872 adev->device.set_voice_volume = adev_set_voice_volume;
8873 adev->device.set_master_volume = adev_set_master_volume;
8874 adev->device.get_master_volume = adev_get_master_volume;
8875 adev->device.set_master_mute = adev_set_master_mute;
8876 adev->device.get_master_mute = adev_get_master_mute;
8877 adev->device.set_mode = adev_set_mode;
8878 adev->device.set_mic_mute = adev_set_mic_mute;
8879 adev->device.get_mic_mute = adev_get_mic_mute;
8880 adev->device.set_parameters = adev_set_parameters;
8881 adev->device.get_parameters = adev_get_parameters;
8882 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8883 adev->device.open_output_stream = adev_open_output_stream;
8884 adev->device.close_output_stream = adev_close_output_stream;
8885 adev->device.open_input_stream = adev_open_input_stream;
8886 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308887 adev->device.create_audio_patch = adev_create_audio_patch;
8888 adev->device.release_audio_patch = adev_release_audio_patch;
8889 adev->device.get_audio_port = adev_get_audio_port;
8890 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008891 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308892 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008893
8894 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008895 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008896 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008897 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008898 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008899 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008900 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008901 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308902 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008903 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008904 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008905 /* Init audio feature manager */
8906 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008907 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008908 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08008909 list_init(&adev->active_inputs_list);
8910 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008911 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008912 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308913 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308914 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308915 adev->perf_lock_opts[0] = 0x101;
8916 adev->perf_lock_opts[1] = 0x20E;
8917 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008918 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07008919 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308920 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008922 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008923 adev->platform = platform_init(adev);
8924 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008925 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008926 free(adev->snd_dev_ref_cnt);
8927 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008928 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008929 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8930 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008931 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008932 return -EINVAL;
8933 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008934
Aalique Grahame22e49102018-12-18 14:23:57 -08008935 adev->extspk = audio_extn_extspk_init(adev);
8936
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308937 if (audio_extn_qaf_is_enabled()) {
8938 ret = audio_extn_qaf_init(adev);
8939 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008940 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308941 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008942 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308943 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8944 *device = NULL;
8945 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308946 return ret;
8947 }
8948
8949 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8950 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8951 }
8952
Derek Chenae7b0342019-02-08 15:17:04 -08008953 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08008954 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8955
Eric Laurentc4aef752013-09-12 17:45:53 -07008956 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8957 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8958 if (adev->visualizer_lib == NULL) {
8959 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8960 } else {
8961 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8962 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008963 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008964 "visualizer_hal_start_output");
8965 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008966 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008967 "visualizer_hal_stop_output");
8968 }
8969 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308970 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008971 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008972 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008973 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308974 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008975 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008976
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008977 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8978 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8979 if (adev->offload_effects_lib == NULL) {
8980 ALOGE("%s: DLOPEN failed for %s", __func__,
8981 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8982 } else {
8983 ALOGV("%s: DLOPEN successful for %s", __func__,
8984 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8985 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308986 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008987 "offload_effects_bundle_hal_start_output");
8988 adev->offload_effects_stop_output =
8989 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8990 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008991 adev->offload_effects_set_hpx_state =
8992 (int (*)(bool))dlsym(adev->offload_effects_lib,
8993 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308994 adev->offload_effects_get_parameters =
8995 (void (*)(struct str_parms *, struct str_parms *))
8996 dlsym(adev->offload_effects_lib,
8997 "offload_effects_bundle_get_parameters");
8998 adev->offload_effects_set_parameters =
8999 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9000 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009001 }
9002 }
9003
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009004 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9005 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9006 if (adev->adm_lib == NULL) {
9007 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9008 } else {
9009 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9010 adev->adm_init = (adm_init_t)
9011 dlsym(adev->adm_lib, "adm_init");
9012 adev->adm_deinit = (adm_deinit_t)
9013 dlsym(adev->adm_lib, "adm_deinit");
9014 adev->adm_register_input_stream = (adm_register_input_stream_t)
9015 dlsym(adev->adm_lib, "adm_register_input_stream");
9016 adev->adm_register_output_stream = (adm_register_output_stream_t)
9017 dlsym(adev->adm_lib, "adm_register_output_stream");
9018 adev->adm_deregister_stream = (adm_deregister_stream_t)
9019 dlsym(adev->adm_lib, "adm_deregister_stream");
9020 adev->adm_request_focus = (adm_request_focus_t)
9021 dlsym(adev->adm_lib, "adm_request_focus");
9022 adev->adm_abandon_focus = (adm_abandon_focus_t)
9023 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009024 adev->adm_set_config = (adm_set_config_t)
9025 dlsym(adev->adm_lib, "adm_set_config");
9026 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9027 dlsym(adev->adm_lib, "adm_request_focus_v2");
9028 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9029 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9030 adev->adm_on_routing_change = (adm_on_routing_change_t)
9031 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009032 }
9033 }
9034
Aalique Grahame22e49102018-12-18 14:23:57 -08009035 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009036 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009037 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009038 //initialize this to false for now,
9039 //this will be set to true through set param
9040 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009041
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009042 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009044
9045 if (k_enable_extended_precision)
9046 adev_verify_devices(adev);
9047
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009048 adev->dsp_bit_width_enforce_mode =
9049 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009050
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309051 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9052 &adev->streams_output_cfg_list,
9053 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009054
Kiran Kandi910e1862013-10-29 13:29:42 -07009055 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009056
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009057 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009058 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9059 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009060 trial = atoi(value);
9061 if (period_size_is_plausible_for_low_latency(trial)) {
9062 pcm_config_low_latency.period_size = trial;
9063 pcm_config_low_latency.start_threshold = trial / 4;
9064 pcm_config_low_latency.avail_min = trial / 4;
9065 configured_low_latency_capture_period_size = trial;
9066 }
9067 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009068 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9069 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009070 trial = atoi(value);
9071 if (period_size_is_plausible_for_low_latency(trial)) {
9072 configured_low_latency_capture_period_size = trial;
9073 }
9074 }
9075
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009076 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9077
Aalique Grahame22e49102018-12-18 14:23:57 -08009078 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9079 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009080 af_period_multiplier = atoi(value);
9081 if (af_period_multiplier < 0)
9082 af_period_multiplier = 2;
9083 else if (af_period_multiplier > 4)
9084 af_period_multiplier = 4;
9085
9086 ALOGV("new period_multiplier = %d", af_period_multiplier);
9087 }
9088
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009089 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009090
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009091 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009092 pthread_mutex_unlock(&adev_init_lock);
9093
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009094 if (adev->adm_init)
9095 adev->adm_data = adev->adm_init();
9096
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309097 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309098 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009099 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309100
9101 audio_extn_snd_mon_init();
9102 pthread_mutex_lock(&adev->lock);
9103 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9104 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009105 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9106 /*
9107 * if the battery state callback happens before charging can be queried,
9108 * it will be guarded with the adev->lock held in the cb function and so
9109 * the callback value will reflect the latest state
9110 */
9111 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309112 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009113 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
9114 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309115 /* Allocate memory for Device config params */
9116 adev->device_cfg_params = (struct audio_device_config_param*)
9117 calloc(platform_get_max_codec_backend(),
9118 sizeof(struct audio_device_config_param));
9119 if (adev->device_cfg_params == NULL)
9120 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309121
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309122 /*
9123 * Check if new PSPD matrix mixer control is supported. If not
9124 * supported, then set flag so that old mixer ctrl is sent while
9125 * sending pspd coefficients on older kernel version. Query mixer
9126 * control for default pcm id and channel value one.
9127 */
9128 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9129 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9130
9131 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9132 if (!ctl) {
9133 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9134 __func__, mixer_ctl_name);
9135 adev->use_old_pspd_mix_ctrl = true;
9136 }
9137
Eric Laurent994a6932013-07-17 11:51:42 -07009138 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009139 return 0;
9140}
9141
9142static struct hw_module_methods_t hal_module_methods = {
9143 .open = adev_open,
9144};
9145
9146struct audio_module HAL_MODULE_INFO_SYM = {
9147 .common = {
9148 .tag = HARDWARE_MODULE_TAG,
9149 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9150 .hal_api_version = HARDWARE_HAL_API_VERSION,
9151 .id = AUDIO_HARDWARE_MODULE_ID,
9152 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009153 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009154 .methods = &hal_module_methods,
9155 },
9156};