blob: 5e4064a2a27fe63b3fe1368fae6d3831be4bbf8e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05302 * 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
58#include <cutils/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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.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
Arun Mirpuriebe78a72018-10-04 18:23:46 -070092#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053094#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070095
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070096#define PROXY_OPEN_RETRY_COUNT 100
97#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080098
Mingming Yin08c7e312015-03-16 18:10:58 -070099#ifdef USE_LL_AS_PRIMARY_OUTPUT
100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
102#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700104#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
105#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800106
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700107#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700108#define DEFAULT_VOIP_BUF_DURATION_MS 20
109#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
110#define DEFAULT_VOIP_SAMP_RATE 48000
111
112#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
113
114struct pcm_config default_pcm_config_voip_copp = {
115 .channels = 1,
116 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
117 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
118 .period_count = 2,
119 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800120 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
121 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700124#define MIN_CHANNEL_COUNT 1
125#define DEFAULT_CHANNEL_COUNT 2
126#define MAX_HIFI_CHANNEL_COUNT 8
127
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700128static unsigned int configured_low_latency_capture_period_size =
129 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
130
Haynes Mathew George16081042017-05-31 17:16:49 -0700131#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
132#define MMAP_PERIOD_COUNT_MIN 32
133#define MMAP_PERIOD_COUNT_MAX 512
134#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
135
Eric Laurentb23d5282013-05-14 15:27:20 -0700136struct pcm_config pcm_config_deep_buffer = {
137 .channels = 2,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
140 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_low_latency = {
148 .channels = 2,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
151 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
154 .stop_threshold = INT_MAX,
155 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
156};
157
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700158static int af_period_multiplier = 4;
159struct pcm_config pcm_config_rt = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = ULL_PERIOD_SIZE, //1 ms
163 .period_count = 512, //=> buffer size is 512ms
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
166 .stop_threshold = INT_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = ULL_PERIOD_SIZE, //1 ms
170};
171
Eric Laurentb23d5282013-05-14 15:27:20 -0700172struct pcm_config pcm_config_hdmi_multi = {
173 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = HDMI_MULTI_PERIOD_SIZE,
176 .period_count = HDMI_MULTI_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Haynes Mathew George16081042017-05-31 17:16:49 -0700183struct pcm_config pcm_config_mmap_playback = {
184 .channels = 2,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = MMAP_PERIOD_SIZE*8,
190 .stop_threshold = INT32_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700196struct pcm_config pcm_config_hifi = {
197 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
198 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
199 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
200 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
201 .format = PCM_FORMAT_S24_3LE,
202 .start_threshold = 0,
203 .stop_threshold = INT_MAX,
204 .avail_min = 0,
205};
206
Eric Laurentb23d5282013-05-14 15:27:20 -0700207struct pcm_config pcm_config_audio_capture = {
208 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
210 .format = PCM_FORMAT_S16_LE,
211};
212
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = 2,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_capture = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700239#define AFE_PROXY_CHANNEL_COUNT 2
240#define AFE_PROXY_SAMPLING_RATE 48000
241
242#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
243#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_playback = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
249 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
254};
255
256#define AFE_PROXY_RECORD_PERIOD_SIZE 768
257#define AFE_PROXY_RECORD_PERIOD_COUNT 4
258
259struct pcm_config pcm_config_afe_proxy_record = {
260 .channels = AFE_PROXY_CHANNEL_COUNT,
261 .rate = AFE_PROXY_SAMPLING_RATE,
262 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
263 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
264 .format = PCM_FORMAT_S16_LE,
265 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
266 .stop_threshold = INT_MAX,
267 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
268};
269
Ashish Jainf1eaa582016-05-23 20:54:24 +0530270#define AUDIO_MAX_PCM_FORMATS 7
271
272const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
273 [AUDIO_FORMAT_DEFAULT] = 0,
274 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
275 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
276 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
278 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
279 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
280};
281
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800282const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700283 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
284 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
286 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700287 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700288 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700289 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
296 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700297 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
298 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700299 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700300
Eric Laurentb23d5282013-05-14 15:27:20 -0700301 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700302 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530303 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
304 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
305 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530306 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
307 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700308 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700309 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700310 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700311 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700312
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800313 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800314 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700315 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700317 [USECASE_VOICE2_CALL] = "voice2-call",
318 [USECASE_VOLTE_CALL] = "volte-call",
319 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800320 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800321 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
322 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800323 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700324 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
325 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
326 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800327 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
328 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
329 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
330
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700331 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
332 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700333 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
334 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700335
336 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
337 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530338 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700339
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530340 /* Transcode loopback cases */
341 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700342
343 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
344 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530345 /* For Interactive Audio Streams */
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
353 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700354
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800355 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
356
357 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700358};
359
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700360static const audio_usecase_t offload_usecases[] = {
361 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700362 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
369 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700370};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800371
Varun Balaraje49253e2017-07-06 19:48:56 +0530372static const audio_usecase_t interactive_usecases[] = {
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
380 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
381};
382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383#define STRING_TO_ENUM(string) { #string, string }
384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800385struct string_to_enum {
386 const char *name;
387 uint32_t value;
388};
389
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700390static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800398 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
401 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
409 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800410};
411
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700412static const struct string_to_enum formats_name_to_enum_table[] = {
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
415 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700416 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
418 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700419 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800420 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
421 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700422 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800423};
424
425//list of all supported sample rates by HDMI specification.
426static const int out_hdmi_sample_rates[] = {
427 32000, 44100, 48000, 88200, 96000, 176400, 192000,
428};
429
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700430static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800431 STRING_TO_ENUM(32000),
432 STRING_TO_ENUM(44100),
433 STRING_TO_ENUM(48000),
434 STRING_TO_ENUM(88200),
435 STRING_TO_ENUM(96000),
436 STRING_TO_ENUM(176400),
437 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700438};
439
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700440static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700441static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700442static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700443//cache last MBDRC cal step level
444static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700445
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530446static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
447static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuriebe78a72018-10-04 18:23:46 -0700448static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800449static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530450
Vatsal Buchaa1358992018-11-14 13:25:08 +0530451#ifdef AUDIO_FEATURE_ENABLED_GCOV
452extern void __gcov_flush();
453static void enable_gcov()
454{
455 __gcov_flush();
456}
457#else
458static void enable_gcov()
459{
460}
461#endif
462
Ramjee Singhacef98f2019-06-28 11:01:25 +0530463#if ANDROID_PLATFORM_SDK_VERSION >= 29
464static int in_set_microphone_direction(const struct audio_stream_in *stream,
465 audio_microphone_direction_t dir);
466static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
467#endif
468
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700469static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
470 int flags __unused)
471{
472 int dir = 0;
473 switch (uc_id) {
474 case USECASE_AUDIO_RECORD_LOW_LATENCY:
475 dir = 1;
476 case USECASE_AUDIO_PLAYBACK_ULL:
477 break;
478 default:
479 return false;
480 }
481
482 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
483 PCM_PLAYBACK : PCM_CAPTURE);
484 if (adev->adm_is_noirq_avail)
485 return adev->adm_is_noirq_avail(adev->adm_data,
486 adev->snd_card, dev_id, dir);
487 return false;
488}
489
490static void register_out_stream(struct stream_out *out)
491{
492 struct audio_device *adev = out->dev;
493 if (is_offload_usecase(out->usecase) ||
494 !adev->adm_register_output_stream)
495 return;
496
497 // register stream first for backward compatibility
498 adev->adm_register_output_stream(adev->adm_data,
499 out->handle,
500 out->flags);
501
502 if (!adev->adm_set_config)
503 return;
504
505 if (out->realtime)
506 adev->adm_set_config(adev->adm_data,
507 out->handle,
508 out->pcm, &out->config);
509}
510
511static void register_in_stream(struct stream_in *in)
512{
513 struct audio_device *adev = in->dev;
514 if (!adev->adm_register_input_stream)
515 return;
516
517 adev->adm_register_input_stream(adev->adm_data,
518 in->capture_handle,
519 in->flags);
520
521 if (!adev->adm_set_config)
522 return;
523
524 if (in->realtime)
525 adev->adm_set_config(adev->adm_data,
526 in->capture_handle,
527 in->pcm,
528 &in->config);
529}
530
531static void request_out_focus(struct stream_out *out, long ns)
532{
533 struct audio_device *adev = out->dev;
534
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700535 if (adev->adm_request_focus_v2)
536 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
537 else if (adev->adm_request_focus)
538 adev->adm_request_focus(adev->adm_data, out->handle);
539}
540
541static void request_in_focus(struct stream_in *in, long ns)
542{
543 struct audio_device *adev = in->dev;
544
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700545 if (adev->adm_request_focus_v2)
546 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
547 else if (adev->adm_request_focus)
548 adev->adm_request_focus(adev->adm_data, in->capture_handle);
549}
550
551static void release_out_focus(struct stream_out *out)
552{
553 struct audio_device *adev = out->dev;
554
555 if (adev->adm_abandon_focus)
556 adev->adm_abandon_focus(adev->adm_data, out->handle);
557}
558
559static void release_in_focus(struct stream_in *in)
560{
561 struct audio_device *adev = in->dev;
562 if (adev->adm_abandon_focus)
563 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
564}
565
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530566static int parse_snd_card_status(struct str_parms *parms, int *card,
567 card_status_t *status)
568{
569 char value[32]={0};
570 char state[32]={0};
571
572 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
573 if (ret < 0)
574 return -1;
575
576 // sscanf should be okay as value is of max length 32.
577 // same as sizeof state.
578 if (sscanf(value, "%d,%s", card, state) < 2)
579 return -1;
580
581 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
582 CARD_STATUS_OFFLINE;
583 return 0;
584}
585
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700586static inline void adjust_frames_for_device_delay(struct stream_out *out,
587 uint32_t *dsp_frames) {
588 // Adjustment accounts for A2dp encoder latency with offload usecases
589 // Note: Encoder latency is returned in ms.
590 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
591 unsigned long offset =
592 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
593 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
594 }
595}
596
vivek mehtaa76401a2015-04-24 14:12:15 -0700597__attribute__ ((visibility ("default")))
598bool audio_hw_send_gain_dep_calibration(int level) {
599 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700600 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700601
602 pthread_mutex_lock(&adev_init_lock);
603
604 if (adev != NULL && adev->platform != NULL) {
605 pthread_mutex_lock(&adev->lock);
606 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700607
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530608 // cache level info for any of the use case which
609 // was not started.
610 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700611
vivek mehtaa76401a2015-04-24 14:12:15 -0700612 pthread_mutex_unlock(&adev->lock);
613 } else {
614 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
615 }
616
617 pthread_mutex_unlock(&adev_init_lock);
618
619 return ret_val;
620}
621
Ashish Jain5106d362016-05-11 19:23:33 +0530622static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
623{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800624 bool gapless_enabled = false;
625 const char *mixer_ctl_name = "Compress Gapless Playback";
626 struct mixer_ctl *ctl;
627
628 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700629 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530630
631 /*Disable gapless if its AV playback*/
632 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800633
634 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
635 if (!ctl) {
636 ALOGE("%s: Could not get ctl for mixer cmd - %s",
637 __func__, mixer_ctl_name);
638 return -EINVAL;
639 }
640
641 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
642 ALOGE("%s: Could not set gapless mode %d",
643 __func__, gapless_enabled);
644 return -EINVAL;
645 }
646 return 0;
647}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700648
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700649__attribute__ ((visibility ("default")))
650int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
651 int table_size) {
652 int ret_val = 0;
653 ALOGV("%s: enter ... ", __func__);
654
655 pthread_mutex_lock(&adev_init_lock);
656 if (adev == NULL) {
657 ALOGW("%s: adev is NULL .... ", __func__);
658 goto done;
659 }
660
661 pthread_mutex_lock(&adev->lock);
662 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
663 pthread_mutex_unlock(&adev->lock);
664done:
665 pthread_mutex_unlock(&adev_init_lock);
666 ALOGV("%s: exit ... ", __func__);
667 return ret_val;
668}
669
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700670static bool is_supported_format(audio_format_t format)
671{
Eric Laurent86e17132013-09-12 17:49:30 -0700672 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530673 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530674 format == AUDIO_FORMAT_AAC_LC ||
675 format == AUDIO_FORMAT_AAC_HE_V1 ||
676 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530677 format == AUDIO_FORMAT_AAC_ADTS_LC ||
678 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
679 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530680 format == AUDIO_FORMAT_AAC_LATM_LC ||
681 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
682 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530683 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
684 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530685 format == AUDIO_FORMAT_PCM_FLOAT ||
686 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700687 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530688 format == AUDIO_FORMAT_AC3 ||
689 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700690 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530691 format == AUDIO_FORMAT_DTS ||
692 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800693 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530694 format == AUDIO_FORMAT_ALAC ||
695 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530696 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530697 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800698 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530699 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700700 format == AUDIO_FORMAT_APTX ||
701 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800702 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700703
704 return false;
705}
706
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700707static inline bool is_mmap_usecase(audio_usecase_t uc_id)
708{
709 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
710 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
711}
712
Avinash Vaish71a8b972014-07-24 15:36:33 +0530713static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
714 struct audio_usecase *uc_info)
715{
716 struct listnode *node;
717 struct audio_usecase *usecase;
718
719 if (uc_info == NULL)
720 return -EINVAL;
721
722 /* Re-route all voice usecases on the shared backend other than the
723 specified usecase to new snd devices */
724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800726 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530727 enable_audio_route(adev, usecase);
728 }
729 return 0;
730}
731
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530732static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530733{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530734 ALOGV("%s", __func__);
735 audio_route_apply_and_update_path(adev->audio_route,
736 "asrc-mode");
737 adev->asrc_mode_enabled = true;
738}
739
740static void disable_asrc_mode(struct audio_device *adev)
741{
742 ALOGV("%s", __func__);
743 audio_route_reset_and_update_path(adev->audio_route,
744 "asrc-mode");
745 adev->asrc_mode_enabled = false;
746}
747
748/*
749 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
750 * 44.1 or Native DSD backends are enabled for any of current use case.
751 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
752 * - Disable current mix path use case(Headphone backend) and re-enable it with
753 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
754 * e.g. Naitve DSD or Headphone 44.1 -> + 48
755 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530756static void check_and_set_asrc_mode(struct audio_device *adev,
757 struct audio_usecase *uc_info,
758 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530759{
760 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530761 int i, num_new_devices = 0;
762 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
763 /*
764 *Split snd device for new combo use case
765 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
766 */
767 if (platform_split_snd_device(adev->platform,
768 snd_device,
769 &num_new_devices,
770 split_new_snd_devices) == 0) {
771 for (i = 0; i < num_new_devices; i++)
772 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
773 } else {
774 int new_backend_idx = platform_get_backend_index(snd_device);
775 if (((new_backend_idx == HEADPHONE_BACKEND) ||
776 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
777 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
778 !adev->asrc_mode_enabled) {
779 struct listnode *node = NULL;
780 struct audio_usecase *uc = NULL;
781 struct stream_out *curr_out = NULL;
782 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
783 int i, num_devices, ret = 0;
784 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530785
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530786 list_for_each(node, &adev->usecase_list) {
787 uc = node_to_item(node, struct audio_usecase, list);
788 curr_out = (struct stream_out*) uc->stream.out;
789 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
790 /*
791 *Split snd device for existing combo use case
792 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
793 */
794 ret = platform_split_snd_device(adev->platform,
795 uc->out_snd_device,
796 &num_devices,
797 split_snd_devices);
798 if (ret < 0 || num_devices == 0) {
799 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
800 split_snd_devices[0] = uc->out_snd_device;
801 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800802 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530803 for (i = 0; i < num_devices; i++) {
804 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
805 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
806 if((new_backend_idx == HEADPHONE_BACKEND) &&
807 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
808 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
809 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
810 __func__);
811 enable_asrc_mode(adev);
812 break;
813 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
814 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
815 (usecase_backend_idx == HEADPHONE_BACKEND)) {
816 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
817 __func__);
818 disable_audio_route(adev, uc);
819 disable_snd_device(adev, uc->out_snd_device);
820 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
821 if (new_backend_idx == DSD_NATIVE_BACKEND)
822 audio_route_apply_and_update_path(adev->audio_route,
823 "hph-true-highquality-mode");
824 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
825 (curr_out->bit_width >= 24))
826 audio_route_apply_and_update_path(adev->audio_route,
827 "hph-highquality-mode");
828 enable_asrc_mode(adev);
829 enable_snd_device(adev, uc->out_snd_device);
830 enable_audio_route(adev, uc);
831 break;
832 }
833 }
834 // reset split devices count
835 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800836 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530837 if (adev->asrc_mode_enabled)
838 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530839 }
840 }
841 }
842}
843
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700844#ifdef DYNAMIC_ECNS_ENABLED
845static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
846 struct audio_effect_config effect_config,
847 unsigned int param_value)
848{
849 char mixer_ctl_name[] = "Audio Effect";
850 struct mixer_ctl *ctl;
851 long set_values[6];
852 struct stream_in *in = adev->active_input;
853
854 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
855 if (!ctl) {
856 ALOGE("%s: Could not get mixer ctl - %s",
857 __func__, mixer_ctl_name);
858 return -EINVAL;
859 }
860
861 set_values[0] = 1; //0:Rx 1:Tx
862 set_values[1] = in->app_type_cfg.app_type;
863 set_values[2] = (long)effect_config.module_id;
864 set_values[3] = (long)effect_config.instance_id;
865 set_values[4] = (long)effect_config.param_id;
866 set_values[5] = param_value;
867
868 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
869
870 return 0;
871
872}
873
874static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
875 int effect_type, unsigned int *param_value)
876{
877 int ret = 0;
878 struct audio_effect_config other_effect_config;
879 struct audio_usecase *usecase = NULL;
880 struct stream_in *in = adev->active_input;
881
882 usecase = get_usecase_from_list(adev, in->usecase);
883 if (!usecase)
884 return -EINVAL;
885
886 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
887 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
888 if (ret < 0) {
889 ALOGE("%s Failed to get effect params %d", __func__, ret);
890 return ret;
891 }
892
893 if (module_id == other_effect_config.module_id) {
894 //Same module id for AEC/NS. Values need to be combined
895 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
896 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
897 *param_value |= other_effect_config.param_value;
898 }
899 }
900
901 return ret;
902}
903
904static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
905{
906 struct audio_effect_config effect_config;
907 struct audio_usecase *usecase = NULL;
908 int ret = 0;
909 unsigned int param_value = 0;
910 struct stream_in *in = adev->active_input;
911
912 if (!in) {
913 ALOGE("%s: Invalid input stream", __func__);
914 return -EINVAL;
915 }
916
917 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
918
919 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800920 if (usecase == NULL) {
921 ALOGE("%s: Could not find the usecase (%d) in the list",
922 __func__, in->usecase);
923 return -EINVAL;
924 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700925
926 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
927 if (ret < 0) {
928 ALOGE("%s Failed to get module id %d", __func__, ret);
929 return ret;
930 }
931 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
932 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
933
934 if(enable)
935 param_value = effect_config.param_value;
936
937 /*Special handling for AEC & NS effects Param values need to be
938 updated if module ids are same*/
939
940 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
941 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
942 if (ret < 0)
943 return ret;
944 }
945
946 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
947
948 return ret;
949}
950
951static void check_and_enable_effect(struct audio_device *adev)
952{
953
954 if (adev->active_input->enable_aec) {
955 enable_disable_effect(adev, EFFECT_AEC, true);
956 }
957
958 if (adev->active_input->enable_ns &&
959 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
960 enable_disable_effect(adev, EFFECT_NS, true);
961 }
962}
963#else
964#define enable_disable_effect(x, y, z) ENOSYS
965#define check_and_enable_effect(x) ENOSYS
966#endif
967
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700968int pcm_ioctl(struct pcm *pcm, int request, ...)
969{
970 va_list ap;
971 void * arg;
972 int pcm_fd = *(int*)pcm;
973
974 va_start(ap, request);
975 arg = va_arg(ap, void *);
976 va_end(ap);
977
978 return ioctl(pcm_fd, request, arg);
979}
980
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700981int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700982 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700984 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700985 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530986 struct stream_out *out = NULL;
Soumya Managolie7651c42018-06-28 16:04:57 +0530987 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800988
989 if (usecase == NULL)
990 return -EINVAL;
991
992 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
993
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800994 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700995 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800996 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700997 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800998
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800999#ifdef DS1_DOLBY_DAP_ENABLED
1000 audio_extn_dolby_set_dmid(adev);
1001 audio_extn_dolby_set_endpoint(adev);
1002#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001003 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001004 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301005 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001006 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301007 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301008 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1009 out = usecase->stream.out;
1010 if (out && out->compr)
1011 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1012 }
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301013 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301014
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001015 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001016 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001017 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managolie7651c42018-06-28 16:04:57 +05301018 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1019 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1020 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1021 if (parms) {
1022 audio_extn_fm_set_parameters(adev, parms);
1023 str_parms_destroy(parms);
1024 }
1025 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 ALOGV("%s: exit", __func__);
1027 return 0;
1028}
1029
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001030int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001031 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001034 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001035
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301036 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001037 return -EINVAL;
1038
1039 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 if (usecase->type == PCM_CAPTURE)
1041 snd_device = usecase->in_snd_device;
1042 else
1043 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001044 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001045 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001046 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001047 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001048 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301049 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar2a7f75b2018-12-10 22:26:53 +05301050 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiange2938532019-06-03 14:29:30 +08001051 if ((usecase->type == PCM_PLAYBACK) &&
1052 (usecase->stream.out != NULL))
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05301053 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 ALOGV("%s: exit", __func__);
1055 return 0;
1056}
1057
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001058int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301061 int i, num_devices = 0;
1062 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001063 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1064
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001065 if (snd_device < SND_DEVICE_MIN ||
1066 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001067 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001068 return -EINVAL;
1069 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001071 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001072 ALOGE("%s: Invalid sound device returned", __func__);
1073 return -EINVAL;
1074 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001075
1076 adev->snd_dev_ref_cnt[snd_device]++;
1077
1078 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1079 (platform_split_snd_device(adev->platform,
1080 snd_device,
1081 &num_devices,
1082 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001083 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001084 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 return 0;
1086 }
1087
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001088 if (audio_extn_spkr_prot_is_enabled())
1089 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001090
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001091 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1092 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001093 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1094 goto err;
1095 }
1096 audio_extn_dev_arbi_acquire(snd_device);
1097 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001098 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001099 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001100 goto err;
1101 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001102 } else if (platform_split_snd_device(adev->platform,
1103 snd_device,
1104 &num_devices,
1105 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301106 for (i = 0; i < num_devices; i++) {
1107 enable_snd_device(adev, new_snd_devices[i]);
1108 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001109 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001110 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301111
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301112
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001113 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1114 (audio_extn_a2dp_start_playback() < 0)) {
1115 ALOGE(" fail to configure A2dp control path ");
1116 goto err;
1117 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301118
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001119 /* due to the possibility of calibration overwrite between listen
1120 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001121 audio_extn_sound_trigger_update_device_status(snd_device,
1122 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301123 audio_extn_listen_update_device_status(snd_device,
1124 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001125 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001126 audio_extn_sound_trigger_update_device_status(snd_device,
1127 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301128 audio_extn_listen_update_device_status(snd_device,
1129 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001130 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001131 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001132 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001133 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301134
1135 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1136 !adev->native_playback_enabled &&
1137 audio_is_true_native_stream_active(adev)) {
1138 ALOGD("%s: %d: napb: enabling native mode in hardware",
1139 __func__, __LINE__);
1140 audio_route_apply_and_update_path(adev->audio_route,
1141 "true-native-mode");
1142 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301143 }
Dhanalakshmi Siddani0f1dfd52019-01-09 12:38:13 +05301144 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1145 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001146 (audio_extn_ffv_get_stream() == adev->active_input)) {
1147 ALOGD("%s: init ec ref loopback", __func__);
1148 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151 return 0;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001152err:
1153 adev->snd_dev_ref_cnt[snd_device]--;
1154 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155}
1156
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001157int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001158 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301160 int i, num_devices = 0;
1161 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001162 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1163
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001164 if (snd_device < SND_DEVICE_MIN ||
1165 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001166 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001167 return -EINVAL;
1168 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001169
1170 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1171 ALOGE("%s: Invalid sound device returned", __func__);
1172 return -EINVAL;
1173 }
1174
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1176 ALOGE("%s: device ref cnt is already 0", __func__);
1177 return -EINVAL;
1178 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001179
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001183 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301184
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001185 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1186 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001187 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001188
1189 // when speaker device is disabled, reset swap.
1190 // will be renabled on usecase start
1191 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001192 } else if (platform_split_snd_device(adev->platform,
1193 snd_device,
1194 &num_devices,
1195 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301196 for (i = 0; i < num_devices; i++) {
1197 disable_snd_device(adev, new_snd_devices[i]);
1198 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001199 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001200 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001201 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001202
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301203 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1204 audio_extn_a2dp_stop_playback();
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001205 else if (snd_device == SND_DEVICE_OUT_HDMI ||
1206 snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301207 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301208 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001209 adev->native_playback_enabled) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301210 ALOGD("%s: %d: napb: disabling native mode in hardware",
1211 __func__, __LINE__);
1212 audio_route_reset_and_update_path(adev->audio_route,
1213 "true-native-mode");
1214 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301215 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001216 adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301217 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301218 disable_asrc_mode(adev);
1219 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001220 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1221 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
1222 (audio_extn_ffv_get_stream() == adev->active_input)) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001223 ALOGD("%s: deinit ec ref loopback", __func__);
1224 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1225 }
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001226
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001227 audio_extn_utils_release_snd_device(snd_device);
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001228 } else {
1229 if (platform_split_snd_device(adev->platform,
1230 snd_device,
1231 &num_devices,
1232 new_snd_devices) == 0) {
1233 for (i = 0; i < num_devices; i++) {
1234 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1235 }
1236 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239 return 0;
1240}
1241
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001242/*
1243 legend:
1244 uc - existing usecase
1245 new_uc - new usecase
1246 d1, d11, d2 - SND_DEVICE enums
1247 a1, a2 - corresponding ANDROID device enums
1248 B1, B2 - backend strings
1249
1250case 1
1251 uc->dev d1 (a1) B1
1252 new_uc->dev d1 (a1), d2 (a2) B1, B2
1253
1254 resolution: disable and enable uc->dev on d1
1255
1256case 2
1257 uc->dev d1 (a1) B1
1258 new_uc->dev d11 (a1) B1
1259
1260 resolution: need to switch uc since d1 and d11 are related
1261 (e.g. speaker and voice-speaker)
1262 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1263
1264case 3
1265 uc->dev d1 (a1) B1
1266 new_uc->dev d2 (a2) B2
1267
1268 resolution: no need to switch uc
1269
1270case 4
1271 uc->dev d1 (a1) B1
1272 new_uc->dev d2 (a2) B1
1273
1274 resolution: disable enable uc-dev on d2 since backends match
1275 we cannot enable two streams on two different devices if they
1276 share the same backend. e.g. if offload is on speaker device using
1277 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1278 using the same backend, offload must also be switched to voice-handset.
1279
1280case 5
1281 uc->dev d1 (a1) B1
1282 new_uc->dev d1 (a1), d2 (a2) B1
1283
1284 resolution: disable enable uc-dev on d2 since backends match
1285 we cannot enable two streams on two different devices if they
1286 share the same backend.
1287
1288case 6
1289 uc->dev d1 (a1) B1
1290 new_uc->dev d2 (a1) B2
1291
1292 resolution: no need to switch
1293
1294case 7
1295 uc->dev d1 (a1), d2 (a2) B1, B2
1296 new_uc->dev d1 (a1) B1
1297
1298 resolution: no need to switch
1299
Zhou Song4ba65882018-07-09 14:48:07 +08001300case 8
1301 uc->dev d1 (a1) B1
1302 new_uc->dev d11 (a1), d2 (a2) B1, B2
1303 resolution: compared to case 1, for this case, d1 and d11 are related
1304 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001305*/
1306static snd_device_t derive_playback_snd_device(void * platform,
1307 struct audio_usecase *uc,
1308 struct audio_usecase *new_uc,
1309 snd_device_t new_snd_device)
1310{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301311 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001312
1313 snd_device_t d1 = uc->out_snd_device;
1314 snd_device_t d2 = new_snd_device;
1315
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301316 switch (uc->type) {
1317 case TRANSCODE_LOOPBACK :
1318 a1 = uc->stream.inout->out_config.devices;
1319 a2 = new_uc->stream.inout->out_config.devices;
1320 break;
1321 default :
1322 a1 = uc->stream.out->devices;
1323 a2 = new_uc->stream.out->devices;
1324 break;
1325 }
1326
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001327 // Treat as a special case when a1 and a2 are not disjoint
1328 if ((a1 != a2) && (a1 & a2)) {
1329 snd_device_t d3[2];
1330 int num_devices = 0;
1331 int ret = platform_split_snd_device(platform,
1332 popcount(a1) > 1 ? d1 : d2,
1333 &num_devices,
1334 d3);
1335 if (ret < 0) {
1336 if (ret != -ENOSYS) {
1337 ALOGW("%s failed to split snd_device %d",
1338 __func__,
1339 popcount(a1) > 1 ? d1 : d2);
1340 }
1341 goto end;
1342 }
1343
1344 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1345 // But if it does happen, we need to give priority to d2 if
1346 // the combo devices active on the existing usecase share a backend.
1347 // This is because we cannot have a usecase active on a combo device
1348 // and a new usecase requests one device in this combo pair.
1349 if (platform_check_backends_match(d3[0], d3[1])) {
1350 return d2; // case 5
1351 } else {
Zhou Song671be042018-08-27 15:33:52 +08001352 // check if d1 is related to any of d3's OR
1353 // old uc is combo device but new_uc is one of the combo device
1354 if (d1 == d3[0] || d1 == d3[1] || popcount(a1) > 1)
1355 return d1; // case 1, 7
Zhou Song4ba65882018-07-09 14:48:07 +08001356 else
1357 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001358 }
1359 } else {
1360 if (platform_check_backends_match(d1, d2)) {
1361 return d2; // case 2, 4
1362 } else {
1363 return d1; // case 6, 3
1364 }
1365 }
1366
1367end:
1368 return d2; // return whatever was calculated before.
1369}
1370
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001371static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301372 struct audio_usecase *uc_info,
1373 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374{
1375 struct listnode *node;
1376 struct audio_usecase *usecase;
1377 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301378 snd_device_t uc_derive_snd_device;
1379 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001380 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1381 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001382 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301383 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001384 /*
1385 * This function is to make sure that all the usecases that are active on
1386 * the hardware codec backend are always routed to any one device that is
1387 * handled by the hardware codec.
1388 * For example, if low-latency and deep-buffer usecases are currently active
1389 * on speaker and out_set_parameters(headset) is received on low-latency
1390 * output, then we have to make sure deep-buffer is also switched to headset,
1391 * because of the limitation that both the devices cannot be enabled
1392 * at the same time as they share the same backend.
1393 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001394 /*
1395 * This call is to check if we need to force routing for a particular stream
1396 * If there is a backend configuration change for the device when a
1397 * new stream starts, then ADM needs to be closed and re-opened with the new
1398 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001399 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001400 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001401 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1402 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301403 /* For a2dp device reconfigure all active sessions
1404 * with new AFE encoder format based on a2dp state
1405 */
1406 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1407 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1408 audio_extn_a2dp_is_force_device_switch()) {
1409 force_routing = true;
1410 force_restart_session = true;
1411 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301412 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001415 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001416 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1418 switch_device[i] = false;
1419
1420 list_for_each(node, &adev->usecase_list) {
1421 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001422
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301423 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1424 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301425 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301426 platform_get_snd_device_name(usecase->out_snd_device),
1427 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301428 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1429 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1430 usecase, uc_info, snd_device);
1431 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1432 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1433 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1434 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001435 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301436 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1437 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1438 ((force_restart_session) ||
1439 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301440 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1441 __func__, use_case_table[usecase->id],
1442 platform_get_snd_device_name(usecase->out_snd_device));
1443 disable_audio_route(adev, usecase);
1444 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301445 /* Enable existing usecase on derived playback device */
1446 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301447 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301448 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449 }
1450 }
1451
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301452 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1453 num_uc_to_switch);
1454
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001455 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001456 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301458 /* Make sure the previous devices to be disabled first and then enable the
1459 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001460 list_for_each(node, &adev->usecase_list) {
1461 usecase = node_to_item(node, struct audio_usecase, list);
1462 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001463 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001464 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001465 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1466 &num_devices, split_snd_devices) == 0) {
1467 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
Weiyin Jiangd7ba5d32019-03-28 18:33:37 +08001468 for (i = 0; i < num_devices; i++) {
1469 /* Disable devices that do not match with derived sound device */
1470 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1471 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001472 }
1473 } else {
1474 disable_snd_device(adev, usecase->out_snd_device);
1475 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 }
1477 }
1478
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001479 list_for_each(node, &adev->usecase_list) {
1480 usecase = node_to_item(node, struct audio_usecase, list);
1481 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001482 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1483 &num_devices, split_snd_devices) == 0) {
1484 /* Enable derived sound device only if it does not match with
1485 one of the split sound devices. This is because the matching
1486 sound device was not disabled */
1487 bool should_enable = true;
1488 for (i = 0; i < num_devices; i++) {
1489 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1490 should_enable = false;
1491 break;
1492 }
1493 }
1494 if (should_enable)
1495 enable_snd_device(adev, derive_snd_device[usecase->id]);
1496 } else {
1497 enable_snd_device(adev, derive_snd_device[usecase->id]);
1498 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001499 }
1500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 /* Re-route all the usecases on the shared backend other than the
1503 specified usecase to new snd devices */
1504 list_for_each(node, &adev->usecase_list) {
1505 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301506 /* Update the out_snd_device only before enabling the audio route */
1507 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301508 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301509 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301510 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301511 use_case_table[usecase->id],
1512 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001513 /* Update voc calibration before enabling VoIP route */
1514 if (usecase->type == VOIP_CALL)
1515 status = platform_switch_voice_call_device_post(adev->platform,
1516 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001517 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301518 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001519 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1520 out_set_voip_volume(&usecase->stream.out->stream,
1521 usecase->stream.out->volume_l,
1522 usecase->stream.out->volume_r);
1523 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301524 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 }
1526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 }
1528}
1529
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301530static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001531 struct audio_usecase *uc_info,
1532 snd_device_t snd_device)
1533{
1534 struct listnode *node;
1535 struct audio_usecase *usecase;
1536 bool switch_device[AUDIO_USECASE_MAX];
1537 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301538 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001539 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001540
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301541 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1542 snd_device);
1543 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301544
1545 /*
1546 * Make sure out devices is checked against out codec backend device and
1547 * also in devices against in codec backend. Checking out device against in
1548 * codec backend or vice versa causes issues.
1549 */
1550 if (uc_info->type == PCM_CAPTURE)
1551 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001552 /*
1553 * This function is to make sure that all the active capture usecases
1554 * are always routed to the same input sound device.
1555 * For example, if audio-record and voice-call usecases are currently
1556 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1557 * is received for voice call then we have to make sure that audio-record
1558 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1559 * because of the limitation that two devices cannot be enabled
1560 * at the same time if they share the same backend.
1561 */
1562 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1563 switch_device[i] = false;
1564
1565 list_for_each(node, &adev->usecase_list) {
1566 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301567 /*
1568 * TODO: Enhance below condition to handle BT sco/USB multi recording
1569 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001570 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001571 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301572 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301573 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301574 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301575 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001576 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001577 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1578 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001579 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001580 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001581 switch_device[usecase->id] = true;
1582 num_uc_to_switch++;
1583 }
1584 }
1585
1586 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001587 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001588
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301589 /* Make sure the previous devices to be disabled first and then enable the
1590 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001591 list_for_each(node, &adev->usecase_list) {
1592 usecase = node_to_item(node, struct audio_usecase, list);
1593 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001594 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001595 }
1596 }
1597
1598 list_for_each(node, &adev->usecase_list) {
1599 usecase = node_to_item(node, struct audio_usecase, list);
1600 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001601 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001602 }
1603 }
1604
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001605 /* Re-route all the usecases on the shared backend other than the
1606 specified usecase to new snd devices */
1607 list_for_each(node, &adev->usecase_list) {
1608 usecase = node_to_item(node, struct audio_usecase, list);
1609 /* Update the in_snd_device only before enabling the audio route */
1610 if (switch_device[usecase->id] ) {
1611 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001612 if (usecase->type != VOICE_CALL) {
1613 /* Update voc calibration before enabling VoIP route */
1614 if (usecase->type == VOIP_CALL)
1615 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001616 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001617 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301618 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001619 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001620 }
1621 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001622 }
1623}
1624
Mingming Yin3a941d42016-02-17 18:08:05 -08001625static void reset_hdmi_sink_caps(struct stream_out *out) {
1626 int i = 0;
1627
1628 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1629 out->supported_channel_masks[i] = 0;
1630 }
1631 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1632 out->supported_formats[i] = 0;
1633 }
1634 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1635 out->supported_sample_rates[i] = 0;
1636 }
1637}
1638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001640static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641{
Mingming Yin3a941d42016-02-17 18:08:05 -08001642 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001643 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Mingming Yin3a941d42016-02-17 18:08:05 -08001645 reset_hdmi_sink_caps(out);
1646
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001647 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001648 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001649 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001650 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001651 }
1652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001655 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001656 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001657 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1658 case 6:
1659 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1660 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1661 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1662 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1663 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1664 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 break;
1666 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001667 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001668 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 break;
1670 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001671
1672 // check channel format caps
1673 i = 0;
1674 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1675 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1676 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1677 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1678 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1679 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1680 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1681 }
1682
Ben Romberger1aaaf862017-04-06 17:49:46 -07001683 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1684 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1685 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1686 }
1687
Mingming Yin3a941d42016-02-17 18:08:05 -08001688 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1689 ALOGV(":%s HDMI supports DTS format", __func__);
1690 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1691 }
1692
1693 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1694 ALOGV(":%s HDMI supports DTS HD format", __func__);
1695 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1696 }
1697
Naresh Tanniru928f0862017-04-07 16:44:23 -07001698 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1699 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1700 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1701 }
1702
Mingming Yin3a941d42016-02-17 18:08:05 -08001703
1704 // check sample rate caps
1705 i = 0;
1706 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1707 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1708 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1709 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1710 }
1711 }
1712
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001713 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714}
1715
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001716static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1717 uint32_t *supported_sample_rates __unused,
1718 uint32_t max_rates __unused)
1719{
1720 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1721 supported_sample_rates,
1722 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301723 ssize_t i = 0;
1724
1725 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001726 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1727 supported_sample_rates[i]);
1728 }
1729 return count;
1730}
1731
1732static inline int read_usb_sup_channel_masks(bool is_playback,
1733 audio_channel_mask_t *supported_channel_masks,
1734 uint32_t max_masks)
1735{
1736 int channels = audio_extn_usb_get_max_channels(is_playback);
1737 int channel_count;
1738 uint32_t num_masks = 0;
1739 if (channels > MAX_HIFI_CHANNEL_COUNT)
1740 channels = MAX_HIFI_CHANNEL_COUNT;
1741
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301742 channel_count = DEFAULT_CHANNEL_COUNT;
1743
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001744 if (is_playback) {
1745 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001746 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301747 // above 2 but we want indexed masks here.
1748 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001749 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001750 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1751 // indexed mask
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301752 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001753 }
Lakshman Chaluvaraju90ddcaa2018-11-21 10:24:37 +05301754
1755 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1756 (num_masks < max_masks)); channel_count--) {
1757 supported_channel_masks[num_masks++] =
1758 audio_channel_mask_for_index_assignment_from_count(channel_count);
1759 }
1760
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001761 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1762 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1763 return num_masks;
1764}
1765
1766static inline int read_usb_sup_formats(bool is_playback __unused,
1767 audio_format_t *supported_formats,
1768 uint32_t max_formats __unused)
1769{
1770 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1771 switch (bitwidth) {
1772 case 24:
1773 // XXX : usb.c returns 24 for s24 and s24_le?
1774 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1775 break;
1776 case 32:
1777 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1778 break;
1779 case 16:
1780 default :
1781 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1782 break;
1783 }
1784 ALOGV("%s: %s supported format %d", __func__,
1785 is_playback ? "P" : "C", bitwidth);
1786 return 1;
1787}
1788
1789static inline int read_usb_sup_params_and_compare(bool is_playback,
1790 audio_format_t *format,
1791 audio_format_t *supported_formats,
1792 uint32_t max_formats,
1793 audio_channel_mask_t *mask,
1794 audio_channel_mask_t *supported_channel_masks,
1795 uint32_t max_masks,
1796 uint32_t *rate,
1797 uint32_t *supported_sample_rates,
1798 uint32_t max_rates) {
1799 int ret = 0;
1800 int num_formats;
1801 int num_masks;
1802 int num_rates;
1803 int i;
1804
1805 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1806 max_formats);
1807 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1808 max_masks);
1809
1810 num_rates = read_usb_sup_sample_rates(is_playback,
1811 supported_sample_rates, max_rates);
1812
1813#define LUT(table, len, what, dflt) \
1814 for (i=0; i<len && (table[i] != what); i++); \
1815 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1816
1817 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1818 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1819 LUT(supported_sample_rates, num_rates, *rate, 0);
1820
1821#undef LUT
1822 return ret < 0 ? -EINVAL : 0; // HACK TBD
1823}
1824
Alexy Josephb1379942016-01-29 15:49:38 -08001825audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001826 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001827{
1828 struct audio_usecase *usecase;
1829 struct listnode *node;
1830
1831 list_for_each(node, &adev->usecase_list) {
1832 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001833 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001834 ALOGV("%s: usecase id %d", __func__, usecase->id);
1835 return usecase->id;
1836 }
1837 }
1838 return USECASE_INVALID;
1839}
1840
Alexy Josephb1379942016-01-29 15:49:38 -08001841struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001842 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001843{
1844 struct audio_usecase *usecase;
1845 struct listnode *node;
1846
1847 list_for_each(node, &adev->usecase_list) {
1848 usecase = node_to_item(node, struct audio_usecase, list);
1849 if (usecase->id == uc_id)
1850 return usecase;
1851 }
1852 return NULL;
1853}
1854
Dhananjay Kumard4833242016-10-06 22:09:12 +05301855struct stream_in *get_next_active_input(const struct audio_device *adev)
1856{
1857 struct audio_usecase *usecase;
1858 struct listnode *node;
1859
1860 list_for_each_reverse(node, &adev->usecase_list) {
1861 usecase = node_to_item(node, struct audio_usecase, list);
1862 if (usecase->type == PCM_CAPTURE)
1863 return usecase->stream.in;
1864 }
1865 return NULL;
1866}
1867
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301868/*
1869 * is a true native playback active
1870 */
1871bool audio_is_true_native_stream_active(struct audio_device *adev)
1872{
1873 bool active = false;
1874 int i = 0;
1875 struct listnode *node;
1876
1877 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1878 ALOGV("%s:napb: not in true mode or non hdphones device",
1879 __func__);
1880 active = false;
1881 goto exit;
1882 }
1883
1884 list_for_each(node, &adev->usecase_list) {
1885 struct audio_usecase *uc;
1886 uc = node_to_item(node, struct audio_usecase, list);
1887 struct stream_out *curr_out =
1888 (struct stream_out*) uc->stream.out;
1889
1890 if (curr_out && PCM_PLAYBACK == uc->type) {
1891 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1892 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1893 uc->id, curr_out->sample_rate,
1894 curr_out->bit_width,
1895 platform_get_snd_device_name(uc->out_snd_device));
1896
1897 if (is_offload_usecase(uc->id) &&
1898 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1899 active = true;
1900 ALOGD("%s:napb:native stream detected", __func__);
1901 }
1902 }
1903 }
1904exit:
1905 return active;
1906}
1907
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001908uint32_t adev_get_dsp_bit_width_enforce_mode()
1909{
1910 if (adev == NULL) {
1911 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1912 return 0;
1913 }
1914 return adev->dsp_bit_width_enforce_mode;
1915}
1916
1917static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1918{
1919 char value[PROPERTY_VALUE_MAX];
1920 int trial;
1921 uint32_t dsp_bit_width_enforce_mode = 0;
1922
1923 if (!mixer) {
1924 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1925 __func__);
1926 return 0;
1927 }
1928
1929 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1930 value, NULL) > 0) {
1931 trial = atoi(value);
1932 switch (trial) {
1933 case 16:
1934 dsp_bit_width_enforce_mode = 16;
1935 break;
1936 case 24:
1937 dsp_bit_width_enforce_mode = 24;
1938 break;
1939 case 32:
1940 dsp_bit_width_enforce_mode = 32;
1941 break;
1942 default:
1943 dsp_bit_width_enforce_mode = 0;
1944 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1945 break;
1946 }
1947 }
1948
1949 return dsp_bit_width_enforce_mode;
1950}
1951
1952static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1953 uint32_t enforce_mode,
1954 bool enable)
1955{
1956 struct mixer_ctl *ctl = NULL;
1957 const char *mixer_ctl_name = "ASM Bit Width";
1958 uint32_t asm_bit_width_mode = 0;
1959
1960 if (enforce_mode == 0) {
1961 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1962 return;
1963 }
1964
1965 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1966 if (!ctl) {
1967 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1968 __func__, mixer_ctl_name);
1969 return;
1970 }
1971
1972 if (enable)
1973 asm_bit_width_mode = enforce_mode;
1974 else
1975 asm_bit_width_mode = 0;
1976
1977 ALOGV("%s DSP bit width feature status is %d width=%d",
1978 __func__, enable, asm_bit_width_mode);
1979 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1980 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1981 asm_bit_width_mode);
1982
1983 return;
1984}
1985
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301986/*
1987 * if native DSD playback active
1988 */
1989bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1990{
1991 bool active = false;
1992 struct listnode *node = NULL;
1993 struct audio_usecase *uc = NULL;
1994 struct stream_out *curr_out = NULL;
1995
1996 list_for_each(node, &adev->usecase_list) {
1997 uc = node_to_item(node, struct audio_usecase, list);
1998 curr_out = (struct stream_out*) uc->stream.out;
1999
2000 if (curr_out && PCM_PLAYBACK == uc->type &&
2001 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2002 active = true;
2003 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302004 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302005 }
2006 }
2007 return active;
2008}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302009
2010static bool force_device_switch(struct audio_usecase *usecase)
2011{
2012 bool ret = false;
2013 bool is_it_true_mode = false;
2014
Zhou Song30f2c3e2018-02-08 14:02:15 +08002015 if (usecase->type == PCM_CAPTURE ||
2016 usecase->type == TRANSCODE_LOOPBACK) {
2017 return false;
2018 }
2019
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002020 if(usecase->stream.out == NULL) {
2021 ALOGE("%s: stream.out is NULL", __func__);
2022 return false;
2023 }
2024
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302025 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002026 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2027 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2028 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302029 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2030 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2031 (!is_it_true_mode && adev->native_playback_enabled)){
2032 ret = true;
2033 ALOGD("napb: time to toggle native mode");
2034 }
2035 }
2036
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302037 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302038 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2039 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002040 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302041 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302042 ALOGD("Force a2dp device switch to update new encoder config");
2043 ret = true;
2044 }
2045
Manish Dewangan671a4202017-08-18 17:30:46 +05302046 if (usecase->stream.out->stream_config_changed) {
2047 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2048 return true;
2049 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302050 return ret;
2051}
2052
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302053bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2054{
2055 bool ret=false;
2056 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2057 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2058 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2059 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2060 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2061 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2062 ret = true;
2063
2064 return ret;
2065}
2066
2067bool is_a2dp_device(snd_device_t out_snd_device)
2068{
2069 bool ret=false;
2070 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2071 ret = true;
2072
2073 return ret;
2074}
2075
2076bool is_bt_soc_on(struct audio_device *adev)
2077{
2078 struct mixer_ctl *ctl;
2079 char *mixer_ctl_name = "BT SOC status";
2080 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2081 bool bt_soc_status = true;
2082 if (!ctl) {
2083 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2084 __func__, mixer_ctl_name);
2085 /*This is to ensure we dont break targets which dont have the kernel change*/
2086 return true;
2087 }
2088 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2089 ALOGD("BT SOC status: %d",bt_soc_status);
2090 return bt_soc_status;
2091}
2092
2093int out_standby_l(struct audio_stream *stream);
2094
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002095int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002097 snd_device_t out_snd_device = SND_DEVICE_NONE;
2098 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099 struct audio_usecase *usecase = NULL;
2100 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002101 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002102 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302103 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002104 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002105 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302107 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2108
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002109 usecase = get_usecase_from_list(adev, uc_id);
2110 if (usecase == NULL) {
2111 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2112 return -EINVAL;
2113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002115 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002116 (usecase->type == VOIP_CALL) ||
2117 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302118 if(usecase->stream.out == NULL) {
2119 ALOGE("%s: stream.out is NULL", __func__);
2120 return -EINVAL;
2121 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002122 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002123 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002124 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002125 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302126 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2127 if (usecase->stream.inout == NULL) {
2128 ALOGE("%s: stream.inout is NULL", __func__);
2129 return -EINVAL;
2130 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302131 stream_out.devices = usecase->stream.inout->out_config.devices;
2132 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2133 stream_out.format = usecase->stream.inout->out_config.format;
2134 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2135 out_snd_device = platform_get_output_snd_device(adev->platform,
2136 &stream_out);
2137 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302138 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002139 } else {
2140 /*
2141 * If the voice call is active, use the sound devices of voice call usecase
2142 * so that it would not result any device switch. All the usecases will
2143 * be switched to new device when select_devices() is called for voice call
2144 * usecase. This is to avoid switching devices for voice call when
2145 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002146 * choose voice call device only if the use case device is
2147 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002148 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002149 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002150 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002151 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002152 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2153 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302154 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2155 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002156 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002157 in_snd_device = vc_usecase->in_snd_device;
2158 out_snd_device = vc_usecase->out_snd_device;
2159 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002160 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002161 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002162 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002163 if ((voip_usecase != NULL) &&
2164 (usecase->type == PCM_PLAYBACK) &&
2165 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002166 out_snd_device_backend_match = platform_check_backends_match(
2167 voip_usecase->out_snd_device,
2168 platform_get_output_snd_device(
2169 adev->platform,
2170 usecase->stream.out));
2171 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002172 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002173 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2174 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002175 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002176 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002177 in_snd_device = voip_usecase->in_snd_device;
2178 out_snd_device = voip_usecase->out_snd_device;
2179 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002180 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002181 hfp_ucid = audio_extn_hfp_get_usecase();
2182 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002183 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002184 in_snd_device = hfp_usecase->in_snd_device;
2185 out_snd_device = hfp_usecase->out_snd_device;
2186 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002187 }
2188 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302189 if (usecase->stream.out == NULL) {
2190 ALOGE("%s: stream.out is NULL", __func__);
2191 return -EINVAL;
2192 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002193 usecase->devices = usecase->stream.out->devices;
2194 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002195 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002196 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002197 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002198 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002199 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002200 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2201
2202 if ((usecase->stream.out != NULL &&
2203 voip_usecase != NULL &&
2204 usecase->stream.out->usecase == voip_usecase->id) &&
2205 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002206 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002207 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002208 select_devices(adev, adev->active_input->usecase);
2209 }
2210 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002211 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302212 if (usecase->stream.in == NULL) {
2213 ALOGE("%s: stream.in is NULL", __func__);
2214 return -EINVAL;
2215 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002216 usecase->devices = usecase->stream.in->device;
2217 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002218 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002219 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002220 if (adev->active_input &&
2221 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302222 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002223 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2224 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2225 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2226 out_device = voip_usecase->stream.out->devices;
2227 else if (adev->primary_output && !adev->primary_output->standby)
2228 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002229 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002230 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2231 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002232 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002233 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002234 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002235 }
2236 }
2237
2238 if (out_snd_device == usecase->out_snd_device &&
2239 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302240
2241 if (!force_device_switch(usecase))
2242 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 }
2244
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302245 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2246 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2247 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2248 return 0;
2249 }
2250
sangwoobc677242013-08-08 16:53:43 +09002251 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002252 out_snd_device, platform_get_snd_device_name(out_snd_device),
2253 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 /*
2256 * Limitation: While in call, to do a device switch we need to disable
2257 * and enable both RX and TX devices though one of them is same as current
2258 * device.
2259 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002260 if ((usecase->type == VOICE_CALL) &&
2261 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2262 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002263 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002264 }
2265
2266 if (((usecase->type == VOICE_CALL) ||
2267 (usecase->type == VOIP_CALL)) &&
2268 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2269 /* Disable sidetone only if voice/voip call already exists */
2270 if (voice_is_call_state_active(adev) ||
2271 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002272 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002273
2274 /* Disable aanc only if voice call exists */
2275 if (voice_is_call_state_active(adev))
2276 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002277 }
2278
Zhou Songc66eb7e2017-08-08 18:29:07 +08002279 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302280 (!audio_extn_a2dp_is_ready())) {
2281 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002282 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302283 }
2284
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002285 /* Disable current sound devices */
2286 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002287 disable_audio_route(adev, usecase);
2288 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 }
2290
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002291 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002292 disable_audio_route(adev, usecase);
2293 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 }
2295
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002296 /* Applicable only on the targets that has external modem.
2297 * New device information should be sent to modem before enabling
2298 * the devices to reduce in-call device switch time.
2299 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002300 if ((usecase->type == VOICE_CALL) &&
2301 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2302 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002303 status = platform_switch_voice_call_enable_device_config(adev->platform,
2304 out_snd_device,
2305 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002306 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002307
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002308 /* Enable new sound devices */
2309 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002310 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302311 if (platform_check_codec_asrc_support(adev->platform))
2312 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002313 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
2315
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002316 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302317 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002318 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002319 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002320
Avinash Vaish71a8b972014-07-24 15:36:33 +05302321 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002322 status = platform_switch_voice_call_device_post(adev->platform,
2323 out_snd_device,
2324 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302325 enable_audio_route_for_voice_usecases(adev, usecase);
2326 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002327
sangwoo170731f2013-06-08 15:36:36 +09002328 usecase->in_snd_device = in_snd_device;
2329 usecase->out_snd_device = out_snd_device;
2330
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302331 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2332 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302333 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002334 if ((24 == usecase->stream.out->bit_width) &&
2335 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2336 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2337 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2338 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2339 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2340 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2341 /*
2342 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2343 * configured device sample rate, if not update the COPP rate to be equal to the
2344 * device sample rate, else open COPP at stream sample rate
2345 */
2346 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2347 usecase->stream.out->sample_rate,
2348 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302349 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2350 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002351 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2352 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2353 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2354 }
Weiyin Jiang619761e2019-07-08 16:13:16 +08002355 }
2356 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002357
Weiyin Jiang619761e2019-07-08 16:13:16 +08002358 /* Notify device change info to effect clients registered */
2359 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang902f7d12019-03-05 23:39:45 +08002360 audio_extn_gef_notify_device_config(
2361 usecase->stream.out->devices,
2362 usecase->stream.out->channel_mask,
2363 usecase->stream.out->app_type_cfg.sample_rate,
2364 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302365 }
sangwoo170731f2013-06-08 15:36:36 +09002366
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002367 /* If input stream is already running then effect needs to be
2368 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002369 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2370 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002371 check_and_enable_effect(adev);
2372
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002373 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002374 /* Enable aanc only if voice call exists */
2375 if (voice_is_call_state_active(adev))
2376 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2377
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002378 /* Enable sidetone only if other voice/voip call already exists */
2379 if (voice_is_call_state_active(adev) ||
2380 voice_extn_compress_voip_is_started(adev))
2381 voice_set_sidetone(adev, out_snd_device, true);
2382 }
2383
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002384 /* Applicable only on the targets that has external modem.
2385 * Enable device command should be sent to modem only after
2386 * enabling voice call mixer controls
2387 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002388 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002389 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2390 out_snd_device,
2391 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302392
2393 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2394
2395 if (usecase->type == VOIP_CALL) {
2396 if (adev->active_input != NULL &&
2397 !adev->active_input->standby) {
2398 if (is_bt_soc_on(adev) == false){
2399 ALOGD("BT SCO MIC disconnected while in connection");
2400 if (adev->active_input->pcm != NULL)
2401 pcm_stop(adev->active_input->pcm);
2402 }
2403 }
2404 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2405 && usecase->stream.out->started) {
2406 if (is_bt_soc_on(adev) == false) {
2407 ALOGD("BT SCO/A2DP disconnected while in connection");
2408 out_standby_l(&usecase->stream.out->stream.common);
2409 }
2410 }
2411 } else if ((usecase->stream.out != NULL) &&
2412 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2413 usecase->stream.out->started) {
2414 if (is_bt_soc_on(adev) == false) {
2415 ALOGD("BT SCO/A2dp disconnected while in connection");
2416 out_standby_l(&usecase->stream.out->stream.common);
2417 }
2418 }
2419 }
2420
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302421 ALOGD("%s: done",__func__);
2422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 return status;
2424}
2425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426static int stop_input_stream(struct stream_in *in)
2427{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302428 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302430
2431 if (in == NULL) {
2432 ALOGE("%s: stream_in ptr is NULL", __func__);
2433 return -EINVAL;
2434 }
2435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 struct audio_device *adev = in->dev;
2437
Eric Laurent994a6932013-07-17 11:51:42 -07002438 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002439 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 uc_info = get_usecase_from_list(adev, in->usecase);
2441 if (uc_info == NULL) {
2442 ALOGE("%s: Could not find the usecase (%d) in the list",
2443 __func__, in->usecase);
2444 return -EINVAL;
2445 }
2446
Derek Chencdd17c72014-11-24 12:39:14 -08002447 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2448 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2449 ALOGE("%s: failed to stop ext hw plugin", __func__);
2450 }
2451
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002452 /* Close in-call recording streams */
2453 voice_check_and_stop_incall_rec_usecase(adev, in);
2454
Eric Laurent150dbfe2013-02-27 14:31:02 -08002455 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002456 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002457
2458 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002459 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002461 list_remove(&uc_info->list);
2462 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002464 adev->active_input = get_next_active_input(adev);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302465 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002466 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 return ret;
2468}
2469
2470int start_input_stream(struct stream_in *in)
2471{
2472 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002473 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302475
2476 if (in == NULL) {
2477 ALOGE("%s: stream_in ptr is NULL", __func__);
2478 return -EINVAL;
2479 }
2480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002482 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002483 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484
Mingming Yin2664a5b2015-09-03 10:53:11 -07002485 if (get_usecase_from_list(adev, usecase) == NULL)
2486 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302487 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2488 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002489
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302490 if (CARD_STATUS_OFFLINE == in->card_status||
2491 CARD_STATUS_OFFLINE == adev->card_status) {
2492 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302493 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302494 goto error_config;
2495 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302496
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302497 if (audio_is_bluetooth_sco_device(in->device)) {
2498 if (!adev->bt_sco_on) {
2499 ALOGE("%s: SCO profile is not ready, return error", __func__);
2500 ret = -EIO;
2501 goto error_config;
2502 }
2503 }
2504
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002505 /* Check if source matches incall recording usecase criteria */
2506 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2507 if (ret)
2508 goto error_config;
2509 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002510 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2511
2512 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2513 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2514 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002515 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002516 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002517
Eric Laurentb23d5282013-05-14 15:27:20 -07002518 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 if (in->pcm_device_id < 0) {
2520 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2521 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002522 ret = -EINVAL;
2523 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002525
2526 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002528
2529 if (!uc_info) {
2530 ret = -ENOMEM;
2531 goto error_config;
2532 }
2533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 uc_info->id = in->usecase;
2535 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002536 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537 uc_info->devices = in->device;
2538 uc_info->in_snd_device = SND_DEVICE_NONE;
2539 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002541 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302542 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2543 adev->perf_lock_opts,
2544 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002545 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546
Derek Chencdd17c72014-11-24 12:39:14 -08002547 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2548 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2549 ALOGE("%s: failed to start ext hw plugin", __func__);
2550 }
2551
Haynes Mathew George16081042017-05-31 17:16:49 -07002552 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302553 ret = audio_extn_cin_start_input_stream(in);
2554 if (ret)
2555 goto error_open;
2556 else
2557 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002558 }
2559
Haynes Mathew George16081042017-05-31 17:16:49 -07002560 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002561 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002562 ALOGE("%s: pcm stream not ready", __func__);
2563 goto error_open;
2564 }
2565 ret = pcm_start(in->pcm);
2566 if (ret < 0) {
2567 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2568 goto error_open;
2569 }
2570 } else {
2571 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2572 unsigned int pcm_open_retry_count = 0;
2573
2574 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2575 flags |= PCM_MMAP | PCM_NOIRQ;
2576 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2577 } else if (in->realtime) {
2578 flags |= PCM_MMAP | PCM_NOIRQ;
2579 }
2580
Garmond Leunge2433c32017-09-28 21:51:22 -07002581 if (audio_extn_ffv_get_stream() == in) {
2582 ALOGD("%s: ffv stream, update pcm config", __func__);
2583 audio_extn_ffv_update_pcm_config(&config);
2584 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002585 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2586 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2587
2588 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002589 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002590 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002591 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002592 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05302593 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
2594 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2595 adev->card_status = CARD_STATUS_OFFLINE;
2596 in->card_status = CARD_STATUS_OFFLINE;
2597 ret = -EIO;
2598 goto error_open;
2599 }
2600
Haynes Mathew George16081042017-05-31 17:16:49 -07002601 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2602 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2603 if (in->pcm != NULL) {
2604 pcm_close(in->pcm);
2605 in->pcm = NULL;
2606 }
2607 if (pcm_open_retry_count-- == 0) {
2608 ret = -EIO;
2609 goto error_open;
2610 }
2611 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2612 continue;
2613 }
2614 break;
2615 }
2616
2617 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002618 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002619 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002620 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002621 if (ret < 0) {
2622 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2623 pcm_close(in->pcm);
2624 in->pcm = NULL;
2625 goto error_open;
2626 }
2627 register_in_stream(in);
2628 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002629 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002630 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002631 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002632 if (ret < 0) {
2633 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002634 pcm_close(in->pcm);
2635 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002636 goto error_open;
2637 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002638 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002639 }
2640
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002641 check_and_enable_effect(adev);
2642
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302643done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302644 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002645 ALOGD("%s: exit", __func__);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302646 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002647 return ret;
2648
2649error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302650 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002652error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302653 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302654 /*
2655 * sleep 50ms to allow sufficient time for kernel
2656 * drivers to recover incases like SSR.
2657 */
2658 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002659 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302660 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002661 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662}
2663
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002664void lock_input_stream(struct stream_in *in)
2665{
2666 pthread_mutex_lock(&in->pre_lock);
2667 pthread_mutex_lock(&in->lock);
2668 pthread_mutex_unlock(&in->pre_lock);
2669}
2670
2671void lock_output_stream(struct stream_out *out)
2672{
2673 pthread_mutex_lock(&out->pre_lock);
2674 pthread_mutex_lock(&out->lock);
2675 pthread_mutex_unlock(&out->pre_lock);
2676}
2677
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678/* must be called with out->lock locked */
2679static int send_offload_cmd_l(struct stream_out* out, int command)
2680{
2681 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2682
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002683 if (!cmd) {
2684 ALOGE("failed to allocate mem for command 0x%x", command);
2685 return -ENOMEM;
2686 }
2687
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002688 ALOGVV("%s %d", __func__, command);
2689
2690 cmd->cmd = command;
2691 list_add_tail(&out->offload_cmd_list, &cmd->node);
2692 pthread_cond_signal(&out->offload_cond);
2693 return 0;
2694}
2695
2696/* must be called iwth out->lock locked */
2697static void stop_compressed_output_l(struct stream_out *out)
2698{
2699 out->offload_state = OFFLOAD_STATE_IDLE;
2700 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002701 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002702 if (out->compr != NULL) {
2703 compress_stop(out->compr);
2704 while (out->offload_thread_blocked) {
2705 pthread_cond_wait(&out->cond, &out->lock);
2706 }
2707 }
2708}
2709
Varun Balaraje49253e2017-07-06 19:48:56 +05302710bool is_interactive_usecase(audio_usecase_t uc_id)
2711{
2712 unsigned int i;
2713 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2714 if (uc_id == interactive_usecases[i])
2715 return true;
2716 }
2717 return false;
2718}
2719
2720static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2721{
2722 audio_usecase_t ret_uc = USECASE_INVALID;
2723 unsigned int intract_uc_index;
2724 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2725
2726 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2727 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2728 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2729 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2730 ret_uc = interactive_usecases[intract_uc_index];
2731 break;
2732 }
2733 }
2734
2735 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2736 return ret_uc;
2737}
2738
2739static void free_interactive_usecase(struct audio_device *adev,
2740 audio_usecase_t uc_id)
2741{
2742 unsigned int interact_uc_index;
2743 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2744
2745 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2746 if (interactive_usecases[interact_uc_index] == uc_id) {
2747 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2748 break;
2749 }
2750 }
2751 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2752}
2753
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002754bool is_offload_usecase(audio_usecase_t uc_id)
2755{
2756 unsigned int i;
2757 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2758 if (uc_id == offload_usecases[i])
2759 return true;
2760 }
2761 return false;
2762}
2763
Dhananjay Kumarac341582017-02-23 23:42:25 +05302764static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002765{
vivek mehta446c3962015-09-14 10:57:35 -07002766 audio_usecase_t ret_uc = USECASE_INVALID;
2767 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002768 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002769 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302770 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002771 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2772 else
2773 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002774
vivek mehta446c3962015-09-14 10:57:35 -07002775 pthread_mutex_lock(&adev->lock);
2776 if (get_usecase_from_list(adev, ret_uc) != NULL)
2777 ret_uc = USECASE_INVALID;
2778 pthread_mutex_unlock(&adev->lock);
2779
2780 return ret_uc;
2781 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002782
2783 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002784 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2785 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2786 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2787 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002788 break;
2789 }
2790 }
vivek mehta446c3962015-09-14 10:57:35 -07002791
2792 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2793 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002794}
2795
2796static void free_offload_usecase(struct audio_device *adev,
2797 audio_usecase_t uc_id)
2798{
vivek mehta446c3962015-09-14 10:57:35 -07002799 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002800 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002801
2802 if (!adev->multi_offload_enable)
2803 return;
2804
2805 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2806 if (offload_usecases[offload_uc_index] == uc_id) {
2807 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002808 break;
2809 }
2810 }
2811 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2812}
2813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814static void *offload_thread_loop(void *context)
2815{
2816 struct stream_out *out = (struct stream_out *) context;
2817 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002818 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002820 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2821 set_sched_policy(0, SP_FOREGROUND);
2822 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2823
2824 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002825 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 for (;;) {
2827 struct offload_cmd *cmd = NULL;
2828 stream_callback_event_t event;
2829 bool send_callback = false;
2830
2831 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2832 __func__, list_empty(&out->offload_cmd_list),
2833 out->offload_state);
2834 if (list_empty(&out->offload_cmd_list)) {
2835 ALOGV("%s SLEEPING", __func__);
2836 pthread_cond_wait(&out->offload_cond, &out->lock);
2837 ALOGV("%s RUNNING", __func__);
2838 continue;
2839 }
2840
2841 item = list_head(&out->offload_cmd_list);
2842 cmd = node_to_item(item, struct offload_cmd, node);
2843 list_remove(item);
2844
2845 ALOGVV("%s STATE %d CMD %d out->compr %p",
2846 __func__, out->offload_state, cmd->cmd, out->compr);
2847
2848 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2849 free(cmd);
2850 break;
2851 }
2852
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002853 // allow OFFLOAD_CMD_ERROR reporting during standby
2854 // this is needed to handle failures during compress_open
2855 // Note however that on a pause timeout, the stream is closed
2856 // and no offload usecase will be active. Therefore this
2857 // special case is needed for compress_open failures alone
2858 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2859 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002861 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 pthread_cond_signal(&out->cond);
2863 continue;
2864 }
2865 out->offload_thread_blocked = true;
2866 pthread_mutex_unlock(&out->lock);
2867 send_callback = false;
2868 switch(cmd->cmd) {
2869 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002870 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002872 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 send_callback = true;
2874 event = STREAM_CBK_EVENT_WRITE_READY;
2875 break;
2876 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002877 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302878 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002879 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302880 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002881 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302882 if (ret < 0)
2883 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302884 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302885 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002886 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002887 else
2888 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002889 if (-ENETRESET != ret && !(-EINTR == ret &&
2890 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302891 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302892 pthread_mutex_lock(&out->lock);
2893 out->send_new_metadata = 1;
2894 out->send_next_track_params = true;
2895 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302896 event = STREAM_CBK_EVENT_DRAIN_READY;
2897 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2898 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302899 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 break;
2901 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002902 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002903 ret = compress_drain(out->compr);
2904 ALOGD("copl(%p):out of compress_drain", out);
2905 // EINTR check avoids drain interruption due to SSR
2906 if (-ENETRESET != ret && !(-EINTR == ret &&
2907 CARD_STATUS_OFFLINE == out->card_status)) {
2908 send_callback = true;
2909 event = STREAM_CBK_EVENT_DRAIN_READY;
2910 } else
2911 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302913 case OFFLOAD_CMD_ERROR:
2914 ALOGD("copl(%p): sending error callback to AF", out);
2915 send_callback = true;
2916 event = STREAM_CBK_EVENT_ERROR;
2917 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 default:
2919 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2920 break;
2921 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002922 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002923 out->offload_thread_blocked = false;
2924 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002925 if (send_callback && out->client_callback) {
2926 ALOGVV("%s: sending client_callback event %d", __func__, event);
2927 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002928 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 free(cmd);
2930 }
2931
2932 pthread_cond_signal(&out->cond);
2933 while (!list_empty(&out->offload_cmd_list)) {
2934 item = list_head(&out->offload_cmd_list);
2935 list_remove(item);
2936 free(node_to_item(item, struct offload_cmd, node));
2937 }
2938 pthread_mutex_unlock(&out->lock);
2939
2940 return NULL;
2941}
2942
2943static int create_offload_callback_thread(struct stream_out *out)
2944{
2945 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2946 list_init(&out->offload_cmd_list);
2947 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2948 offload_thread_loop, out);
2949 return 0;
2950}
2951
2952static int destroy_offload_callback_thread(struct stream_out *out)
2953{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002954 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 stop_compressed_output_l(out);
2956 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2957
2958 pthread_mutex_unlock(&out->lock);
2959 pthread_join(out->offload_thread, (void **) NULL);
2960 pthread_cond_destroy(&out->offload_cond);
2961
2962 return 0;
2963}
2964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965static int stop_output_stream(struct stream_out *out)
2966{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302967 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 struct audio_usecase *uc_info;
2969 struct audio_device *adev = out->dev;
2970
Eric Laurent994a6932013-07-17 11:51:42 -07002971 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002972 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 uc_info = get_usecase_from_list(adev, out->usecase);
2974 if (uc_info == NULL) {
2975 ALOGE("%s: Could not find the usecase (%d) in the list",
2976 __func__, out->usecase);
2977 return -EINVAL;
2978 }
2979
Derek Chencdd17c72014-11-24 12:39:14 -08002980 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
2981 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2982 ALOGE("%s: failed to stop ext hw plugin", __func__);
2983 }
2984
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002985 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302986 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002987 if (adev->visualizer_stop_output != NULL)
2988 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002989
2990 audio_extn_dts_remove_state_notifier_node(out->usecase);
2991
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002992 if (adev->offload_effects_stop_output != NULL)
2993 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2994 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002995
Arun Mirpuridbef0c72018-09-12 18:36:10 -07002996 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
2997 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07002998 voice_set_device_mute_flag(adev, false);
2999
Eric Laurent150dbfe2013-02-27 14:31:02 -08003000 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003001 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003002
3003 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003004 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003006 if (is_offload_usecase(out->usecase)) {
3007 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3008 adev->dsp_bit_width_enforce_mode,
3009 false);
3010 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003011 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3012 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3013 false);
3014
3015 if (ret != 0)
3016 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3017 /* default service interval was successfully updated,
3018 reopen USB backend with new service interval */
3019 ret = 0;
3020 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003021
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003022 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303023 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003024 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303025 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003026 ALOGV("Disable passthrough , reset mixer to pcm");
3027 /* NO_PASSTHROUGH */
3028 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003029 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003030 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3031 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003032
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303033 /* Must be called after removing the usecase from list */
3034 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303035 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303036
Manish Dewangan21a850a2017-08-14 12:03:55 +05303037 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003038 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3039 if (ret < 0)
3040 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3041 }
3042
Garmond Leung5fd0b552018-04-17 11:56:12 -07003043 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003044 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 return ret;
3046}
3047
3048int start_output_stream(struct stream_out *out)
3049{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 struct audio_usecase *uc_info;
3052 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003053 char mixer_ctl_name[128];
3054 struct mixer_ctl *ctl = NULL;
3055 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303056 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057
Haynes Mathew George380745d2017-10-04 15:27:45 -07003058 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003059 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3060 ret = -EINVAL;
3061 goto error_config;
3062 }
3063
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303064 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3065 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3066 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303067
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303068 if (CARD_STATUS_OFFLINE == out->card_status ||
3069 CARD_STATUS_OFFLINE == adev->card_status) {
3070 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303071 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303072 goto error_config;
3073 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303074
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003075 //Update incall music usecase to reflect correct voice session
3076 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3077 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3078 if (ret != 0) {
3079 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3080 __func__, ret);
3081 goto error_config;
3082 }
3083 }
3084
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303085 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3086 if (!audio_extn_a2dp_is_ready()) {
3087 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303088 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303089 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303090 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3091 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3092 ret = -EAGAIN;
3093 goto error_config;
3094 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303095 }
3096 }
3097 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303098 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3099 if (!adev->bt_sco_on) {
3100 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3101 //combo usecase just by pass a2dp
3102 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3103 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3104 } else {
3105 ALOGE("%s: SCO profile is not ready, return error", __func__);
3106 ret = -EAGAIN;
3107 goto error_config;
3108 }
3109 }
3110 }
3111
Eric Laurentb23d5282013-05-14 15:27:20 -07003112 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 if (out->pcm_device_id < 0) {
3114 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3115 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003116 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003117 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 }
3119
3120 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003121
3122 if (!uc_info) {
3123 ret = -ENOMEM;
3124 goto error_config;
3125 }
3126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 uc_info->id = out->usecase;
3128 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003129 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003130 uc_info->devices = out->devices;
3131 uc_info->in_snd_device = SND_DEVICE_NONE;
3132 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003133
3134 /* This must be called before adding this usecase to the list */
3135 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3136 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3137 /* USB backend is not reopened immediately.
3138 This is eventually done as part of select_devices */
3139 }
3140
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003141 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303143 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3144 adev->perf_lock_opts,
3145 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303146
3147 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303148 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303149 if (audio_extn_passthru_is_enabled() &&
3150 audio_extn_passthru_is_passthrough_stream(out)) {
3151 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303152 }
3153 }
3154
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303155 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3156 (!audio_extn_a2dp_is_ready())) {
3157 if (!a2dp_combo) {
3158 check_a2dp_restore_l(adev, out, false);
3159 } else {
3160 audio_devices_t dev = out->devices;
3161 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3162 select_devices(adev, out->usecase);
3163 out->devices = dev;
3164 }
3165 } else {
3166 select_devices(adev, out->usecase);
3167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003168
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003169 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3170 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003171 voice_set_device_mute_flag(adev, true);
3172
Derek Chencdd17c72014-11-24 12:39:14 -08003173 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3174 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3175 ALOGE("%s: failed to start ext hw plugin", __func__);
3176 }
3177
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003178 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3179 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003180
3181 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003182 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003183 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3184 ALOGE("%s: pcm stream not ready", __func__);
3185 goto error_open;
3186 }
3187 ret = pcm_start(out->pcm);
3188 if (ret < 0) {
3189 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3190 goto error_open;
3191 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003192 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003193 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003194 unsigned int flags = PCM_OUT;
3195 unsigned int pcm_open_retry_count = 0;
3196 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3197 flags |= PCM_MMAP | PCM_NOIRQ;
3198 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003199 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003200 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003201 } else
3202 flags |= PCM_MONOTONIC;
3203
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003204 if ((adev->vr_audio_mode_enabled) &&
3205 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3206 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3207 "PCM_Dev %d Topology", out->pcm_device_id);
3208 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3209 if (!ctl) {
3210 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3211 __func__, mixer_ctl_name);
3212 } else {
3213 //if success use ULLPP
3214 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3215 __func__, mixer_ctl_name, out->pcm_device_id);
3216 //There is a still a possibility that some sessions
3217 // that request for FAST|RAW when 3D audio is active
3218 //can go through ULLPP. Ideally we expects apps to
3219 //listen to audio focus and stop concurrent playback
3220 //Also, we will look for mode flag (voice_in_communication)
3221 //before enabling the realtime flag.
3222 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3223 }
3224 }
3225
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003226 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003227 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3229 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003230 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303231 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
3232 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3233 out->card_status = CARD_STATUS_OFFLINE;
3234 adev->card_status = CARD_STATUS_OFFLINE;
3235 ret = -EIO;
3236 goto error_open;
3237 }
3238
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003239 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3240 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3241 if (out->pcm != NULL) {
3242 pcm_close(out->pcm);
3243 out->pcm = NULL;
3244 }
3245 if (pcm_open_retry_count-- == 0) {
3246 ret = -EIO;
3247 goto error_open;
3248 }
3249 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3250 continue;
3251 }
3252 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05303254 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3255 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003256
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003257 ALOGV("%s: pcm_prepare", __func__);
3258 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003259 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003260 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003261 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003262 if (ret < 0) {
3263 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3264 pcm_close(out->pcm);
3265 out->pcm = NULL;
3266 goto error_open;
3267 }
3268 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003269 // apply volume for voip playback after path is set up
3270 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3271 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003273 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303274 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003275 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3276 adev->dsp_bit_width_enforce_mode,
3277 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003279 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003280 out->compr = compress_open(adev->snd_card,
3281 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003283 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303284 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
3285 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3286 adev->card_status = CARD_STATUS_OFFLINE;
3287 out->card_status = CARD_STATUS_OFFLINE;
3288 ret = -EIO;
3289 goto error_open;
3290 }
3291
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003293 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 compress_close(out->compr);
3295 out->compr = NULL;
3296 ret = -EIO;
3297 goto error_open;
3298 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303299 /* compress_open sends params of the track, so reset the flag here */
3300 out->is_compr_metadata_avail = false;
3301
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003302 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003303 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003304
Fred Oh3f43e742015-03-04 18:42:34 -08003305 /* Since small bufs uses blocking writes, a write will be blocked
3306 for the default max poll time (20s) in the event of an SSR.
3307 Reduce the poll time to observe and deal with SSR faster.
3308 */
Ashish Jain5106d362016-05-11 19:23:33 +05303309 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003310 compress_set_max_poll_wait(out->compr, 1000);
3311 }
3312
Manish Dewangan69426c82017-01-30 17:35:36 +05303313 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303314 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303315
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003316 audio_extn_dts_create_state_notifier_node(out->usecase);
3317 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3318 popcount(out->channel_mask),
3319 out->playback_started);
3320
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003321#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303322 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003323 audio_extn_dolby_send_ddp_endp_params(adev);
3324#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303325 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3326 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003327 if (adev->visualizer_start_output != NULL)
3328 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3329 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303330 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003331 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003334
3335 if (ret == 0) {
3336 register_out_stream(out);
3337 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003338 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3339 ALOGE("%s: pcm stream not ready", __func__);
3340 goto error_open;
3341 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003342 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003343 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003344 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003345 if (ret < 0)
3346 goto error_open;
3347 }
3348 }
3349
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303350 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003351 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003352
Manish Dewangan21a850a2017-08-14 12:03:55 +05303353 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003354 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003355 if (ret < 0)
3356 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3357 }
3358
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003359 // consider a scenario where on pause lower layers are tear down.
3360 // so on resume, swap mixer control need to be sent only when
3361 // backend is active, hence rather than sending from enable device
3362 // sending it from start of streamtream
3363
3364 platform_set_swap_channels(adev, true);
3365
Haynes Mathew George380745d2017-10-04 15:27:45 -07003366 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303367 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003368 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003369error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303370 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003372error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303373 /*
3374 * sleep 50ms to allow sufficient time for kernel
3375 * drivers to recover incases like SSR.
3376 */
3377 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003378 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303379 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003380 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383static int check_input_parameters(uint32_t sample_rate,
3384 audio_format_t format,
3385 int channel_count)
3386{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003387 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303389 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3390 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3391 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003392 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003393 !audio_extn_compr_cap_format_supported(format))
3394 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003395
3396 switch (channel_count) {
3397 case 1:
3398 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303399 case 3:
3400 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003401 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003402 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003403 break;
3404 default:
3405 ret = -EINVAL;
3406 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407
3408 switch (sample_rate) {
3409 case 8000:
3410 case 11025:
3411 case 12000:
3412 case 16000:
3413 case 22050:
3414 case 24000:
3415 case 32000:
3416 case 44100:
3417 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003418 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303419 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003420 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303421 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 break;
3423 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003424 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 }
3426
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003427 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428}
3429
Naresh Tanniru04f71882018-06-26 17:46:22 +05303430
3431/** Add a value in a list if not already present.
3432 * @return true if value was successfully inserted or already present,
3433 * false if the list is full and does not contain the value.
3434 */
3435static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3436 for (size_t i = 0; i < list_length; i++) {
3437 if (list[i] == value) return true; // value is already present
3438 if (list[i] == 0) { // no values in this slot
3439 list[i] = value;
3440 return true; // value inserted
3441 }
3442 }
3443 return false; // could not insert value
3444}
3445
3446/** Add channel_mask in supported_channel_masks if not already present.
3447 * @return true if channel_mask was successfully inserted or already present,
3448 * false if supported_channel_masks is full and does not contain channel_mask.
3449 */
3450static void register_channel_mask(audio_channel_mask_t channel_mask,
3451 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3452 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3453 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3454}
3455
3456/** Add format in supported_formats if not already present.
3457 * @return true if format was successfully inserted or already present,
3458 * false if supported_formats is full and does not contain format.
3459 */
3460static void register_format(audio_format_t format,
3461 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3462 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3463 "%s: stream can not declare supporting its format %x", __func__, format);
3464}
3465/** Add sample_rate in supported_sample_rates if not already present.
3466 * @return true if sample_rate was successfully inserted or already present,
3467 * false if supported_sample_rates is full and does not contain sample_rate.
3468 */
3469static void register_sample_rate(uint32_t sample_rate,
3470 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3471 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3472 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3473}
3474
Karthikeyan Mani35531922018-11-07 15:44:13 -08003475static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3476{
3477 uint32_t high = num1, low = num2, temp = 0;
3478
3479 if (!num1 || !num2)
3480 return 0;
3481
3482 if (num1 < num2) {
3483 high = num2;
3484 low = num1;
3485 }
3486
3487 while (low != 0) {
3488 temp = low;
3489 low = high % low;
3490 high = temp;
3491 }
3492 return (num1 * num2)/high;
3493}
3494
3495static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3496{
3497 uint32_t remainder = 0;
3498
3499 if (!multiplier)
3500 return num;
3501
3502 remainder = num % multiplier;
3503 if (remainder)
3504 num += (multiplier - remainder);
3505
3506 return num;
3507}
3508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509static size_t get_input_buffer_size(uint32_t sample_rate,
3510 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003511 int channel_count,
3512 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513{
3514 size_t size = 0;
Karthikeyan Mani35531922018-11-07 15:44:13 -08003515 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003517 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3518 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003520 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003521 if (is_low_latency)
3522 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303523
Karthikeyan Mani35531922018-11-07 15:44:13 -08003524 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3525 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003527 /* make sure the size is multiple of 32 bytes
3528 * At 48 kHz mono 16-bit PCM:
3529 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3530 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Mani35531922018-11-07 15:44:13 -08003531 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003532 */
Karthikeyan Mani35531922018-11-07 15:44:13 -08003533 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003534
3535 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536}
3537
Ashish Jain058165c2016-09-28 23:18:48 +05303538static size_t get_output_period_size(uint32_t sample_rate,
3539 audio_format_t format,
3540 int channel_count,
3541 int duration /*in millisecs*/)
3542{
3543 size_t size = 0;
3544 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3545
3546 if ((duration == 0) || (sample_rate == 0) ||
3547 (bytes_per_sample == 0) || (channel_count == 0)) {
3548 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3549 bytes_per_sample, channel_count);
3550 return -EINVAL;
3551 }
3552
3553 size = (sample_rate *
3554 duration *
3555 bytes_per_sample *
3556 channel_count) / 1000;
3557 /*
3558 * To have same PCM samples for all channels, the buffer size requires to
3559 * be multiple of (number of channels * bytes per sample)
3560 * For writes to succeed, the buffer must be written at address which is multiple of 32
3561 */
3562 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3563
3564 return (size/(channel_count * bytes_per_sample));
3565}
3566
Zhou Song48453a02018-01-10 17:50:59 +08003567static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303568{
3569 uint64_t actual_frames_rendered = 0;
3570 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3571
3572 /* This adjustment accounts for buffering after app processor.
3573 * It is based on estimated DSP latency per use case, rather than exact.
3574 */
3575 int64_t platform_latency = platform_render_latency(out->usecase) *
3576 out->sample_rate / 1000000LL;
3577
Zhou Song48453a02018-01-10 17:50:59 +08003578 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303579 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3580 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3581 * hence only estimate.
3582 */
3583 int64_t signed_frames = out->written - kernel_buffer_size;
3584
3585 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3586
Zhou Song48453a02018-01-10 17:50:59 +08003587 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303588 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003589 if (timestamp != NULL )
3590 *timestamp = out->writeAt;
3591 } else if (timestamp != NULL) {
3592 clock_gettime(CLOCK_MONOTONIC, timestamp);
3593 }
3594 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303595
3596 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3597 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3598 (long long int)out->written, (int)kernel_buffer_size,
3599 audio_bytes_per_sample(out->compr_config.codec->format),
3600 popcount(out->channel_mask));
3601
3602 return actual_frames_rendered;
3603}
3604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3606{
3607 struct stream_out *out = (struct stream_out *)stream;
3608
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610}
3611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003612static int out_set_sample_rate(struct audio_stream *stream __unused,
3613 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614{
3615 return -ENOSYS;
3616}
3617
3618static size_t out_get_buffer_size(const struct audio_stream *stream)
3619{
3620 struct stream_out *out = (struct stream_out *)stream;
3621
Varun Balaraje49253e2017-07-06 19:48:56 +05303622 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303623 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303624 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303625 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3626 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3627 else
3628 return out->compr_config.fragment_size;
3629 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003630 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003631 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3632 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 +05303633 else if (is_offload_usecase(out->usecase) &&
3634 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303635 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003636
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003637 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003638 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639}
3640
3641static uint32_t out_get_channels(const struct audio_stream *stream)
3642{
3643 struct stream_out *out = (struct stream_out *)stream;
3644
3645 return out->channel_mask;
3646}
3647
3648static audio_format_t out_get_format(const struct audio_stream *stream)
3649{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003650 struct stream_out *out = (struct stream_out *)stream;
3651
3652 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653}
3654
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003655static int out_set_format(struct audio_stream *stream __unused,
3656 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657{
3658 return -ENOSYS;
3659}
3660
3661static int out_standby(struct audio_stream *stream)
3662{
3663 struct stream_out *out = (struct stream_out *)stream;
3664 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003665 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303667 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3668 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003670 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003672 if (adev->adm_deregister_stream)
3673 adev->adm_deregister_stream(adev->adm_data, out->handle);
3674
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003675 if (is_offload_usecase(out->usecase))
3676 stop_compressed_output_l(out);
3677
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003678 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003680 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3681 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303682 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003683 pthread_mutex_unlock(&adev->lock);
3684 pthread_mutex_unlock(&out->lock);
3685 ALOGD("VOIP output entered standby");
3686 return 0;
3687 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688 if (out->pcm) {
3689 pcm_close(out->pcm);
3690 out->pcm = NULL;
3691 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003692 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3693 do_stop = out->playback_started;
3694 out->playback_started = false;
3695 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003696 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003697 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303698 out->send_next_track_params = false;
3699 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003700 out->gapless_mdata.encoder_delay = 0;
3701 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003702 if (out->compr != NULL) {
3703 compress_close(out->compr);
3704 out->compr = NULL;
3705 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003706 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003707 if (do_stop) {
3708 stop_output_stream(out);
3709 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003710 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 }
3712 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303713 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 return 0;
3715}
3716
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303717static int out_on_error(struct audio_stream *stream)
3718{
3719 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003720 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303721
3722 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003723 // always send CMD_ERROR for offload streams, this
3724 // is needed e.g. when SSR happens within compress_open
3725 // since the stream is active, offload_callback_thread is also active.
3726 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3727 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003728 }
3729 pthread_mutex_unlock(&out->lock);
3730
3731 status = out_standby(&out->stream.common);
3732
3733 lock_output_stream(out);
3734 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003735 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303736 }
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05303737
3738 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3739 ALOGD("Setting previous card status if offline");
3740 out->prev_card_status_offline = true;
3741 }
3742
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303743 pthread_mutex_unlock(&out->lock);
3744
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003745 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303746}
3747
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303748/*
3749 *standby implementation without locks, assumes that the callee already
3750 *has taken adev and out lock.
3751 */
3752int out_standby_l(struct audio_stream *stream)
3753{
3754 struct stream_out *out = (struct stream_out *)stream;
3755 struct audio_device *adev = out->dev;
3756
3757 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3758 stream, out->usecase, use_case_table[out->usecase]);
3759
3760 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003761 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303762 if (adev->adm_deregister_stream)
3763 adev->adm_deregister_stream(adev->adm_data, out->handle);
3764
3765 if (is_offload_usecase(out->usecase))
3766 stop_compressed_output_l(out);
3767
3768 out->standby = true;
3769 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3770 voice_extn_compress_voip_close_output_stream(stream);
3771 out->started = 0;
3772 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003773 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303774 return 0;
3775 } else if (!is_offload_usecase(out->usecase)) {
3776 if (out->pcm) {
3777 pcm_close(out->pcm);
3778 out->pcm = NULL;
3779 }
3780 } else {
3781 ALOGD("copl(%p):standby", out);
3782 out->send_next_track_params = false;
3783 out->is_compr_metadata_avail = false;
3784 out->gapless_mdata.encoder_delay = 0;
3785 out->gapless_mdata.encoder_padding = 0;
3786 if (out->compr != NULL) {
3787 compress_close(out->compr);
3788 out->compr = NULL;
3789 }
3790 }
3791 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003792 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303793 }
3794 ALOGD("%s: exit", __func__);
3795 return 0;
3796}
3797
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003798static int out_dump(const struct audio_stream *stream __unused,
3799 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800{
3801 return 0;
3802}
3803
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003804static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3805{
3806 int ret = 0;
3807 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003808
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003809 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003810 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003811 return -EINVAL;
3812 }
3813
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303814 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003815
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003816 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3817 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303818 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003819 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003820 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3821 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303822 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003823 }
3824
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003825 ALOGV("%s new encoder delay %u and padding %u", __func__,
3826 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3827
3828 return 0;
3829}
3830
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003831static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3832{
3833 return out == adev->primary_output || out == adev->voice_tx_output;
3834}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003835
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303836// note: this call is safe only if the stream_cb is
3837// removed first in close_output_stream (as is done now).
3838static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3839{
3840 if (!stream || !parms)
3841 return;
3842
3843 struct stream_out *out = (struct stream_out *)stream;
3844 struct audio_device *adev = out->dev;
3845
3846 card_status_t status;
3847 int card;
3848 if (parse_snd_card_status(parms, &card, &status) < 0)
3849 return;
3850
3851 pthread_mutex_lock(&adev->lock);
3852 bool valid_cb = (card == adev->snd_card);
3853 pthread_mutex_unlock(&adev->lock);
3854
3855 if (!valid_cb)
3856 return;
3857
3858 lock_output_stream(out);
3859 if (out->card_status != status)
3860 out->card_status = status;
3861 pthread_mutex_unlock(&out->lock);
3862
3863 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3864 use_case_table[out->usecase],
3865 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3866
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303867 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303868 out_on_error(stream);
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303869 if (voice_is_call_state_active(adev) &&
3870 out == adev->primary_output) {
3871 ALOGD("%s: SSR/PDR occurred, end all calls", __func__);
3872 pthread_mutex_lock(&adev->lock);
3873 voice_stop_call(adev);
3874 adev->mode = AUDIO_MODE_NORMAL;
3875 pthread_mutex_unlock(&adev->lock);
3876 }
3877 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303878 return;
3879}
3880
Kevin Rocardfce19002017-08-07 19:21:36 -07003881static int get_alive_usb_card(struct str_parms* parms) {
3882 int card;
3883 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3884 !audio_extn_usb_alive(card)) {
3885 return card;
3886 }
3887 return -ENODEV;
3888}
3889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3891{
3892 struct stream_out *out = (struct stream_out *)stream;
3893 struct audio_device *adev = out->dev;
3894 struct str_parms *parms;
3895 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003896 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303897 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003898 bool reconfig = false;
3899 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900
sangwoobc677242013-08-08 16:53:43 +09003901 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003902 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303904 if (!parms)
3905 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003906 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3907 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003909 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003910 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003912 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003913 * When HDMI cable is unplugged the music playback is paused and
3914 * the policy manager sends routing=0. But the audioflinger continues
3915 * to write data until standby time (3sec). As the HDMI core is
3916 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003917 * Avoid this by routing audio to speaker until standby.
3918 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003919 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3920 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303921 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003922 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3923 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003924 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303925 /*
3926 * When A2DP is disconnected the
3927 * music playback is paused and the policy manager sends routing=0
3928 * But the audioflingercontinues to write data until standby time
3929 * (3sec). As BT is turned off, the write gets blocked.
3930 * Avoid this by routing audio to speaker until standby.
3931 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003932 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003933 (val == AUDIO_DEVICE_NONE) &&
3934 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303935 val = AUDIO_DEVICE_OUT_SPEAKER;
3936 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303937 /*
3938 * When USB headset is disconnected the music platback paused
3939 * and the policy manager send routing=0. But if the USB is connected
3940 * back before the standby time, AFE is not closed and opened
3941 * when USB is connected back. So routing to speker will guarantee
3942 * AFE reconfiguration and AFE will be opend once USB is connected again
3943 */
3944 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3945 (val == AUDIO_DEVICE_NONE) &&
3946 !audio_extn_usb_connected(parms)) {
3947 val = AUDIO_DEVICE_OUT_SPEAKER;
3948 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303949 /* To avoid a2dp to sco overlapping / BT device improper state
3950 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303951 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303952 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3953 if (!audio_extn_a2dp_is_ready()) {
3954 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3955 //combo usecase just by pass a2dp
3956 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303957 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303958 } else {
3959 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3960 /* update device to a2dp and don't route as BT returned error
3961 * However it is still possible a2dp routing called because
3962 * of current active device disconnection (like wired headset)
3963 */
3964 out->devices = val;
3965 pthread_mutex_unlock(&out->lock);
3966 pthread_mutex_unlock(&adev->lock);
3967 goto error;
3968 }
3969 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303970 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003971
3972 audio_devices_t new_dev = val;
3973
3974 // Workaround: If routing to an non existing usb device, fail gracefully
3975 // The routing request will otherwise block during 10 second
3976 int card;
3977 if (audio_is_usb_out_device(new_dev) &&
3978 (card = get_alive_usb_card(parms)) >= 0) {
3979
3980 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3981 pthread_mutex_unlock(&adev->lock);
3982 pthread_mutex_unlock(&out->lock);
3983 ret = -ENOSYS;
3984 goto routing_fail;
3985 }
3986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003987 /*
3988 * select_devices() call below switches all the usecases on the same
3989 * backend to the new device. Refer to check_usecases_codec_backend() in
3990 * the select_devices(). But how do we undo this?
3991 *
3992 * For example, music playback is active on headset (deep-buffer usecase)
3993 * and if we go to ringtones and select a ringtone, low-latency usecase
3994 * will be started on headset+speaker. As we can't enable headset+speaker
3995 * and headset devices at the same time, select_devices() switches the music
3996 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3997 * So when the ringtone playback is completed, how do we undo the same?
3998 *
3999 * We are relying on the out_set_parameters() call on deep-buffer output,
4000 * once the ringtone playback is ended.
4001 * NOTE: We should not check if the current devices are same as new devices.
4002 * Because select_devices() must be called to switch back the music
4003 * playback to headset.
4004 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004005 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004006 audio_devices_t new_dev = val;
4007 bool same_dev = out->devices == new_dev;
4008 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004009
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004010 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004011 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004012 if (adev->mode == AUDIO_MODE_IN_CALL) {
4013 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004014 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4015 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4016 audio_extn_usb_set_service_interval(true /*playback*/,
4017 service_interval,
4018 &reconfig);
4019 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4020 }
4021 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004022 }
4023 } else {
4024 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004025 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004026 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004027 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004028
4029 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004030 if (!same_dev) {
4031 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304032 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4033 adev->perf_lock_opts,
4034 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004035 if (adev->adm_on_routing_change)
4036 adev->adm_on_routing_change(adev->adm_data,
4037 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004038 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304039 if (!bypass_a2dp) {
4040 select_devices(adev, out->usecase);
4041 } else {
4042 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4043 select_devices(adev, out->usecase);
4044 out->devices = new_dev;
4045 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004046
4047 if (!same_dev) {
4048 // on device switch force swap, lower functions will make sure
4049 // to check if swap is allowed or not.
4050 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304051 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004052 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304053 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4054 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004055 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304056 pthread_mutex_lock(&out->compr_mute_lock);
4057 out->a2dp_compress_mute = false;
4058 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4059 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004060 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4061 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304062 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004063 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004064 }
4065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004067 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004069 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004070
4071 if (out == adev->primary_output) {
4072 pthread_mutex_lock(&adev->lock);
4073 audio_extn_set_parameters(adev, parms);
4074 pthread_mutex_unlock(&adev->lock);
4075 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004076 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004077 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004078 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004079
4080 audio_extn_dts_create_state_notifier_node(out->usecase);
4081 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4082 popcount(out->channel_mask),
4083 out->playback_started);
4084
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004085 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004086 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004087
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304088 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4089 sizeof(value));
4090 if (err >= 0) {
4091 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4092 audio_extn_send_dual_mono_mixing_coefficients(out);
4093 }
4094
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304095 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4096 if (err >= 0) {
4097 strlcpy(out->profile, value, sizeof(out->profile));
4098 ALOGV("updating stream profile with value '%s'", out->profile);
4099 lock_output_stream(out);
4100 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4101 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004102 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304103 out->sample_rate, out->bit_width,
4104 out->channel_mask, out->profile,
4105 &out->app_type_cfg);
4106 pthread_mutex_unlock(&out->lock);
4107 }
4108
Alexy Joseph98988832017-01-13 14:56:59 -08004109 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004110 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4111 // and vendor.audio.hal.output.suspend.supported is set to true
4112 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004113 //check suspend parameter only for low latency and if the property
4114 //is enabled
4115 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4116 ALOGI("%s: got suspend_playback %s", __func__, value);
4117 lock_output_stream(out);
4118 if (!strncmp(value, "false", 5)) {
4119 //suspend_playback=false is supposed to set QOS value back to 75%
4120 //the mixer control sent with value Enable will achieve that
4121 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4122 } else if (!strncmp (value, "true", 4)) {
4123 //suspend_playback=true is supposed to remove QOS value
4124 //resetting the mixer control will set the default value
4125 //for the mixer control which is Disable and this removes the QOS vote
4126 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4127 } else {
4128 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4129 " got %s", __func__, value);
4130 ret = -1;
4131 }
4132
4133 if (ret != 0) {
4134 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4135 __func__, out->pm_qos_mixer_path, ret);
4136 }
4137
4138 pthread_mutex_unlock(&out->lock);
4139 }
4140 }
4141 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304143error:
Eric Laurent994a6932013-07-17 11:51:42 -07004144 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 return ret;
4146}
4147
Ramjee Singhacef98f2019-06-28 11:01:25 +05304148#if ANDROID_PLATFORM_SDK_VERSION >= 29
4149static int in_set_microphone_direction(const struct audio_stream_in *stream,
4150 audio_microphone_direction_t dir) {
4151 int ret_val = -ENOSYS;
4152 (void)stream;
4153 (void)dir;
4154 ALOGV("---- in_set_microphone_direction()");
4155 return ret_val;
4156}
4157
4158static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4159 int ret_val = -ENOSYS;
4160 (void)zoom;
4161 (void)stream;
4162 ALOGV("---- in_set_microphone_field_dimension()");
4163 return ret_val;
4164}
4165#endif
4166
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004167static bool stream_get_parameter_channels(struct str_parms *query,
4168 struct str_parms *reply,
4169 audio_channel_mask_t *supported_channel_masks) {
4170 int ret = -1;
4171 char value[512];
4172 bool first = true;
4173 size_t i, j;
4174
4175 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4176 ret = 0;
4177 value[0] = '\0';
4178 i = 0;
4179 while (supported_channel_masks[i] != 0) {
4180 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4181 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4182 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304183 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004184
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304185 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004186 first = false;
4187 break;
4188 }
4189 }
4190 i++;
4191 }
4192 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4193 }
4194 return ret == 0;
4195}
4196
4197static bool stream_get_parameter_formats(struct str_parms *query,
4198 struct str_parms *reply,
4199 audio_format_t *supported_formats) {
4200 int ret = -1;
4201 char value[256];
4202 size_t i, j;
4203 bool first = true;
4204
4205 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4206 ret = 0;
4207 value[0] = '\0';
4208 i = 0;
4209 while (supported_formats[i] != 0) {
4210 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4211 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4212 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304213 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004214 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304215 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004216 first = false;
4217 break;
4218 }
4219 }
4220 i++;
4221 }
4222 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4223 }
4224 return ret == 0;
4225}
4226
4227static bool stream_get_parameter_rates(struct str_parms *query,
4228 struct str_parms *reply,
4229 uint32_t *supported_sample_rates) {
4230
4231 int i;
4232 char value[256];
4233 int ret = -1;
4234 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4235 ret = 0;
4236 value[0] = '\0';
4237 i=0;
4238 int cursor = 0;
4239 while (supported_sample_rates[i]) {
4240 int avail = sizeof(value) - cursor;
4241 ret = snprintf(value + cursor, avail, "%s%d",
4242 cursor > 0 ? "|" : "",
4243 supported_sample_rates[i]);
4244 if (ret < 0 || ret >= avail) {
4245 // if cursor is at the last element of the array
4246 // overwrite with \0 is duplicate work as
4247 // snprintf already put a \0 in place.
4248 // else
4249 // we had space to write the '|' at value[cursor]
4250 // (which will be overwritten) or no space to fill
4251 // the first element (=> cursor == 0)
4252 value[cursor] = '\0';
4253 break;
4254 }
4255 cursor += ret;
4256 ++i;
4257 }
4258 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4259 value);
4260 }
4261 return ret >= 0;
4262}
4263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4265{
4266 struct stream_out *out = (struct stream_out *)stream;
4267 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004268 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269 char value[256];
4270 struct str_parms *reply = str_parms_create();
4271 size_t i, j;
4272 int ret;
4273 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004274
4275 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004276 if (reply) {
4277 str_parms_destroy(reply);
4278 }
4279 if (query) {
4280 str_parms_destroy(query);
4281 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004282 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4283 return NULL;
4284 }
4285
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004286 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4288 if (ret >= 0) {
4289 value[0] = '\0';
4290 i = 0;
4291 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004292 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4293 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004295 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004297 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298 first = false;
4299 break;
4300 }
4301 }
4302 i++;
4303 }
4304 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4305 str = str_parms_to_str(reply);
4306 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004307 voice_extn_out_get_parameters(out, query, reply);
4308 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004310
Alexy Joseph62142aa2015-11-16 15:10:34 -08004311
4312 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4313 if (ret >= 0) {
4314 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304315 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4316 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004317 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304318 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004319 } else {
4320 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304321 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004322 }
4323 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004324 if (str)
4325 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004326 str = str_parms_to_str(reply);
4327 }
4328
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004329 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4330 if (ret >= 0) {
4331 value[0] = '\0';
4332 i = 0;
4333 first = true;
4334 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004335 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4336 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004337 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004338 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004339 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004340 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004341 first = false;
4342 break;
4343 }
4344 }
4345 i++;
4346 }
4347 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004348 if (str)
4349 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004350 str = str_parms_to_str(reply);
4351 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004352
4353 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4354 if (ret >= 0) {
4355 value[0] = '\0';
4356 i = 0;
4357 first = true;
4358 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004359 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4360 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004361 if (!first) {
4362 strlcat(value, "|", sizeof(value));
4363 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004364 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004365 first = false;
4366 break;
4367 }
4368 }
4369 i++;
4370 }
4371 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4372 if (str)
4373 free(str);
4374 str = str_parms_to_str(reply);
4375 }
4376
Alexy Joseph98988832017-01-13 14:56:59 -08004377 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4378 //only low latency track supports suspend_resume
4379 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004380 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004381 if (str)
4382 free(str);
4383 str = str_parms_to_str(reply);
4384 }
4385
4386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 str_parms_destroy(query);
4388 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004389 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 return str;
4391}
4392
4393static uint32_t out_get_latency(const struct audio_stream_out *stream)
4394{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004395 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004397 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398
Alexy Josephaa54c872014-12-03 02:46:47 -08004399 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304400 lock_output_stream(out);
4401 latency = audio_extn_utils_compress_get_dsp_latency(out);
4402 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004403 } else if ((out->realtime) ||
4404 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004405 // since the buffer won't be filled up faster than realtime,
4406 // return a smaller number
4407 if (out->config.rate)
4408 period_ms = (out->af_period_multiplier * out->config.period_size *
4409 1000) / (out->config.rate);
4410 else
4411 period_ms = 0;
4412 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004413 } else {
4414 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004415 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004416 }
4417
yidongh0515e042017-07-06 15:00:34 +08004418 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004419 latency += audio_extn_a2dp_get_encoder_latency();
4420
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304421 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004422 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423}
4424
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304425static float AmpToDb(float amplification)
4426{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304427 float db = DSD_VOLUME_MIN_DB;
4428 if (amplification > 0) {
4429 db = 20 * log10(amplification);
4430 if(db < DSD_VOLUME_MIN_DB)
4431 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304432 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304433 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304434}
4435
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004436static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4437 float right)
4438{
4439 struct stream_out *out = (struct stream_out *)stream;
4440 long volume = 0;
4441 char mixer_ctl_name[128] = "";
4442 struct audio_device *adev = out->dev;
4443 struct mixer_ctl *ctl = NULL;
4444 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4445 PCM_PLAYBACK);
4446
4447 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4448 "Playback %d Volume", pcm_device_id);
4449 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4450 if (!ctl) {
4451 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4452 __func__, mixer_ctl_name);
4453 return -EINVAL;
4454 }
4455 if (left != right)
4456 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4457 __func__, left, right);
4458 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4459 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4460 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4461 __func__, mixer_ctl_name, volume);
4462 return -EINVAL;
4463 }
4464 return 0;
4465}
4466
4467
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304468static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4469 float right)
4470{
4471 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304472 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304473 char mixer_ctl_name[128];
4474 struct audio_device *adev = out->dev;
4475 struct mixer_ctl *ctl;
4476 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4477 PCM_PLAYBACK);
4478
4479 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4480 "Compress Playback %d Volume", pcm_device_id);
4481 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4482 if (!ctl) {
4483 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4484 __func__, mixer_ctl_name);
4485 return -EINVAL;
4486 }
4487 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4488 __func__, mixer_ctl_name, left, right);
4489 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4490 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4491 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4492
4493 return 0;
4494}
4495
Zhou Song2b8f28f2017-09-11 10:51:38 +08004496static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4497 float right)
4498{
4499 struct stream_out *out = (struct stream_out *)stream;
4500 char mixer_ctl_name[] = "App Type Gain";
4501 struct audio_device *adev = out->dev;
4502 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304503 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004504
4505 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4506 if (!ctl) {
4507 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4508 __func__, mixer_ctl_name);
4509 return -EINVAL;
4510 }
4511
4512 set_values[0] = 0; //0: Rx Session 1:Tx Session
4513 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304514 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4515 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004516
4517 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4518 return 0;
4519}
4520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521static int out_set_volume(struct audio_stream_out *stream, float left,
4522 float right)
4523{
Eric Laurenta9024de2013-04-04 09:19:12 -07004524 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304526 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004527
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004528 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4529
Eric Laurenta9024de2013-04-04 09:19:12 -07004530 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4531 /* only take left channel into account: the API is for stereo anyway */
4532 out->muted = (left == 0.0f);
4533 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004534 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304535 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004536 /*
4537 * Set mute or umute on HDMI passthrough stream.
4538 * Only take left channel into account.
4539 * Mute is 0 and unmute 1
4540 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304541 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304542 } else if (out->format == AUDIO_FORMAT_DSD){
4543 char mixer_ctl_name[128] = "DSD Volume";
4544 struct audio_device *adev = out->dev;
4545 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4546
4547 if (!ctl) {
4548 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4549 __func__, mixer_ctl_name);
4550 return -EINVAL;
4551 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304552 volume[0] = (long)(AmpToDb(left));
4553 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304554 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4555 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004556 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304557 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004558 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304559 if (!out->a2dp_compress_mute)
4560 ret = out_set_compr_volume(stream, left, right);
4561 out->volume_l = left;
4562 out->volume_r = right;
4563 pthread_mutex_unlock(&out->compr_mute_lock);
4564 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004565 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004566 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004567 if (!out->standby)
4568 ret = out_set_voip_volume(stream, left, right);
4569 out->volume_l = left;
4570 out->volume_r = right;
4571 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004572 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4573 ALOGV("%s: MMAP set volume called", __func__);
4574 if (!out->standby)
4575 ret = out_set_mmap_volume(stream, left, right);
4576 out->volume_l = left;
4577 out->volume_r = right;
4578 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004579 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 return -ENOSYS;
4582}
4583
Zhou Songc9672822017-08-16 16:01:39 +08004584static void update_frames_written(struct stream_out *out, size_t bytes)
4585{
4586 size_t bpf = 0;
4587
4588 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4589 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4590 bpf = 1;
4591 else if (!is_offload_usecase(out->usecase))
4592 bpf = audio_bytes_per_sample(out->format) *
4593 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004594
4595 pthread_mutex_lock(&out->position_query_lock);
4596 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004597 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004598 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4599 }
4600 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004601}
4602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4604 size_t bytes)
4605{
4606 struct stream_out *out = (struct stream_out *)stream;
4607 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004608 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304609 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004610 const size_t frame_size = audio_stream_out_frame_size(stream);
4611 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304612 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613
Haynes Mathew George380745d2017-10-04 15:27:45 -07004614 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004615 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304616
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304617 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004618
Dhananjay Kumarac341582017-02-23 23:42:25 +05304619 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304620 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304621 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4622 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004623 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304624 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304625 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304626 ALOGD(" %s: sound card is not active/SSR state", __func__);
4627 ret= -EIO;
4628 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304629 }
4630 }
4631
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304632 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304633 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304634 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304635 goto exit;
4636 }
4637
Haynes Mathew George16081042017-05-31 17:16:49 -07004638 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4639 ret = -EINVAL;
4640 goto exit;
4641 }
4642
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304643 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4644 !out->is_iec61937_info_available) {
4645
4646 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4647 out->is_iec61937_info_available = true;
4648 } else if (audio_extn_passthru_is_enabled()) {
4649 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304650 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304651
4652 if((out->format == AUDIO_FORMAT_DTS) ||
4653 (out->format == AUDIO_FORMAT_DTS_HD)) {
4654 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4655 buffer, bytes);
4656 if (ret) {
4657 if (ret != -ENOSYS) {
4658 out->is_iec61937_info_available = false;
4659 ALOGD("iec61937 transmission info not yet updated retry");
4660 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304661 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304662 /* if stream has started and after that there is
4663 * stream config change (iec transmission config)
4664 * then trigger select_device to update backend configuration.
4665 */
4666 out->stream_config_changed = true;
4667 pthread_mutex_lock(&adev->lock);
4668 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304669 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4670 ret = -EINVAL;
4671 goto exit;
4672 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304673 pthread_mutex_unlock(&adev->lock);
4674 out->stream_config_changed = false;
4675 out->is_iec61937_info_available = true;
4676 }
4677 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304678
Garmond Leung317cbf12017-09-13 16:20:50 -07004679 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304680 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4681 (out->is_iec61937_info_available == true)) {
4682 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4683 ret = -EINVAL;
4684 goto exit;
4685 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304686 }
4687 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304688
4689 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4690 (audio_extn_a2dp_is_suspended())) {
4691 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4692 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304693 ret = -EIO;
4694 goto exit;
4695 }
4696 }
4697 }
4698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004700 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004701 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004702 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4703 ret = voice_extn_compress_voip_start_output_stream(out);
4704 else
4705 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004707 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004709 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710 goto exit;
4711 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304712 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004713 if (last_known_cal_step != -1) {
4714 ALOGD("%s: retry previous failed cal level set", __func__);
4715 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304716 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004717 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304718
4719 if ((out->is_iec61937_info_available == true) &&
4720 (audio_extn_passthru_is_passthrough_stream(out))&&
4721 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4722 ret = -EINVAL;
4723 goto exit;
4724 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304725 if (out->set_dual_mono)
4726 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728
Ashish Jain81eb2a82015-05-13 10:52:34 +05304729 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004730 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304731 adev->is_channel_status_set = true;
4732 }
4733
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304734 if ((adev->use_old_pspd_mix_ctrl == true) &&
4735 (out->pspd_coeff_sent == false)) {
4736 /*
4737 * Need to resend pspd coefficients after stream started for
4738 * older kernel version as it does not save the coefficients
4739 * and also stream has to be started for coeff to apply.
4740 */
4741 usecase = get_usecase_from_list(adev, out->usecase);
4742 if (usecase != NULL) {
4743 audio_extn_set_custom_mtmx_params(adev, usecase, true);
4744 out->pspd_coeff_sent = true;
4745 }
4746 }
4747
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004748 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004749 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004750 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004751 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004752 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4753 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304754 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4755 ALOGD("copl(%p):send next track params in gapless", out);
4756 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4757 out->send_next_track_params = false;
4758 out->is_compr_metadata_avail = false;
4759 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004760 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304761 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304762 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004763
Ashish Jain83a6cc22016-06-28 14:34:17 +05304764 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304765 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304766 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304767 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004768 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304769 return -EINVAL;
4770 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304771 audio_format_t dst_format = out->hal_op_format;
4772 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304773
4774 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4775 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4776
Ashish Jain83a6cc22016-06-28 14:34:17 +05304777 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304778 dst_format,
4779 buffer,
4780 src_format,
4781 frames);
4782
Ashish Jain83a6cc22016-06-28 14:34:17 +05304783 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304784 bytes_to_write);
4785
4786 /*Convert written bytes in audio flinger format*/
4787 if (ret > 0)
4788 ret = ((ret * format_to_bitwidth_table[out->format]) /
4789 format_to_bitwidth_table[dst_format]);
4790 }
4791 } else
4792 ret = compress_write(out->compr, buffer, bytes);
4793
Zhou Songc9672822017-08-16 16:01:39 +08004794 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4795 update_frames_written(out, bytes);
4796
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304797 if (ret < 0)
4798 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004799 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304800 /*msg to cb thread only if non blocking write is enabled*/
4801 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304802 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004803 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304804 } else if (-ENETRESET == ret) {
4805 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304806 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304807 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304808 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004809 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304810 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004811 }
Ashish Jain5106d362016-05-11 19:23:33 +05304812
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304813 /* Call compr start only when non-zero bytes of data is there to be rendered */
4814 if (!out->playback_started && ret > 0) {
4815 int status = compress_start(out->compr);
4816 if (status < 0) {
4817 ret = status;
4818 ALOGE("%s: compr start failed with err %d", __func__, errno);
4819 goto exit;
4820 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004821 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004822 out->playback_started = 1;
4823 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004824
4825 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4826 popcount(out->channel_mask),
4827 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004828 }
4829 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004830 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004831 return ret;
4832 } else {
4833 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004834 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004835 if (out->muted)
4836 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004837 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4838 __func__, frames, frame_size, bytes_to_write);
4839
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004840 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4841 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004842 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4843 int16_t *src = (int16_t *)buffer;
4844 int16_t *dst = (int16_t *)buffer;
4845
4846 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4847 out->format != AUDIO_FORMAT_PCM_16_BIT,
4848 "out_write called for incall music use case with wrong properties");
4849
4850 /*
4851 * FIXME: this can be removed once audio flinger mixer supports
4852 * mono output
4853 */
4854
4855 /*
4856 * Code below goes over each frame in the buffer and adds both
4857 * L and R samples and then divides by 2 to convert to mono
4858 */
4859 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4860 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4861 }
4862 bytes_to_write /= 2;
4863 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004864
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304865 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004866
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004867 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004868
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004869 if (out->config.rate)
4870 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4871 out->config.rate;
4872
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004873 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004874 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4875
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004876 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004877 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004878 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304879 out->convert_buffer != NULL) {
4880
4881 memcpy_by_audio_format(out->convert_buffer,
4882 out->hal_op_format,
4883 buffer,
4884 out->hal_ip_format,
4885 out->config.period_size * out->config.channels);
4886
4887 ret = pcm_write(out->pcm, out->convert_buffer,
4888 (out->config.period_size *
4889 out->config.channels *
4890 format_to_bitwidth_table[out->hal_op_format]));
4891 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304892 /*
4893 * To avoid underrun in DSP when the application is not pumping
4894 * data at required rate, check for the no. of bytes and ignore
4895 * pcm_write if it is less than actual buffer size.
4896 * It is a work around to a change in compress VOIP driver.
4897 */
4898 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4899 bytes < (out->config.period_size * out->config.channels *
4900 audio_bytes_per_sample(out->format))) {
4901 size_t voip_buf_size =
4902 out->config.period_size * out->config.channels *
4903 audio_bytes_per_sample(out->format);
4904 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4905 __func__, bytes, voip_buf_size);
4906 usleep(((uint64_t)voip_buf_size - bytes) *
4907 1000000 / audio_stream_out_frame_size(stream) /
4908 out_get_sample_rate(&out->stream.common));
4909 ret = 0;
4910 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004911 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304912 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004913
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004914 release_out_focus(out);
4915
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304916 if (ret < 0)
4917 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004918 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304919 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004920 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921 }
4922
4923exit:
Zhou Songc9672822017-08-16 16:01:39 +08004924 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304925 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304926 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304927 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 pthread_mutex_unlock(&out->lock);
4929
4930 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004931 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004932 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304933 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304934 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304935 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304936 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304937 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304938 out->standby = true;
4939 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304940 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304941 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4942 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4943 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004944
4945 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304946 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004947 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004948 return ret;
4949 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004951 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004952 return bytes;
4953}
4954
4955static int out_get_render_position(const struct audio_stream_out *stream,
4956 uint32_t *dsp_frames)
4957{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004958 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004959
4960 if (dsp_frames == NULL)
4961 return -EINVAL;
4962
4963 *dsp_frames = 0;
4964 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004965 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304966
4967 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4968 * this operation and adev_close_output_stream(where out gets reset).
4969 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304970 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004971 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304972 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004973 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304974 return 0;
4975 }
4976
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004977 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304978 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304979 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004980 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304981 if (ret < 0)
4982 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004983 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304984 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004985 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304986 if (-ENETRESET == ret) {
4987 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304988 out->card_status = CARD_STATUS_OFFLINE;
4989 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304990 } else if(ret < 0) {
4991 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304992 ret = -EINVAL;
4993 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304994 /*
4995 * Handle corner case where compress session is closed during SSR
4996 * and timestamp is queried
4997 */
4998 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304999 ret = -EINVAL;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305000 } else if (out->prev_card_status_offline) {
5001 ALOGE("ERROR: previously sound card was offline,return error");
5002 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305003 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305004 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005005 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305006 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305007 pthread_mutex_unlock(&out->lock);
5008 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005009 } else if (audio_is_linear_pcm(out->format)) {
5010 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005011 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005012 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005013 } else
5014 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015}
5016
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005017static int out_add_audio_effect(const struct audio_stream *stream __unused,
5018 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019{
5020 return 0;
5021}
5022
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005023static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5024 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025{
5026 return 0;
5027}
5028
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005029static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5030 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305032 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033}
5034
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005035static int out_get_presentation_position(const struct audio_stream_out *stream,
5036 uint64_t *frames, struct timespec *timestamp)
5037{
5038 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305039 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005040 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005041
Ashish Jain5106d362016-05-11 19:23:33 +05305042 /* below piece of code is not guarded against any lock because audioFliner serializes
5043 * this operation and adev_close_output_stream( where out gets reset).
5044 */
5045 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305046 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005047 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305048 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5049 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5050 return 0;
5051 }
5052
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005053 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005054
Ashish Jain5106d362016-05-11 19:23:33 +05305055 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5056 ret = compress_get_tstamp(out->compr, &dsp_frames,
5057 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005058 // Adjustment accounts for A2dp encoder latency with offload usecases
5059 // Note: Encoder latency is returned in ms.
5060 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5061 unsigned long offset =
5062 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5063 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5064 }
Ashish Jain5106d362016-05-11 19:23:33 +05305065 ALOGVV("%s rendered frames %ld sample_rate %d",
5066 __func__, dsp_frames, out->sample_rate);
5067 *frames = dsp_frames;
5068 if (ret < 0)
5069 ret = -errno;
5070 if (-ENETRESET == ret) {
5071 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305072 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305073 ret = -EINVAL;
5074 } else
5075 ret = 0;
5076 /* this is the best we can do */
5077 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005078 } else {
5079 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005080 unsigned int avail;
5081 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5082 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5083 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5084 // This adjustment accounts for buffering after app processor.
5085 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005086 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005087 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005088
Weiyin Jiangd4633762018-03-16 12:05:03 +08005089 // Adjustment accounts for A2dp encoder latency with non offload usecases
5090 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5091 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5092 signed_frames -=
5093 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5094 }
5095
5096 // It would be unusual for this value to be negative, but check just in case ...
5097 if (signed_frames >= 0) {
5098 *frames = signed_frames;
5099 ret = 0;
5100 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005101 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305102 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305103 *frames = out->written;
5104 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305105 if (is_offload_usecase(out->usecase))
5106 ret = -EINVAL;
5107 else
5108 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005109 }
5110 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005111 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005112 return ret;
5113}
5114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005115static int out_set_callback(struct audio_stream_out *stream,
5116 stream_callback_t callback, void *cookie)
5117{
5118 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005119 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005120
5121 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005122 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005123 out->client_callback = callback;
5124 out->client_cookie = cookie;
5125 if (out->adsp_hdlr_stream_handle) {
5126 ret = audio_extn_adsp_hdlr_stream_set_callback(
5127 out->adsp_hdlr_stream_handle,
5128 callback,
5129 cookie);
5130 if (ret)
5131 ALOGW("%s:adsp hdlr callback registration failed %d",
5132 __func__, ret);
5133 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005134 pthread_mutex_unlock(&out->lock);
5135 return 0;
5136}
5137
5138static int out_pause(struct audio_stream_out* stream)
5139{
5140 struct stream_out *out = (struct stream_out *)stream;
5141 int status = -ENOSYS;
5142 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005143 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005144 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005145 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005146 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305147 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305148 status = compress_pause(out->compr);
5149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005150 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005151
Mingming Yin21854652016-04-13 11:54:02 -07005152 if (audio_extn_passthru_is_active()) {
5153 ALOGV("offload use case, pause passthru");
5154 audio_extn_passthru_on_pause(out);
5155 }
5156
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305157 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005158 audio_extn_dts_notify_playback_state(out->usecase, 0,
5159 out->sample_rate, popcount(out->channel_mask),
5160 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005161 }
5162 pthread_mutex_unlock(&out->lock);
5163 }
5164 return status;
5165}
5166
5167static int out_resume(struct audio_stream_out* stream)
5168{
5169 struct stream_out *out = (struct stream_out *)stream;
5170 int status = -ENOSYS;
5171 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005172 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005173 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005174 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005175 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005176 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305177 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305178 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005179 }
5180 if (!status) {
5181 out->offload_state = OFFLOAD_STATE_PLAYING;
5182 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305183 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005184 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5185 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005186 }
5187 pthread_mutex_unlock(&out->lock);
5188 }
5189 return status;
5190}
5191
5192static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5193{
5194 struct stream_out *out = (struct stream_out *)stream;
5195 int status = -ENOSYS;
5196 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005197 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005198 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005199 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5200 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5201 else
5202 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5203 pthread_mutex_unlock(&out->lock);
5204 }
5205 return status;
5206}
5207
5208static int out_flush(struct audio_stream_out* stream)
5209{
5210 struct stream_out *out = (struct stream_out *)stream;
5211 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005212 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005213 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005214 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005215 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5216 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005217 } else {
5218 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5219 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005220 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005221 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005222 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005223 return 0;
5224 }
5225 return -ENOSYS;
5226}
5227
Haynes Mathew George16081042017-05-31 17:16:49 -07005228static int out_stop(const struct audio_stream_out* stream)
5229{
5230 struct stream_out *out = (struct stream_out *)stream;
5231 struct audio_device *adev = out->dev;
5232 int ret = -ENOSYS;
5233
5234 ALOGV("%s", __func__);
5235 pthread_mutex_lock(&adev->lock);
5236 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5237 out->playback_started && out->pcm != NULL) {
5238 pcm_stop(out->pcm);
5239 ret = stop_output_stream(out);
5240 out->playback_started = false;
5241 }
5242 pthread_mutex_unlock(&adev->lock);
5243 return ret;
5244}
5245
5246static int out_start(const struct audio_stream_out* stream)
5247{
5248 struct stream_out *out = (struct stream_out *)stream;
5249 struct audio_device *adev = out->dev;
5250 int ret = -ENOSYS;
5251
5252 ALOGV("%s", __func__);
5253 pthread_mutex_lock(&adev->lock);
5254 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5255 !out->playback_started && out->pcm != NULL) {
5256 ret = start_output_stream(out);
5257 if (ret == 0) {
5258 out->playback_started = true;
5259 }
5260 }
5261 pthread_mutex_unlock(&adev->lock);
5262 return ret;
5263}
5264
5265/*
5266 * Modify config->period_count based on min_size_frames
5267 */
5268static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5269{
5270 int periodCountRequested = (min_size_frames + config->period_size - 1)
5271 / config->period_size;
5272 int periodCount = MMAP_PERIOD_COUNT_MIN;
5273
5274 ALOGV("%s original config.period_size = %d config.period_count = %d",
5275 __func__, config->period_size, config->period_count);
5276
5277 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5278 periodCount *= 2;
5279 }
5280 config->period_count = periodCount;
5281
5282 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5283}
5284
5285static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5286 int32_t min_size_frames,
5287 struct audio_mmap_buffer_info *info)
5288{
5289 struct stream_out *out = (struct stream_out *)stream;
5290 struct audio_device *adev = out->dev;
5291 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005292 unsigned int offset1 = 0;
5293 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005294 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005295 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005296 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005297
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005298 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305299 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005300 pthread_mutex_lock(&adev->lock);
5301
Sharad Sangle90e613f2018-05-04 16:15:38 +05305302 if (CARD_STATUS_OFFLINE == out->card_status ||
5303 CARD_STATUS_OFFLINE == adev->card_status) {
5304 ALOGW("out->card_status or adev->card_status offline, try again");
5305 ret = -EIO;
5306 goto exit;
5307 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005308 if (info == NULL || min_size_frames == 0) {
5309 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5310 ret = -EINVAL;
5311 goto exit;
5312 }
5313 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5314 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5315 ret = -ENOSYS;
5316 goto exit;
5317 }
5318 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5319 if (out->pcm_device_id < 0) {
5320 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5321 __func__, out->pcm_device_id, out->usecase);
5322 ret = -EINVAL;
5323 goto exit;
5324 }
5325
5326 adjust_mmap_period_count(&out->config, min_size_frames);
5327
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005328 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005329 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5330 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5331 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305332 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5333 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5334 out->card_status = CARD_STATUS_OFFLINE;
5335 adev->card_status = CARD_STATUS_OFFLINE;
5336 ret = -EIO;
5337 goto exit;
5338 }
5339
Haynes Mathew George16081042017-05-31 17:16:49 -07005340 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5341 step = "open";
5342 ret = -ENODEV;
5343 goto exit;
5344 }
5345 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5346 if (ret < 0) {
5347 step = "begin";
5348 goto exit;
5349 }
5350 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005351 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005352 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005353 ret = platform_get_mmap_data_fd(adev->platform,
5354 out->pcm_device_id, 0 /*playback*/,
5355 &info->shared_memory_fd,
5356 &mmap_size);
5357 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005358 // Fall back to non exclusive mode
5359 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5360 } else {
5361 if (mmap_size < buffer_size) {
5362 step = "mmap";
5363 goto exit;
5364 }
5365 // FIXME: indicate exclusive mode support by returning a negative buffer size
5366 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005367 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005368 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005369
5370 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5371 if (ret < 0) {
5372 step = "commit";
5373 goto exit;
5374 }
5375
5376 out->standby = false;
5377 ret = 0;
5378
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005379 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005380 __func__, info->shared_memory_address, info->buffer_size_frames);
5381
5382exit:
5383 if (ret != 0) {
5384 if (out->pcm == NULL) {
5385 ALOGE("%s: %s - %d", __func__, step, ret);
5386 } else {
5387 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5388 pcm_close(out->pcm);
5389 out->pcm = NULL;
5390 }
5391 }
5392 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305393 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005394 return ret;
5395}
5396
5397static int out_get_mmap_position(const struct audio_stream_out *stream,
5398 struct audio_mmap_position *position)
5399{
5400 struct stream_out *out = (struct stream_out *)stream;
5401 ALOGVV("%s", __func__);
5402 if (position == NULL) {
5403 return -EINVAL;
5404 }
5405 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005406 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005407 return -ENOSYS;
5408 }
5409 if (out->pcm == NULL) {
5410 return -ENOSYS;
5411 }
5412
5413 struct timespec ts = { 0, 0 };
5414 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5415 if (ret < 0) {
5416 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5417 return ret;
5418 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005419 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005420 return 0;
5421}
5422
5423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005424/** audio_stream_in implementation **/
5425static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5426{
5427 struct stream_in *in = (struct stream_in *)stream;
5428
5429 return in->config.rate;
5430}
5431
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005432static int in_set_sample_rate(struct audio_stream *stream __unused,
5433 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434{
5435 return -ENOSYS;
5436}
5437
5438static size_t in_get_buffer_size(const struct audio_stream *stream)
5439{
5440 struct stream_in *in = (struct stream_in *)stream;
5441
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005442 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5443 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005444 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5445 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 -07005446 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5447 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305448 else if(audio_extn_cin_attached_usecase(in->usecase))
5449 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005450
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005451 return in->config.period_size * in->af_period_multiplier *
5452 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453}
5454
5455static uint32_t in_get_channels(const struct audio_stream *stream)
5456{
5457 struct stream_in *in = (struct stream_in *)stream;
5458
5459 return in->channel_mask;
5460}
5461
5462static audio_format_t in_get_format(const struct audio_stream *stream)
5463{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005464 struct stream_in *in = (struct stream_in *)stream;
5465
5466 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467}
5468
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005469static int in_set_format(struct audio_stream *stream __unused,
5470 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005471{
5472 return -ENOSYS;
5473}
5474
5475static int in_standby(struct audio_stream *stream)
5476{
5477 struct stream_in *in = (struct stream_in *)stream;
5478 struct audio_device *adev = in->dev;
5479 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305480 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5481 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005482 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305483
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005484 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005485 if (!in->standby && in->is_st_session) {
5486 ALOGD("%s: sound trigger pcm stop lab", __func__);
5487 audio_extn_sound_trigger_stop_lab(in);
5488 in->standby = 1;
5489 }
5490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005491 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005492 if (adev->adm_deregister_stream)
5493 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5494
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005495 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005497 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005498 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005499 voice_extn_compress_voip_close_input_stream(stream);
5500 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005501 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5502 do_stop = in->capture_started;
5503 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005504 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305505 if (audio_extn_cin_attached_usecase(in->usecase))
5506 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005507 }
5508
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005509 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005510 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005511 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005512 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005513 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005514 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005515
5516 if (do_stop)
5517 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005518 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519 }
5520 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005521 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005522 return status;
5523}
5524
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005525static int in_dump(const struct audio_stream *stream __unused,
5526 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005527{
5528 return 0;
5529}
5530
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305531static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5532{
5533 if (!stream || !parms)
5534 return;
5535
5536 struct stream_in *in = (struct stream_in *)stream;
5537 struct audio_device *adev = in->dev;
5538
5539 card_status_t status;
5540 int card;
5541 if (parse_snd_card_status(parms, &card, &status) < 0)
5542 return;
5543
5544 pthread_mutex_lock(&adev->lock);
5545 bool valid_cb = (card == adev->snd_card);
5546 pthread_mutex_unlock(&adev->lock);
5547
5548 if (!valid_cb)
5549 return;
5550
5551 lock_input_stream(in);
5552 if (in->card_status != status)
5553 in->card_status = status;
5554 pthread_mutex_unlock(&in->lock);
5555
5556 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5557 use_case_table[in->usecase],
5558 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5559
5560 // a better solution would be to report error back to AF and let
5561 // it put the stream to standby
5562 if (status == CARD_STATUS_OFFLINE)
5563 in_standby(&in->stream.common);
5564
5565 return;
5566}
5567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5569{
5570 struct stream_in *in = (struct stream_in *)stream;
5571 struct audio_device *adev = in->dev;
5572 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005574 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305576 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005577 parms = str_parms_create_str(kvpairs);
5578
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305579 if (!parms)
5580 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005581 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005582 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005583
5584 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5585 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 val = atoi(value);
5587 /* no audio source uses val == 0 */
5588 if ((in->source != val) && (val != 0)) {
5589 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005590 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5591 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5592 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005593 (in->config.rate == 8000 || in->config.rate == 16000 ||
5594 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005595 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005596 err = voice_extn_compress_voip_open_input_stream(in);
5597 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005598 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005599 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005600 }
5601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 }
5603 }
5604
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005605 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5606 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005607 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005608 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5609
5610 // Workaround: If routing to an non existing usb device, fail gracefully
5611 // The routing request will otherwise block during 10 second
5612 int card;
5613 if (audio_is_usb_in_device(val) &&
5614 (card = get_alive_usb_card(parms)) >= 0) {
5615
5616 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5617 ret = -ENOSYS;
5618 } else {
5619
5620 in->device = val;
5621 /* If recording is in progress, change the tx device to new device */
5622 if (!in->standby && !in->is_st_session) {
5623 ALOGV("update input routing change");
5624 // inform adm before actual routing to prevent glitches.
5625 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005626 adev->adm_on_routing_change(adev->adm_data,
5627 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005628 ret = select_devices(adev, in->usecase);
5629 }
5630 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632 }
5633 }
5634
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305635 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5636 if (err >= 0) {
5637 strlcpy(in->profile, value, sizeof(in->profile));
5638 ALOGV("updating stream profile with value '%s'", in->profile);
5639 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5640 &adev->streams_input_cfg_list,
5641 in->device, in->flags, in->format,
5642 in->sample_rate, in->bit_width,
5643 in->profile, &in->app_type_cfg);
5644 }
5645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005646 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005647 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005648
5649 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305650error:
Eric Laurent994a6932013-07-17 11:51:42 -07005651 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005652 return ret;
5653}
5654
5655static char* in_get_parameters(const struct audio_stream *stream,
5656 const char *keys)
5657{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005658 struct stream_in *in = (struct stream_in *)stream;
5659 struct str_parms *query = str_parms_create_str(keys);
5660 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005661 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005662
5663 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005664 if (reply) {
5665 str_parms_destroy(reply);
5666 }
5667 if (query) {
5668 str_parms_destroy(query);
5669 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005670 ALOGE("in_get_parameters: failed to create query or reply");
5671 return NULL;
5672 }
5673
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005674 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005675
5676 voice_extn_in_get_parameters(in, query, reply);
5677
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005678 stream_get_parameter_channels(query, reply,
5679 &in->supported_channel_masks[0]);
5680 stream_get_parameter_formats(query, reply,
5681 &in->supported_formats[0]);
5682 stream_get_parameter_rates(query, reply,
5683 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005684 str = str_parms_to_str(reply);
5685 str_parms_destroy(query);
5686 str_parms_destroy(reply);
5687
5688 ALOGV("%s: exit: returns - %s", __func__, str);
5689 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005690}
5691
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005692static int in_set_gain(struct audio_stream_in *stream __unused,
5693 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005694{
5695 return 0;
5696}
5697
5698static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5699 size_t bytes)
5700{
5701 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305702
5703 if (in == NULL) {
5704 ALOGE("%s: stream_in ptr is NULL", __func__);
5705 return -EINVAL;
5706 }
5707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305709 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305710 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005711
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005712 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305713
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005714 if (in->is_st_session) {
5715 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5716 /* Read from sound trigger HAL */
5717 audio_extn_sound_trigger_read(in, buffer, bytes);
5718 pthread_mutex_unlock(&in->lock);
5719 return bytes;
5720 }
5721
Haynes Mathew George16081042017-05-31 17:16:49 -07005722 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5723 ret = -ENOSYS;
5724 goto exit;
5725 }
5726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005728 pthread_mutex_lock(&adev->lock);
5729 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5730 ret = voice_extn_compress_voip_start_input_stream(in);
5731 else
5732 ret = start_input_stream(in);
5733 pthread_mutex_unlock(&adev->lock);
5734 if (ret != 0) {
5735 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005736 }
5737 in->standby = 0;
5738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005739
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005740 // what's the duration requested by the client?
5741 long ns = 0;
5742
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305743 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005744 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5745 in->config.rate;
5746
5747 request_in_focus(in, ns);
5748 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005749
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305750 if (audio_extn_cin_attached_usecase(in->usecase)) {
5751 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5752 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305753 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005754 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305755 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005756 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005757 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005758 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005759 } else if (audio_extn_ffv_get_stream() == in) {
5760 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305761 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005762 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305763 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5764 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5765 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5766 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305767 ret = -EINVAL;
5768 goto exit;
5769 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305770 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305771 ret = -errno;
5772 }
5773 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305774 /* bytes read is always set to bytes for non compress usecases */
5775 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776 }
5777
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005778 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005780 /*
5781 * Instead of writing zeroes here, we could trust the hardware
5782 * to always provide zeroes when muted.
5783 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305784 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5785 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005786 memset(buffer, 0, bytes);
5787
5788exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005789 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305790 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005791 pthread_mutex_unlock(&in->lock);
5792
5793 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305794 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305795 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305796 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305797 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305798 in->standby = true;
5799 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305800 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5801 bytes_read = bytes;
5802 memset(buffer, 0, bytes);
5803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005805 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305806 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305807 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005808 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305809 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005810}
5811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005812static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005813{
5814 return 0;
5815}
5816
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005817static int add_remove_audio_effect(const struct audio_stream *stream,
5818 effect_handle_t effect,
5819 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005820{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005821 struct stream_in *in = (struct stream_in *)stream;
5822 int status = 0;
5823 effect_descriptor_t desc;
5824
5825 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005826 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5827
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005828 if (status != 0)
5829 return status;
5830
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005831 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005832 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005833 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5834 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005835 in->enable_aec != enable &&
5836 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5837 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005838 if (!in->standby) {
5839 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5840 select_devices(in->dev, in->usecase);
5841 }
5842
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005843 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005844 if (in->enable_ns != enable &&
5845 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5846 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005847 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005848 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5849 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005850 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5851 select_devices(in->dev, in->usecase);
5852 } else
5853 select_devices(in->dev, in->usecase);
5854 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005855 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005856 pthread_mutex_unlock(&in->dev->lock);
5857 pthread_mutex_unlock(&in->lock);
5858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005859 return 0;
5860}
5861
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005862static int in_add_audio_effect(const struct audio_stream *stream,
5863 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005864{
Eric Laurent994a6932013-07-17 11:51:42 -07005865 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005866 return add_remove_audio_effect(stream, effect, true);
5867}
5868
5869static int in_remove_audio_effect(const struct audio_stream *stream,
5870 effect_handle_t effect)
5871{
Eric Laurent994a6932013-07-17 11:51:42 -07005872 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005873 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005874}
5875
Haynes Mathew George16081042017-05-31 17:16:49 -07005876static int in_stop(const struct audio_stream_in* stream)
5877{
5878 struct stream_in *in = (struct stream_in *)stream;
5879 struct audio_device *adev = in->dev;
5880
5881 int ret = -ENOSYS;
5882 ALOGV("%s", __func__);
5883 pthread_mutex_lock(&adev->lock);
5884 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5885 in->capture_started && in->pcm != NULL) {
5886 pcm_stop(in->pcm);
5887 ret = stop_input_stream(in);
5888 in->capture_started = false;
5889 }
5890 pthread_mutex_unlock(&adev->lock);
5891 return ret;
5892}
5893
5894static int in_start(const struct audio_stream_in* stream)
5895{
5896 struct stream_in *in = (struct stream_in *)stream;
5897 struct audio_device *adev = in->dev;
5898 int ret = -ENOSYS;
5899
5900 ALOGV("%s in %p", __func__, in);
5901 pthread_mutex_lock(&adev->lock);
5902 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5903 !in->capture_started && in->pcm != NULL) {
5904 if (!in->capture_started) {
5905 ret = start_input_stream(in);
5906 if (ret == 0) {
5907 in->capture_started = true;
5908 }
5909 }
5910 }
5911 pthread_mutex_unlock(&adev->lock);
5912 return ret;
5913}
5914
5915static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5916 int32_t min_size_frames,
5917 struct audio_mmap_buffer_info *info)
5918{
5919 struct stream_in *in = (struct stream_in *)stream;
5920 struct audio_device *adev = in->dev;
5921 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005922 unsigned int offset1 = 0;
5923 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005924 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005925 uint32_t mmap_size = 0;
5926 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005927
5928 pthread_mutex_lock(&adev->lock);
5929 ALOGV("%s in %p", __func__, in);
5930
Sharad Sangle90e613f2018-05-04 16:15:38 +05305931 if (CARD_STATUS_OFFLINE == in->card_status||
5932 CARD_STATUS_OFFLINE == adev->card_status) {
5933 ALOGW("in->card_status or adev->card_status offline, try again");
5934 ret = -EIO;
5935 goto exit;
5936 }
5937
Haynes Mathew George16081042017-05-31 17:16:49 -07005938 if (info == NULL || min_size_frames == 0) {
5939 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5940 ret = -EINVAL;
5941 goto exit;
5942 }
5943 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5944 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5945 ALOGV("%s in %p", __func__, in);
5946 ret = -ENOSYS;
5947 goto exit;
5948 }
5949 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5950 if (in->pcm_device_id < 0) {
5951 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5952 __func__, in->pcm_device_id, in->usecase);
5953 ret = -EINVAL;
5954 goto exit;
5955 }
5956
5957 adjust_mmap_period_count(&in->config, min_size_frames);
5958
5959 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5960 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5961 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5962 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305963 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
5964 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5965 in->card_status = CARD_STATUS_OFFLINE;
5966 adev->card_status = CARD_STATUS_OFFLINE;
5967 ret = -EIO;
5968 goto exit;
5969 }
5970
Haynes Mathew George16081042017-05-31 17:16:49 -07005971 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5972 step = "open";
5973 ret = -ENODEV;
5974 goto exit;
5975 }
5976
5977 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5978 if (ret < 0) {
5979 step = "begin";
5980 goto exit;
5981 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005982
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005983 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5984 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
5985 info->burst_size_frames = in->config.period_size;
5986 ret = platform_get_mmap_data_fd(adev->platform,
5987 in->pcm_device_id, 1 /*capture*/,
5988 &info->shared_memory_fd,
5989 &mmap_size);
5990 if (ret < 0) {
5991 // Fall back to non exclusive mode
5992 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5993 } else {
5994 if (mmap_size < buffer_size) {
5995 step = "mmap";
5996 goto exit;
5997 }
5998 // FIXME: indicate exclusive mode support by returning a negative buffer size
5999 info->buffer_size_frames *= -1;
6000 }
6001
6002 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006003
6004 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6005 if (ret < 0) {
6006 step = "commit";
6007 goto exit;
6008 }
6009
6010 in->standby = false;
6011 ret = 0;
6012
6013 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6014 __func__, info->shared_memory_address, info->buffer_size_frames);
6015
6016exit:
6017 if (ret != 0) {
6018 if (in->pcm == NULL) {
6019 ALOGE("%s: %s - %d", __func__, step, ret);
6020 } else {
6021 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6022 pcm_close(in->pcm);
6023 in->pcm = NULL;
6024 }
6025 }
6026 pthread_mutex_unlock(&adev->lock);
6027 return ret;
6028}
6029
6030static int in_get_mmap_position(const struct audio_stream_in *stream,
6031 struct audio_mmap_position *position)
6032{
6033 struct stream_in *in = (struct stream_in *)stream;
6034 ALOGVV("%s", __func__);
6035 if (position == NULL) {
6036 return -EINVAL;
6037 }
6038 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6039 return -ENOSYS;
6040 }
6041 if (in->pcm == NULL) {
6042 return -ENOSYS;
6043 }
6044 struct timespec ts = { 0, 0 };
6045 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6046 if (ret < 0) {
6047 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6048 return ret;
6049 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05306050 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006051 return 0;
6052}
6053
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306054static int in_get_active_microphones(const struct audio_stream_in *stream,
6055 struct audio_microphone_characteristic_t *mic_array,
6056 size_t *mic_count) {
6057 struct stream_in *in = (struct stream_in *)stream;
6058 struct audio_device *adev = in->dev;
6059 ALOGVV("%s", __func__);
6060
6061 lock_input_stream(in);
6062 pthread_mutex_lock(&adev->lock);
6063 int ret = platform_get_active_microphones(adev->platform,
6064 audio_channel_count_from_in_mask(in->channel_mask),
6065 in->usecase, mic_array, mic_count);
6066 pthread_mutex_unlock(&adev->lock);
6067 pthread_mutex_unlock(&in->lock);
6068
6069 return ret;
6070}
6071
6072static int adev_get_microphones(const struct audio_hw_device *dev,
6073 struct audio_microphone_characteristic_t *mic_array,
6074 size_t *mic_count) {
6075 struct audio_device *adev = (struct audio_device *)dev;
6076 ALOGVV("%s", __func__);
6077
6078 pthread_mutex_lock(&adev->lock);
6079 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6080 pthread_mutex_unlock(&adev->lock);
6081
6082 return ret;
6083}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306084int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006085 audio_io_handle_t handle,
6086 audio_devices_t devices,
6087 audio_output_flags_t flags,
6088 struct audio_config *config,
6089 struct audio_stream_out **stream_out,
6090 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006091{
6092 struct audio_device *adev = (struct audio_device *)dev;
6093 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306094 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006095 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006096 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306097 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006098 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6099 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6100 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6101 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006102
kunleizdff872d2018-08-20 14:40:33 +08006103 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006104 is_usb_dev = false;
6105 devices = AUDIO_DEVICE_OUT_SPEAKER;
6106 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6107 __func__, devices);
6108 }
6109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006110 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006112 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6113
Mingming Yin3a941d42016-02-17 18:08:05 -08006114 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6115 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306116 devices, flags, &out->stream);
6117
6118
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006119 if (!out) {
6120 return -ENOMEM;
6121 }
6122
Haynes Mathew George204045b2015-02-25 20:32:03 -08006123 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006124 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306125 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006126 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006127 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006129 if (devices == AUDIO_DEVICE_NONE)
6130 devices = AUDIO_DEVICE_OUT_SPEAKER;
6131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132 out->flags = flags;
6133 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006134 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006135 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006136 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306137 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306138 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6139 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6140 else
6141 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006142 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006143 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006144 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306145 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306146 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306147 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006148 out->hal_output_suspend_supported = 0;
6149 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306150 out->set_dual_mono = false;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05306151 out->prev_card_status_offline = false;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05306152 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306154 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306155 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006156 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6157
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006158 if (audio_is_linear_pcm(out->format) &&
6159 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6160 pthread_mutex_lock(&adev->lock);
6161 if (is_hdmi) {
6162 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6163 ret = read_hdmi_sink_caps(out);
6164 } else if (is_usb_dev) {
6165 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6166 &config->format,
6167 &out->supported_formats[0],
6168 MAX_SUPPORTED_FORMATS,
6169 &config->channel_mask,
6170 &out->supported_channel_masks[0],
6171 MAX_SUPPORTED_CHANNEL_MASKS,
6172 &config->sample_rate,
6173 &out->supported_sample_rates[0],
6174 MAX_SUPPORTED_SAMPLE_RATES);
6175 ALOGV("plugged dev USB ret %d", ret);
6176 } else {
6177 ret = -1;
6178 }
6179 pthread_mutex_unlock(&adev->lock);
6180 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006181 if (ret == -ENOSYS) {
6182 /* ignore and go with default */
6183 ret = 0;
6184 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006185 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006186 goto error_open;
6187 }
6188 }
6189 }
6190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006191 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006192#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006193 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6194 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6195 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6196 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6197 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6198 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6199
6200 out->config = default_pcm_config_voip_copp;
6201 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6202 out->config.rate = out->sample_rate;
6203
6204#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306205 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006206 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006207 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006208 ret = voice_extn_compress_voip_open_output_stream(out);
6209 if (ret != 0) {
6210 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6211 __func__, ret);
6212 goto error_open;
6213 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006214#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006215 } else if (audio_is_linear_pcm(out->format) &&
6216 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6217 out->channel_mask = config->channel_mask;
6218 out->sample_rate = config->sample_rate;
6219 out->format = config->format;
6220 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6221 // does this change?
6222 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6223 out->config.rate = config->sample_rate;
6224 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6225 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6226 audio_bytes_per_sample(config->format));
6227 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006228 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306229 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306230 pthread_mutex_lock(&adev->lock);
6231 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6232 pthread_mutex_unlock(&adev->lock);
6233
6234 // reject offload during card offline to allow
6235 // fallback to s/w paths
6236 if (offline) {
6237 ret = -ENODEV;
6238 goto error_open;
6239 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006241 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6242 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6243 ALOGE("%s: Unsupported Offload information", __func__);
6244 ret = -EINVAL;
6245 goto error_open;
6246 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006247
Atul Khare3fa6e542017-08-09 00:56:17 +05306248 if (config->offload_info.format == 0)
6249 config->offload_info.format = config->format;
6250 if (config->offload_info.sample_rate == 0)
6251 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006252
Mingming Yin90310102013-11-13 16:57:00 -08006253 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306254 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006255 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006256 ret = -EINVAL;
6257 goto error_open;
6258 }
6259
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006260 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6261 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6262 (audio_extn_passthru_is_passthrough_stream(out)) &&
6263 !((config->sample_rate == 48000) ||
6264 (config->sample_rate == 96000) ||
6265 (config->sample_rate == 192000))) {
6266 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6267 __func__, config->sample_rate, config->offload_info.format);
6268 ret = -EINVAL;
6269 goto error_open;
6270 }
6271
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006272 out->compr_config.codec = (struct snd_codec *)
6273 calloc(1, sizeof(struct snd_codec));
6274
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006275 if (!out->compr_config.codec) {
6276 ret = -ENOMEM;
6277 goto error_open;
6278 }
6279
Dhananjay Kumarac341582017-02-23 23:42:25 +05306280 out->stream.pause = out_pause;
6281 out->stream.resume = out_resume;
6282 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306283 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306284 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006285 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306286 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006287 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306288 } else {
6289 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6290 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006291 }
vivek mehta446c3962015-09-14 10:57:35 -07006292
6293 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006294 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6295 config->format == 0 && config->sample_rate == 0 &&
6296 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006297 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006298 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6299 } else {
6300 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6301 ret = -EEXIST;
6302 goto error_open;
6303 }
vivek mehta446c3962015-09-14 10:57:35 -07006304 }
6305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006306 if (config->offload_info.channel_mask)
6307 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006308 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006309 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006310 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006311 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306312 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006313 ret = -EINVAL;
6314 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006315 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006316
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006317 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006318 out->sample_rate = config->offload_info.sample_rate;
6319
Mingming Yin3ee55c62014-08-04 14:23:35 -07006320 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006321
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306322 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306323 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306324 audio_extn_dolby_send_ddp_endp_params(adev);
6325 audio_extn_dolby_set_dmid(adev);
6326 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006327
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006328 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006329 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006330 out->compr_config.codec->bit_rate =
6331 config->offload_info.bit_rate;
6332 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306333 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006334 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306335 /* Update bit width only for non passthrough usecases.
6336 * For passthrough usecases, the output will always be opened @16 bit
6337 */
6338 if (!audio_extn_passthru_is_passthrough_stream(out))
6339 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306340
6341 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6342 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6343 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6344
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006345 /*TODO: Do we need to change it for passthrough */
6346 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006347
Manish Dewangana6fc5442015-08-24 20:30:31 +05306348 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6349 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306350 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306351 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306352 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6353 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306354
6355 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6356 AUDIO_FORMAT_PCM) {
6357
6358 /*Based on platform support, configure appropriate alsa format for corresponding
6359 *hal input format.
6360 */
6361 out->compr_config.codec->format = hal_format_to_alsa(
6362 config->offload_info.format);
6363
Ashish Jain83a6cc22016-06-28 14:34:17 +05306364 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306365 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306366 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306367
Dhananjay Kumarac341582017-02-23 23:42:25 +05306368 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306369 *hal input format and alsa format might differ based on platform support.
6370 */
6371 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306372 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306373
6374 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6375
6376 /* Check if alsa session is configured with the same format as HAL input format,
6377 * if not then derive correct fragment size needed to accomodate the
6378 * conversion of HAL input format to alsa format.
6379 */
6380 audio_extn_utils_update_direct_pcm_fragment_size(out);
6381
6382 /*if hal input and output fragment size is different this indicates HAL input format is
6383 *not same as the alsa format
6384 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306385 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306386 /*Allocate a buffer to convert input data to the alsa configured format.
6387 *size of convert buffer is equal to the size required to hold one fragment size
6388 *worth of pcm data, this is because flinger does not write more than fragment_size
6389 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306390 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6391 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306392 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6393 ret = -ENOMEM;
6394 goto error_open;
6395 }
6396 }
6397 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6398 out->compr_config.fragment_size =
6399 audio_extn_passthru_get_buffer_size(&config->offload_info);
6400 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6401 } else {
6402 out->compr_config.fragment_size =
6403 platform_get_compress_offload_buffer_size(&config->offload_info);
6404 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6405 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006406
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306407 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6408 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6409 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006410 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306411 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006412
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306413 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6414 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6415 }
6416
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006417 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6418 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006419
Manish Dewangan69426c82017-01-30 17:35:36 +05306420 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6421 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6422 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6423 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6424 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6425 } else {
6426 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6427 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006428
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306429 memset(&out->channel_map_param, 0,
6430 sizeof(struct audio_out_channel_map_param));
6431
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006432 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306433 out->send_next_track_params = false;
6434 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006435 out->offload_state = OFFLOAD_STATE_IDLE;
6436 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006437 out->writeAt.tv_sec = 0;
6438 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006439
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006440 audio_extn_dts_create_state_notifier_node(out->usecase);
6441
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006442 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6443 __func__, config->offload_info.version,
6444 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306445
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306446 /* Check if DSD audio format is supported in codec
6447 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306448 */
6449
6450 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306451 (!platform_check_codec_dsd_support(adev->platform) ||
6452 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306453 ret = -EINVAL;
6454 goto error_open;
6455 }
6456
Ashish Jain5106d362016-05-11 19:23:33 +05306457 /* Disable gapless if any of the following is true
6458 * passthrough playback
6459 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306460 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306461 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306462 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306463 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006464 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306465 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306466 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306467 check_and_set_gapless_mode(adev, false);
6468 } else
6469 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006470
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306471 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006472 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6473 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306474 if (config->format == AUDIO_FORMAT_DSD) {
6475 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6476 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6477 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006478
6479 create_offload_callback_thread(out);
6480
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006481 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006482 switch (config->sample_rate) {
6483 case 0:
6484 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6485 break;
6486 case 8000:
6487 case 16000:
6488 case 48000:
6489 out->sample_rate = config->sample_rate;
6490 break;
6491 default:
6492 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6493 config->sample_rate);
6494 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6495 ret = -EINVAL;
6496 goto error_open;
6497 }
6498 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6499 switch (config->channel_mask) {
6500 case AUDIO_CHANNEL_NONE:
6501 case AUDIO_CHANNEL_OUT_STEREO:
6502 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6503 break;
6504 default:
6505 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6506 config->channel_mask);
6507 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6508 ret = -EINVAL;
6509 goto error_open;
6510 }
6511 switch (config->format) {
6512 case AUDIO_FORMAT_DEFAULT:
6513 case AUDIO_FORMAT_PCM_16_BIT:
6514 out->format = AUDIO_FORMAT_PCM_16_BIT;
6515 break;
6516 default:
6517 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6518 config->format);
6519 config->format = AUDIO_FORMAT_PCM_16_BIT;
6520 ret = -EINVAL;
6521 goto error_open;
6522 }
6523
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306524 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006525 if (ret != 0) {
6526 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006527 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006528 goto error_open;
6529 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006530 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006531 if (config->sample_rate == 0)
6532 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6533 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6534 config->sample_rate != 8000) {
6535 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6536 ret = -EINVAL;
6537 goto error_open;
6538 }
6539 out->sample_rate = config->sample_rate;
6540 out->config.rate = config->sample_rate;
6541 if (config->format == AUDIO_FORMAT_DEFAULT)
6542 config->format = AUDIO_FORMAT_PCM_16_BIT;
6543 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6544 config->format = AUDIO_FORMAT_PCM_16_BIT;
6545 ret = -EINVAL;
6546 goto error_open;
6547 }
6548 out->format = config->format;
6549 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6550 out->config = pcm_config_afe_proxy_playback;
6551 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006552 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306553 unsigned int channels = 0;
6554 /*Update config params to default if not set by the caller*/
6555 if (config->sample_rate == 0)
6556 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6557 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6558 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6559 if (config->format == AUDIO_FORMAT_DEFAULT)
6560 config->format = AUDIO_FORMAT_PCM_16_BIT;
6561
6562 channels = audio_channel_count_from_out_mask(out->channel_mask);
6563
Varun Balaraje49253e2017-07-06 19:48:56 +05306564 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6565 out->usecase = get_interactive_usecase(adev);
6566 out->config = pcm_config_low_latency;
6567 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306568 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006569 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6570 out->flags);
6571 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006572 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6573 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6574 out->config = pcm_config_mmap_playback;
6575 out->stream.start = out_start;
6576 out->stream.stop = out_stop;
6577 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6578 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306579 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6580 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006581 out->hal_output_suspend_supported =
6582 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6583 out->dynamic_pm_qos_config_supported =
6584 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6585 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006586 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6587 } else {
6588 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6589 //the mixer path will be a string similar to "low-latency-playback resume"
6590 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6591 strlcat(out->pm_qos_mixer_path,
6592 " resume", MAX_MIXER_PATH_LEN);
6593 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6594 out->pm_qos_mixer_path);
6595 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306596 out->config = pcm_config_low_latency;
6597 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6598 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6599 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306600 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6601 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6602 if (out->config.period_size <= 0) {
6603 ALOGE("Invalid configuration period size is not valid");
6604 ret = -EINVAL;
6605 goto error_open;
6606 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306607 } else {
6608 /* primary path is the default path selected if no other outputs are available/suitable */
6609 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6610 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6611 }
6612 out->hal_ip_format = format = out->format;
6613 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6614 out->hal_op_format = pcm_format_to_hal(out->config.format);
6615 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6616 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006617 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306618 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306619 if (out->hal_ip_format != out->hal_op_format) {
6620 uint32_t buffer_size = out->config.period_size *
6621 format_to_bitwidth_table[out->hal_op_format] *
6622 out->config.channels;
6623 out->convert_buffer = calloc(1, buffer_size);
6624 if (out->convert_buffer == NULL){
6625 ALOGE("Allocation failed for convert buffer for size %d",
6626 out->compr_config.fragment_size);
6627 ret = -ENOMEM;
6628 goto error_open;
6629 }
6630 ALOGD("Convert buffer allocated of size %d", buffer_size);
6631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006632 }
6633
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006634 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6635 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306636
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006637 /* TODO remove this hardcoding and check why width is zero*/
6638 if (out->bit_width == 0)
6639 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306640 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006641 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006642 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306643 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306644 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006645 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6646 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6647 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006648 if(adev->primary_output == NULL)
6649 adev->primary_output = out;
6650 else {
6651 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006652 ret = -EEXIST;
6653 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006654 }
6655 }
6656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006657 /* Check if this usecase is already existing */
6658 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006659 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6660 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006661 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006662 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006663 ret = -EEXIST;
6664 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006665 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006667 pthread_mutex_unlock(&adev->lock);
6668
6669 out->stream.common.get_sample_rate = out_get_sample_rate;
6670 out->stream.common.set_sample_rate = out_set_sample_rate;
6671 out->stream.common.get_buffer_size = out_get_buffer_size;
6672 out->stream.common.get_channels = out_get_channels;
6673 out->stream.common.get_format = out_get_format;
6674 out->stream.common.set_format = out_set_format;
6675 out->stream.common.standby = out_standby;
6676 out->stream.common.dump = out_dump;
6677 out->stream.common.set_parameters = out_set_parameters;
6678 out->stream.common.get_parameters = out_get_parameters;
6679 out->stream.common.add_audio_effect = out_add_audio_effect;
6680 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6681 out->stream.get_latency = out_get_latency;
6682 out->stream.set_volume = out_set_volume;
6683 out->stream.write = out_write;
6684 out->stream.get_render_position = out_get_render_position;
6685 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006686 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006687
Haynes Mathew George16081042017-05-31 17:16:49 -07006688 if (out->realtime)
6689 out->af_period_multiplier = af_period_multiplier;
6690 else
6691 out->af_period_multiplier = 1;
6692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006693 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006694 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006695 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006696
6697 config->format = out->stream.common.get_format(&out->stream.common);
6698 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6699 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306700 register_format(out->format, out->supported_formats);
6701 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6702 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306704 /*
6705 By locking output stream before registering, we allow the callback
6706 to update stream's state only after stream's initial state is set to
6707 adev state.
6708 */
6709 lock_output_stream(out);
6710 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6711 pthread_mutex_lock(&adev->lock);
6712 out->card_status = adev->card_status;
6713 pthread_mutex_unlock(&adev->lock);
6714 pthread_mutex_unlock(&out->lock);
6715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006716 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306717 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006718 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006719
6720 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6721 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6722 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006723 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306724 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006725 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006726 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306727 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006728 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6729 out->usecase, PCM_PLAYBACK);
6730 hdlr_stream_cfg.flags = out->flags;
6731 hdlr_stream_cfg.type = PCM_PLAYBACK;
6732 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6733 &hdlr_stream_cfg);
6734 if (ret) {
6735 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6736 out->adsp_hdlr_stream_handle = NULL;
6737 }
6738 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306739 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006740 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006741 if (ret < 0) {
6742 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6743 out->ip_hdlr_handle = NULL;
6744 }
6745 }
Eric Laurent994a6932013-07-17 11:51:42 -07006746 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006747 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006748
6749error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306750 if (out->convert_buffer)
6751 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006752 free(out);
6753 *stream_out = NULL;
6754 ALOGD("%s: exit: ret %d", __func__, ret);
6755 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006756}
6757
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306758void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006759 struct audio_stream_out *stream)
6760{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006761 struct stream_out *out = (struct stream_out *)stream;
6762 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006763 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006764
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006765 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306766
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306767 // must deregister from sndmonitor first to prevent races
6768 // between the callback and close_stream
6769 audio_extn_snd_mon_unregister_listener(out);
6770
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006771 /* close adsp hdrl session before standby */
6772 if (out->adsp_hdlr_stream_handle) {
6773 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6774 if (ret)
6775 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6776 out->adsp_hdlr_stream_handle = NULL;
6777 }
6778
Manish Dewangan21a850a2017-08-14 12:03:55 +05306779 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006780 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6781 out->ip_hdlr_handle = NULL;
6782 }
6783
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006784 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306785 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006786 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306787 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306788 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006789 if(ret != 0)
6790 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6791 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006792 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006793 out_standby(&stream->common);
6794
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006795 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006796 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006797 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006798 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006799 if (out->compr_config.codec != NULL)
6800 free(out->compr_config.codec);
6801 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006802
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306803 out->a2dp_compress_mute = false;
6804
Varun Balaraje49253e2017-07-06 19:48:56 +05306805 if (is_interactive_usecase(out->usecase))
6806 free_interactive_usecase(adev, out->usecase);
6807
Ashish Jain83a6cc22016-06-28 14:34:17 +05306808 if (out->convert_buffer != NULL) {
6809 free(out->convert_buffer);
6810 out->convert_buffer = NULL;
6811 }
6812
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006813 if (adev->voice_tx_output == out)
6814 adev->voice_tx_output = NULL;
6815
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306816 if (adev->primary_output == out)
6817 adev->primary_output = NULL;
6818
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006819 pthread_cond_destroy(&out->cond);
6820 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006821 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006822 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006823}
6824
6825static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6826{
6827 struct audio_device *adev = (struct audio_device *)dev;
6828 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006829 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006830 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006831 int ret;
6832 int status = 0;
Zhou Songa32012a2019-05-21 18:08:51 +08006833 struct listnode *node;
6834 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006836 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006837 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006838
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306839 if (!parms)
6840 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306841
Zhou Songa32012a2019-05-21 18:08:51 +08006842 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306843 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6844 if (ret >= 0) {
6845 /* When set to false, HAL should disable EC and NS */
Zhou Songa32012a2019-05-21 18:08:51 +08006846 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306847 adev->bt_sco_on = true;
Zhou Songa32012a2019-05-21 18:08:51 +08006848 } else {
6849 ALOGD("route device to handset/mic when sco is off");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306850 adev->bt_sco_on = false;
Zhou Songa32012a2019-05-21 18:08:51 +08006851 list_for_each(node, &adev->usecase_list) {
6852 usecase = node_to_item(node, struct audio_usecase, list);
6853 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
6854 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
6855 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
6856 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
6857 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
6858 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
6859 else
6860 continue;
6861 select_devices(adev, usecase->id);
6862 }
6863 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306864 }
6865
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006866 status = voice_set_parameters(adev, parms);
6867 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006868 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006870 status = platform_set_parameters(adev->platform, parms);
6871 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006872 goto done;
6873
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006874 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6875 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006876 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6878 adev->bluetooth_nrec = true;
6879 else
6880 adev->bluetooth_nrec = false;
6881 }
6882
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006883 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6884 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006885 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6886 adev->screen_off = false;
6887 else
6888 adev->screen_off = true;
6889 }
6890
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006891 ret = str_parms_get_int(parms, "rotation", &val);
6892 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006893 bool reverse_speakers = false;
6894 switch(val) {
6895 // FIXME: note that the code below assumes that the speakers are in the correct placement
6896 // relative to the user when the device is rotated 90deg from its default rotation. This
6897 // assumption is device-specific, not platform-specific like this code.
6898 case 270:
6899 reverse_speakers = true;
6900 break;
6901 case 0:
6902 case 90:
6903 case 180:
6904 break;
6905 default:
6906 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006907 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006908 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006909 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006910 // check and set swap
6911 // - check if orientation changed and speaker active
6912 // - set rotation and cache the rotation value
6913 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006914 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006915 }
6916
Mingming Yin514a8bc2014-07-29 15:22:21 -07006917 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6918 if (ret >= 0) {
6919 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6920 adev->bt_wb_speech_enabled = true;
6921 else
6922 adev->bt_wb_speech_enabled = false;
6923 }
6924
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006925 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6926 if (ret >= 0) {
6927 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306928 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006929 if (audio_is_output_device(val) &&
6930 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006931 ALOGV("cache new ext disp type and edid");
6932 ret = platform_get_ext_disp_type(adev->platform);
6933 if (ret < 0) {
6934 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306935 } else {
6936 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006937 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306938 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006939 /*
6940 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6941 * Per AudioPolicyManager, USB device is higher priority than WFD.
6942 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6943 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6944 * starting voice call on USB
6945 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006946 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306947 if (ret >= 0)
6948 audio_extn_usb_add_device(device, atoi(value));
6949
Zhou Song6f862822017-11-06 17:27:57 +08006950 if (!audio_extn_usb_is_tunnel_supported()) {
6951 ALOGV("detected USB connect .. disable proxy");
6952 adev->allow_afe_proxy_usage = false;
6953 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006954 }
6955 }
6956
6957 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6958 if (ret >= 0) {
6959 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306960 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006961 /*
6962 * The HDMI / Displayport disconnect handling has been moved to
6963 * audio extension to ensure that its parameters are not
6964 * invalidated prior to updating sysfs of the disconnect event
6965 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6966 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306967 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006968 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306969 if (ret >= 0)
6970 audio_extn_usb_remove_device(device, atoi(value));
6971
Zhou Song6f862822017-11-06 17:27:57 +08006972 if (!audio_extn_usb_is_tunnel_supported()) {
6973 ALOGV("detected USB disconnect .. enable proxy");
6974 adev->allow_afe_proxy_usage = true;
6975 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006976 }
6977 }
6978
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306979 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6980 if (ret >= 0) {
6981 struct audio_usecase *usecase;
6982 struct listnode *node;
6983 list_for_each(node, &adev->usecase_list) {
6984 usecase = node_to_item(node, struct audio_usecase, list);
6985 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006986 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306987 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006988
6989 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306990 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006991 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306992 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306993 //force device switch to re configure encoder
6994 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306995 audio_extn_a2dp_set_handoff_mode(false);
6996 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306997 break;
6998 }
6999 }
7000 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007001
7002 //handle vr audio setparam
7003 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7004 value, sizeof(value));
7005 if (ret >= 0) {
7006 ALOGI("Setting vr mode to be %s", value);
7007 if (!strncmp(value, "true", 4)) {
7008 adev->vr_audio_mode_enabled = true;
7009 ALOGI("Setting vr mode to true");
7010 } else if (!strncmp(value, "false", 5)) {
7011 adev->vr_audio_mode_enabled = false;
7012 ALOGI("Setting vr mode to false");
7013 } else {
7014 ALOGI("wrong vr mode set");
7015 }
7016 }
7017
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307018 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007019done:
7020 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007021 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307022error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007023 ALOGV("%s: exit with code(%d)", __func__, status);
7024 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025}
7026
7027static char* adev_get_parameters(const struct audio_hw_device *dev,
7028 const char *keys)
7029{
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307030 ALOGD("%s:%s", __func__, keys);
7031
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007032 struct audio_device *adev = (struct audio_device *)dev;
7033 struct str_parms *reply = str_parms_create();
7034 struct str_parms *query = str_parms_create_str(keys);
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307035
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007036 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307037 char value[256] = {0};
7038 int ret = 0;
7039
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007040 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007041 if (reply) {
7042 str_parms_destroy(reply);
7043 }
7044 if (query) {
7045 str_parms_destroy(query);
7046 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007047 ALOGE("adev_get_parameters: failed to create query or reply");
7048 return NULL;
7049 }
7050
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007051 //handle vr audio getparam
7052
7053 ret = str_parms_get_str(query,
7054 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7055 value, sizeof(value));
7056
7057 if (ret >= 0) {
7058 bool vr_audio_enabled = false;
7059 pthread_mutex_lock(&adev->lock);
7060 vr_audio_enabled = adev->vr_audio_mode_enabled;
7061 pthread_mutex_unlock(&adev->lock);
7062
7063 ALOGI("getting vr mode to %d", vr_audio_enabled);
7064
7065 if (vr_audio_enabled) {
7066 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7067 "true");
7068 goto exit;
7069 } else {
7070 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7071 "false");
7072 goto exit;
7073 }
7074 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007075
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007076 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007077 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007078 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007079 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307080 pthread_mutex_unlock(&adev->lock);
7081
Naresh Tannirud7205b62014-06-20 02:54:48 +05307082exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007083 str = str_parms_to_str(reply);
7084 str_parms_destroy(query);
7085 str_parms_destroy(reply);
7086
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307087 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007088 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089}
7090
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007091static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092{
7093 return 0;
7094}
7095
7096static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7097{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007098 int ret;
7099 struct audio_device *adev = (struct audio_device *)dev;
7100 pthread_mutex_lock(&adev->lock);
7101 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007102 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007103 pthread_mutex_unlock(&adev->lock);
7104 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007105}
7106
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007107static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7108 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007109{
7110 return -ENOSYS;
7111}
7112
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007113static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7114 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115{
7116 return -ENOSYS;
7117}
7118
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007119static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7120 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007121{
7122 return -ENOSYS;
7123}
7124
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007125static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7126 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007127{
7128 return -ENOSYS;
7129}
7130
7131static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7132{
7133 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007134 struct listnode *node;
7135 struct audio_usecase *usecase = NULL;
7136 int ret = 0;
kunleiz60c17e72017-05-04 12:15:35 +08007137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138 pthread_mutex_lock(&adev->lock);
7139 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007140 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007141 adev->mode = mode;
Kunlei Zhang0eab0432019-05-21 14:25:57 +08007142 if (voice_is_in_call(adev) &&
7143 (mode == AUDIO_MODE_NORMAL ||
7144 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007145 list_for_each(node, &adev->usecase_list) {
7146 usecase = node_to_item(node, struct audio_usecase, list);
7147 if (usecase->type == VOICE_CALL)
7148 break;
7149 }
7150 if (usecase &&
7151 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7152 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7153 true);
7154 if (ret != 0) {
7155 /* default service interval was successfully updated,
7156 reopen USB backend with new service interval */
7157 check_usecases_codec_backend(adev,
7158 usecase,
7159 usecase->out_snd_device);
7160 }
7161 }
7162
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007163 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007164 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007165 adev->current_call_output = NULL;
kunleiz60c17e72017-05-04 12:15:35 +08007166 // restore device for other active usecases after stop call
7167 list_for_each(node, &adev->usecase_list) {
7168 usecase = node_to_item(node, struct audio_usecase, list);
7169 select_devices(adev, usecase->id);
7170 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007171 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007172 }
7173 pthread_mutex_unlock(&adev->lock);
7174 return 0;
7175}
7176
7177static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7178{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007179 int ret;
7180
7181 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007182 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007183 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007184 if (adev->ext_hw_plugin)
7185 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007186 pthread_mutex_unlock(&adev->lock);
7187
7188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007189}
7190
7191static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7192{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007193 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007194 return 0;
7195}
7196
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007197static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007198 const struct audio_config *config)
7199{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007200 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007202 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7203 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007204}
7205
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007206static bool adev_input_allow_hifi_record(struct audio_device *adev,
7207 audio_devices_t devices,
7208 audio_input_flags_t flags,
7209 audio_source_t source) {
7210 const bool allowed = true;
7211
7212 if (!audio_is_usb_in_device(devices))
7213 return !allowed;
7214
7215 switch (flags) {
7216 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007217 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007218 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7219 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007220 default:
7221 return !allowed;
7222 }
7223
7224 switch (source) {
7225 case AUDIO_SOURCE_DEFAULT:
7226 case AUDIO_SOURCE_MIC:
7227 case AUDIO_SOURCE_UNPROCESSED:
7228 break;
7229 default:
7230 return !allowed;
7231 }
7232
7233 switch (adev->mode) {
7234 case 0:
7235 break;
7236 default:
7237 return !allowed;
7238 }
7239
7240 return allowed;
7241}
7242
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007243static int adev_update_voice_comm_input_stream(struct stream_in *in,
7244 struct audio_config *config)
7245{
7246 bool valid_rate = (config->sample_rate == 8000 ||
7247 config->sample_rate == 16000 ||
7248 config->sample_rate == 32000 ||
7249 config->sample_rate == 48000);
7250 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7251
7252#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007253 if (valid_rate && valid_ch &&
7254 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007255 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7256 in->config = default_pcm_config_voip_copp;
7257 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7258 DEFAULT_VOIP_BUF_DURATION_MS,
7259 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7260 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007261 ALOGW("%s No valid input in voip, use defaults"
7262 "sample rate %u, channel mask 0x%X",
7263 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007264 }
7265 in->config.rate = config->sample_rate;
7266 in->sample_rate = config->sample_rate;
7267#else
7268 //XXX needed for voice_extn_compress_voip_open_input_stream
7269 in->config.rate = config->sample_rate;
7270 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7271 voice_extn_compress_voip_is_active(in->dev)) &&
7272 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7273 valid_rate && valid_ch) {
7274 voice_extn_compress_voip_open_input_stream(in);
7275 // update rate entries to match config from AF
7276 in->config.rate = config->sample_rate;
7277 in->sample_rate = config->sample_rate;
7278 } else {
7279 ALOGW("%s compress voip not active, use defaults", __func__);
7280 }
7281#endif
7282 return 0;
7283}
7284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007286 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007287 audio_devices_t devices,
7288 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007289 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307290 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007291 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007292 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007293{
7294 struct audio_device *adev = (struct audio_device *)dev;
7295 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007296 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007297 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007298 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307299 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007300 bool is_usb_dev = audio_is_usb_in_device(devices);
7301 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7302 devices,
7303 flags,
7304 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307305
kunleizdff872d2018-08-20 14:40:33 +08007306 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007307 is_usb_dev = false;
7308 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7309 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7310 __func__, devices);
7311 }
7312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007313 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007314
7315 if (!(is_usb_dev && may_use_hifi_record)) {
7316 if (config->sample_rate == 0)
7317 config->sample_rate = 48000;
7318 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7319 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7320 if (config->format == AUDIO_FORMAT_DEFAULT)
7321 config->format = AUDIO_FORMAT_PCM_16_BIT;
7322
7323 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7324
7325 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7326 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307327 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007328
7329 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007330
7331 if (!in) {
7332 ALOGE("failed to allocate input stream");
7333 return -ENOMEM;
7334 }
7335
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307336 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307337 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7338 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007339 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007340 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007342 in->stream.common.get_sample_rate = in_get_sample_rate;
7343 in->stream.common.set_sample_rate = in_set_sample_rate;
7344 in->stream.common.get_buffer_size = in_get_buffer_size;
7345 in->stream.common.get_channels = in_get_channels;
7346 in->stream.common.get_format = in_get_format;
7347 in->stream.common.set_format = in_set_format;
7348 in->stream.common.standby = in_standby;
7349 in->stream.common.dump = in_dump;
7350 in->stream.common.set_parameters = in_set_parameters;
7351 in->stream.common.get_parameters = in_get_parameters;
7352 in->stream.common.add_audio_effect = in_add_audio_effect;
7353 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7354 in->stream.set_gain = in_set_gain;
7355 in->stream.read = in_read;
7356 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307357 in->stream.get_active_microphones = in_get_active_microphones;
Ramjee Singhacef98f2019-06-28 11:01:25 +05307358#if ANDROID_PLATFORM_SDK_VERSION >= 29
7359 in->stream.set_microphone_direction = in_set_microphone_direction;
7360 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
7361#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362
7363 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007364 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007365 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007366 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007367 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007368 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007369 in->bit_width = 16;
7370 in->af_period_multiplier = 1;
7371
7372 /* Update config params with the requested sample rate and channels */
7373 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7374 (adev->mode != AUDIO_MODE_IN_CALL)) {
7375 ret = -EINVAL;
7376 goto err_open;
7377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007378
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007379 if (is_usb_dev && may_use_hifi_record) {
7380 /* HiFi record selects an appropriate format, channel, rate combo
7381 depending on sink capabilities*/
7382 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7383 &config->format,
7384 &in->supported_formats[0],
7385 MAX_SUPPORTED_FORMATS,
7386 &config->channel_mask,
7387 &in->supported_channel_masks[0],
7388 MAX_SUPPORTED_CHANNEL_MASKS,
7389 &config->sample_rate,
7390 &in->supported_sample_rates[0],
7391 MAX_SUPPORTED_SAMPLE_RATES);
7392 if (ret != 0) {
7393 ret = -EINVAL;
7394 goto err_open;
7395 }
7396 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007397 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307398 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307399 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7400 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7401 in->config.format = PCM_FORMAT_S32_LE;
7402 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307403 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7404 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7405 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7406 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7407 bool ret_error = false;
7408 in->bit_width = 24;
7409 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7410 from HAL is 24_packed and 8_24
7411 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7412 24_packed return error indicating supported format is 24_packed
7413 *> In case of any other source requesting 24 bit or float return error
7414 indicating format supported is 16 bit only.
7415
7416 on error flinger will retry with supported format passed
7417 */
7418 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7419 (source != AUDIO_SOURCE_CAMCORDER)) {
7420 config->format = AUDIO_FORMAT_PCM_16_BIT;
7421 if (config->sample_rate > 48000)
7422 config->sample_rate = 48000;
7423 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007424 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7425 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307426 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7427 ret_error = true;
7428 }
7429
7430 if (ret_error) {
7431 ret = -EINVAL;
7432 goto err_open;
7433 }
7434 }
7435
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007436 in->channel_mask = config->channel_mask;
7437 in->format = config->format;
7438
7439 in->usecase = USECASE_AUDIO_RECORD;
7440 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7441 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7442 is_low_latency = true;
7443#if LOW_LATENCY_CAPTURE_USE_CASE
7444 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7445#endif
7446 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7447 }
7448
7449 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7450 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7451 in->realtime = 0;
7452 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7453 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007454 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007455 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007456 in->stream.start = in_start;
7457 in->stream.stop = in_stop;
7458 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7459 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007460 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007461 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7462 } else if (in->realtime) {
7463 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007464 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007465 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007466 in->sample_rate = in->config.rate;
7467 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007468 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007469 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7470 in->config = pcm_config_audio_capture;
7471 frame_size = audio_stream_in_frame_size(&in->stream);
7472 buffer_size = get_input_buffer_size(config->sample_rate,
7473 config->format,
7474 channel_count,
7475 false /*is_low_latency*/);
7476 in->config.period_size = buffer_size / frame_size;
7477 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007478 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007479 switch (config->format) {
7480 case AUDIO_FORMAT_PCM_32_BIT:
7481 in->bit_width = 32;
7482 break;
7483 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7484 case AUDIO_FORMAT_PCM_8_24_BIT:
7485 in->bit_width = 24;
7486 break;
7487 default:
7488 in->bit_width = 16;
7489 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007490 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007491 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007492 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307493 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007494 if (config->sample_rate == 0)
7495 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7496 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7497 config->sample_rate != 8000) {
7498 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7499 ret = -EINVAL;
7500 goto err_open;
7501 }
7502 if (config->format == AUDIO_FORMAT_DEFAULT)
7503 config->format = AUDIO_FORMAT_PCM_16_BIT;
7504 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7505 config->format = AUDIO_FORMAT_PCM_16_BIT;
7506 ret = -EINVAL;
7507 goto err_open;
7508 }
7509
7510 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7511 in->config = pcm_config_afe_proxy_record;
7512 in->config.channels = channel_count;
7513 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307514 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007515 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307516 int ret_val;
7517 pthread_mutex_lock(&adev->lock);
7518 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7519 in, config, &channel_mask_updated);
7520 pthread_mutex_unlock(&adev->lock);
7521
7522 if (!ret_val) {
7523 if (channel_mask_updated == true) {
7524 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7525 __func__, config->channel_mask);
7526 ret = -EINVAL;
7527 goto err_open;
7528 }
7529 ALOGD("%s: created multi-channel session succesfully",__func__);
7530 } else if (audio_extn_compr_cap_enabled() &&
7531 audio_extn_compr_cap_format_supported(config->format) &&
7532 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7533 audio_extn_compr_cap_init(in);
7534 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307535 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307536 ret = audio_extn_cin_configure_input_stream(in);
7537 if (ret)
7538 goto err_open;
7539 } else {
7540 in->config = pcm_config_audio_capture;
7541 in->config.rate = config->sample_rate;
7542 in->config.format = pcm_format_from_audio_format(config->format);
7543 in->config.channels = channel_count;
7544 in->sample_rate = config->sample_rate;
7545 in->format = config->format;
7546 frame_size = audio_stream_in_frame_size(&in->stream);
7547 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007548 config->format,
7549 channel_count,
7550 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307551 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007552
Revathi Uddarajud2634032017-12-07 14:42:34 +05307553 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7554 /* optionally use VOIP usecase depending on config(s) */
7555 ret = adev_update_voice_comm_input_stream(in, config);
7556 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007557
Revathi Uddarajud2634032017-12-07 14:42:34 +05307558 if (ret) {
7559 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7560 goto err_open;
7561 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007562 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007563 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307564 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7565 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007566 devices, flags, in->format,
7567 in->sample_rate, in->bit_width,
7568 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307569 register_format(in->format, in->supported_formats);
7570 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7571 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307572
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007573 /* This stream could be for sound trigger lab,
7574 get sound trigger pcm if present */
7575 audio_extn_sound_trigger_check_and_get_session(in);
7576
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307577 lock_input_stream(in);
7578 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7579 pthread_mutex_lock(&adev->lock);
7580 in->card_status = adev->card_status;
7581 pthread_mutex_unlock(&adev->lock);
7582 pthread_mutex_unlock(&in->lock);
7583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007584 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007585 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007586 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007587
7588err_open:
7589 free(in);
7590 *stream_in = NULL;
7591 return ret;
7592}
7593
7594static void adev_close_input_stream(struct audio_hw_device *dev,
7595 struct audio_stream_in *stream)
7596{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007597 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007598 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007599 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307600
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307601 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007602
kunleizef40adb2018-12-28 17:50:23 +08007603 /* must deregister from sndmonitor first to prevent races
7604 * between the callback and close_stream
7605 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307606 audio_extn_snd_mon_unregister_listener(stream);
7607
kunleizef40adb2018-12-28 17:50:23 +08007608 /* Disable echo reference if there are no active input, hfp call
7609 * and sound trigger while closing input stream
7610 */
7611 if (!adev->active_input &&
7612 !audio_extn_hfp_is_active(adev) &&
7613 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8405edd2018-11-29 15:04:56 +08007614 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleizef40adb2018-12-28 17:50:23 +08007615 else
7616 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307617
Pallavid7c7a272018-01-16 11:22:55 +05307618 if (in == NULL) {
7619 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7620 return;
7621 }
7622
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007623 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307624 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007625 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307626 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007627 if (ret != 0)
7628 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7629 __func__, ret);
7630 } else
7631 in_standby(&stream->common);
7632
Revathi Uddarajud2634032017-12-07 14:42:34 +05307633 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007634 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007635 audio_extn_ssr_deinit();
7636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007637
Garmond Leunge2433c32017-09-28 21:51:22 -07007638 if (audio_extn_ffv_get_stream() == in) {
7639 audio_extn_ffv_stream_deinit();
7640 }
7641
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307642 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007643 audio_extn_compr_cap_format_supported(in->config.format))
7644 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307645
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307646 if (audio_extn_cin_attached_usecase(in->usecase))
7647 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007648
Mingming Yinfd7607b2016-01-22 12:48:44 -08007649 if (in->is_st_session) {
7650 ALOGV("%s: sound trigger pcm stop lab", __func__);
7651 audio_extn_sound_trigger_stop_lab(in);
7652 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007653 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307654 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007655 return;
7656}
7657
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307658int adev_create_audio_patch(struct audio_hw_device *dev,
7659 unsigned int num_sources,
7660 const struct audio_port_config *sources,
7661 unsigned int num_sinks,
7662 const struct audio_port_config *sinks,
7663 audio_patch_handle_t *handle)
7664{
7665
7666
7667 return audio_extn_hw_loopback_create_audio_patch(dev,
7668 num_sources,
7669 sources,
7670 num_sinks,
7671 sinks,
7672 handle);
7673
7674}
7675
7676int adev_release_audio_patch(struct audio_hw_device *dev,
7677 audio_patch_handle_t handle)
7678{
7679 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7680}
7681
7682int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7683{
7684 return audio_extn_hw_loopback_get_audio_port(dev, config);
7685}
7686
7687int adev_set_audio_port_config(struct audio_hw_device *dev,
7688 const struct audio_port_config *config)
7689{
7690 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7691}
7692
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007693static int adev_dump(const audio_hw_device_t *device __unused,
7694 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007695{
7696 return 0;
7697}
7698
7699static int adev_close(hw_device_t *device)
7700{
7701 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007702
7703 if (!adev)
7704 return 0;
7705
7706 pthread_mutex_lock(&adev_init_lock);
7707
7708 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307709 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007710 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007711 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307712 audio_extn_utils_release_streams_cfg_lists(
7713 &adev->streams_output_cfg_list,
7714 &adev->streams_input_cfg_list);
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307715 if (audio_extn_qap_is_enabled())
7716 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307717 if (audio_extn_qaf_is_enabled())
7718 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007719 audio_route_free(adev->audio_route);
Weiyin Jiang902f7d12019-03-05 23:39:45 +08007720 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07007721 free(adev->snd_dev_ref_cnt);
7722 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007723 if (adev->adm_deinit)
7724 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307725 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007726 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307727 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307728 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007729 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307730 if (adev->device_cfg_params) {
7731 free(adev->device_cfg_params);
7732 adev->device_cfg_params = NULL;
7733 }
Derek Chencdd17c72014-11-24 12:39:14 -08007734 if(adev->ext_hw_plugin)
7735 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007736 free(device);
7737 adev = NULL;
7738 }
7739 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchaa1358992018-11-14 13:25:08 +05307740 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007741 return 0;
7742}
7743
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007744/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7745 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7746 * just that it _might_ work.
7747 */
7748static int period_size_is_plausible_for_low_latency(int period_size)
7749{
7750 switch (period_size) {
7751 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007752 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007753 case 240:
7754 case 320:
7755 case 480:
7756 return 1;
7757 default:
7758 return 0;
7759 }
7760}
7761
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307762static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7763{
7764 bool is_snd_card_status = false;
7765 bool is_ext_device_status = false;
7766 char value[32];
7767 int card = -1;
7768 card_status_t status;
7769
7770 if (cookie != adev || !parms)
7771 return;
7772
7773 if (!parse_snd_card_status(parms, &card, &status)) {
7774 is_snd_card_status = true;
7775 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7776 is_ext_device_status = true;
7777 } else {
7778 // not a valid event
7779 return;
7780 }
7781
7782 pthread_mutex_lock(&adev->lock);
7783 if (card == adev->snd_card || is_ext_device_status) {
7784 if (is_snd_card_status && adev->card_status != status) {
7785 adev->card_status = status;
7786 platform_snd_card_update(adev->platform, status);
7787 audio_extn_fm_set_parameters(adev, parms);
7788 } else if (is_ext_device_status) {
7789 platform_set_parameters(adev->platform, parms);
7790 }
7791 }
7792 pthread_mutex_unlock(&adev->lock);
7793 return;
7794}
7795
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307796/* out and adev lock held */
7797static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7798{
7799 struct audio_usecase *uc_info;
7800 float left_p;
7801 float right_p;
7802 audio_devices_t devices;
7803
7804 uc_info = get_usecase_from_list(adev, out->usecase);
7805 if (uc_info == NULL) {
7806 ALOGE("%s: Could not find the usecase (%d) in the list",
7807 __func__, out->usecase);
7808 return -EINVAL;
7809 }
7810
7811 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7812 out->usecase, use_case_table[out->usecase]);
7813
7814 if (restore) {
7815 // restore A2DP device for active usecases and unmute if required
7816 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7817 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7818 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7819 select_devices(adev, uc_info->id);
7820 pthread_mutex_lock(&out->compr_mute_lock);
7821 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7822 (out->a2dp_compress_mute)) {
7823 out->a2dp_compress_mute = false;
7824 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7825 }
7826 pthread_mutex_unlock(&out->compr_mute_lock);
7827 }
7828 } else {
7829 // mute compress stream if suspended
7830 pthread_mutex_lock(&out->compr_mute_lock);
7831 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7832 (!out->a2dp_compress_mute)) {
7833 if (!out->standby) {
7834 ALOGD("%s: selecting speaker and muting stream", __func__);
7835 devices = out->devices;
7836 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7837 left_p = out->volume_l;
7838 right_p = out->volume_r;
7839 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7840 compress_pause(out->compr);
7841 out_set_compr_volume(&out->stream, (float)0, (float)0);
7842 out->a2dp_compress_mute = true;
7843 select_devices(adev, out->usecase);
7844 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7845 compress_resume(out->compr);
7846 out->devices = devices;
7847 out->volume_l = left_p;
7848 out->volume_r = right_p;
7849 }
7850 }
7851 pthread_mutex_unlock(&out->compr_mute_lock);
7852 }
7853 ALOGV("%s: exit", __func__);
7854 return 0;
7855}
7856
7857int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7858{
7859 int ret = 0;
7860
7861 lock_output_stream(out);
7862 pthread_mutex_lock(&adev->lock);
7863
7864 ret = check_a2dp_restore_l(adev, out, restore);
7865
7866 pthread_mutex_unlock(&adev->lock);
7867 pthread_mutex_unlock(&out->lock);
7868 return ret;
7869}
7870
Haynes Mathew George01156f92018-04-13 15:29:54 -07007871void adev_on_battery_status_changed(bool charging)
7872{
7873 pthread_mutex_lock(&adev->lock);
7874 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7875 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007876 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007877 pthread_mutex_unlock(&adev->lock);
7878}
7879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007880static int adev_open(const hw_module_t *module, const char *name,
7881 hw_device_t **device)
7882{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307883 int ret;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307884 char mixer_ctl_name[128] = {0};
7885 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307886
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007887 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007888 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7889
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007890 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007891 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007892 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007893 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007894 ALOGD("%s: returning existing instance of adev", __func__);
7895 ALOGD("%s: exit", __func__);
7896 pthread_mutex_unlock(&adev_init_lock);
7897 return 0;
7898 }
7899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007900 adev = calloc(1, sizeof(struct audio_device));
7901
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007902 if (!adev) {
7903 pthread_mutex_unlock(&adev_init_lock);
7904 return -ENOMEM;
7905 }
7906
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007907 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7908
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307909#ifdef DYNAMIC_LOG_ENABLED
7910 register_for_dynamic_logging("hal");
7911#endif
7912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007913 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7914 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7915 adev->device.common.module = (struct hw_module_t *)module;
7916 adev->device.common.close = adev_close;
7917
7918 adev->device.init_check = adev_init_check;
7919 adev->device.set_voice_volume = adev_set_voice_volume;
7920 adev->device.set_master_volume = adev_set_master_volume;
7921 adev->device.get_master_volume = adev_get_master_volume;
7922 adev->device.set_master_mute = adev_set_master_mute;
7923 adev->device.get_master_mute = adev_get_master_mute;
7924 adev->device.set_mode = adev_set_mode;
7925 adev->device.set_mic_mute = adev_set_mic_mute;
7926 adev->device.get_mic_mute = adev_get_mic_mute;
7927 adev->device.set_parameters = adev_set_parameters;
7928 adev->device.get_parameters = adev_get_parameters;
7929 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7930 adev->device.open_output_stream = adev_open_output_stream;
7931 adev->device.close_output_stream = adev_close_output_stream;
7932 adev->device.open_input_stream = adev_open_input_stream;
7933 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307934 adev->device.create_audio_patch = adev_create_audio_patch;
7935 adev->device.release_audio_patch = adev_release_audio_patch;
7936 adev->device.get_audio_port = adev_get_audio_port;
7937 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007938 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307939 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007940
7941 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007942 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007943 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007944 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007945 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007946 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007947 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007948 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307949 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007950 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007951 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007952 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007953 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007954 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007955 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307956 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307957 adev->perf_lock_opts[0] = 0x101;
7958 adev->perf_lock_opts[1] = 0x20E;
7959 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007960 adev->dsp_bit_width_enforce_mode = 0;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307961 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007963 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007964 adev->platform = platform_init(adev);
7965 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007966 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007967 free(adev->snd_dev_ref_cnt);
7968 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007969 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007970 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7971 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007972 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007973 return -EINVAL;
7974 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007975
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307976 if (audio_extn_qap_is_enabled()) {
7977 ret = audio_extn_qap_init(adev);
7978 if (ret < 0) {
7979 pthread_mutex_destroy(&adev->lock);
7980 free(adev);
7981 adev = NULL;
7982 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7983 *device = NULL;
7984 pthread_mutex_unlock(&adev_init_lock);
7985 return ret;
7986 }
7987 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
7988 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
7989 }
7990
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307991 if (audio_extn_qaf_is_enabled()) {
7992 ret = audio_extn_qaf_init(adev);
7993 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007994 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307995 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007996 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307997 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7998 *device = NULL;
7999 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308000 return ret;
8001 }
8002
8003 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8004 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8005 }
8006
Derek Chencdd17c72014-11-24 12:39:14 -08008007 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8008
Eric Laurentc4aef752013-09-12 17:45:53 -07008009 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8010 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8011 if (adev->visualizer_lib == NULL) {
8012 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8013 } else {
8014 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8015 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008016 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008017 "visualizer_hal_start_output");
8018 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008019 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008020 "visualizer_hal_stop_output");
8021 }
8022 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308023 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008024 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008025 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308026 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008027 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008028
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008029 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8030 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8031 if (adev->offload_effects_lib == NULL) {
8032 ALOGE("%s: DLOPEN failed for %s", __func__,
8033 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8034 } else {
8035 ALOGV("%s: DLOPEN successful for %s", __func__,
8036 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8037 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308038 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008039 "offload_effects_bundle_hal_start_output");
8040 adev->offload_effects_stop_output =
8041 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8042 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008043 adev->offload_effects_set_hpx_state =
8044 (int (*)(bool))dlsym(adev->offload_effects_lib,
8045 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308046 adev->offload_effects_get_parameters =
8047 (void (*)(struct str_parms *, struct str_parms *))
8048 dlsym(adev->offload_effects_lib,
8049 "offload_effects_bundle_get_parameters");
8050 adev->offload_effects_set_parameters =
8051 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8052 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008053 }
8054 }
8055
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008056 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8057 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8058 if (adev->adm_lib == NULL) {
8059 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8060 } else {
8061 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8062 adev->adm_init = (adm_init_t)
8063 dlsym(adev->adm_lib, "adm_init");
8064 adev->adm_deinit = (adm_deinit_t)
8065 dlsym(adev->adm_lib, "adm_deinit");
8066 adev->adm_register_input_stream = (adm_register_input_stream_t)
8067 dlsym(adev->adm_lib, "adm_register_input_stream");
8068 adev->adm_register_output_stream = (adm_register_output_stream_t)
8069 dlsym(adev->adm_lib, "adm_register_output_stream");
8070 adev->adm_deregister_stream = (adm_deregister_stream_t)
8071 dlsym(adev->adm_lib, "adm_deregister_stream");
8072 adev->adm_request_focus = (adm_request_focus_t)
8073 dlsym(adev->adm_lib, "adm_request_focus");
8074 adev->adm_abandon_focus = (adm_abandon_focus_t)
8075 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008076 adev->adm_set_config = (adm_set_config_t)
8077 dlsym(adev->adm_lib, "adm_set_config");
8078 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8079 dlsym(adev->adm_lib, "adm_request_focus_v2");
8080 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8081 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8082 adev->adm_on_routing_change = (adm_on_routing_change_t)
8083 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008084 }
8085 }
8086
Mingming Yin514a8bc2014-07-29 15:22:21 -07008087 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008088 //initialize this to false for now,
8089 //this will be set to true through set param
8090 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008091
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008092 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008093 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008094 adev->dsp_bit_width_enforce_mode =
8095 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008096
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308097 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8098 &adev->streams_output_cfg_list,
8099 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008100
Kiran Kandi910e1862013-10-29 13:29:42 -07008101 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008102
8103 char value[PROPERTY_VALUE_MAX];
8104 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008105 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008106 trial = atoi(value);
8107 if (period_size_is_plausible_for_low_latency(trial)) {
8108 pcm_config_low_latency.period_size = trial;
8109 pcm_config_low_latency.start_threshold = trial / 4;
8110 pcm_config_low_latency.avail_min = trial / 4;
8111 configured_low_latency_capture_period_size = trial;
8112 }
8113 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008114 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008115 trial = atoi(value);
8116 if (period_size_is_plausible_for_low_latency(trial)) {
8117 configured_low_latency_capture_period_size = trial;
8118 }
8119 }
8120
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008121 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8122
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008123 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008124 af_period_multiplier = atoi(value);
8125 if (af_period_multiplier < 0)
8126 af_period_multiplier = 2;
8127 else if (af_period_multiplier > 4)
8128 af_period_multiplier = 4;
8129
8130 ALOGV("new period_multiplier = %d", af_period_multiplier);
8131 }
8132
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008133 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008134 pthread_mutex_unlock(&adev_init_lock);
8135
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008136 if (adev->adm_init)
8137 adev->adm_data = adev->adm_init();
8138
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308139 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308140 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008141 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308142
8143 audio_extn_snd_mon_init();
8144 pthread_mutex_lock(&adev->lock);
8145 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8146 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008147 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8148 /*
8149 * if the battery state callback happens before charging can be queried,
8150 * it will be guarded with the adev->lock held in the cb function and so
8151 * the callback value will reflect the latest state
8152 */
8153 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308154 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008155 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8156 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308157 /* Allocate memory for Device config params */
8158 adev->device_cfg_params = (struct audio_device_config_param*)
8159 calloc(platform_get_max_codec_backend(),
8160 sizeof(struct audio_device_config_param));
8161 if (adev->device_cfg_params == NULL)
8162 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308163
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308164 /*
8165 * Check if new PSPD matrix mixer control is supported. If not
8166 * supported, then set flag so that old mixer ctrl is sent while
8167 * sending pspd coefficients on older kernel version. Query mixer
8168 * control for default pcm id and channel value one.
8169 */
8170 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
8171 "AudStr %d ChMixer Weight Ch %d", 0, 1);
8172
8173 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
8174 if (!ctl) {
8175 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
8176 __func__, mixer_ctl_name);
8177 adev->use_old_pspd_mix_ctrl = true;
8178 }
8179
Eric Laurent994a6932013-07-17 11:51:42 -07008180 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008181 return 0;
8182}
8183
8184static struct hw_module_methods_t hal_module_methods = {
8185 .open = adev_open,
8186};
8187
8188struct audio_module HAL_MODULE_INFO_SYM = {
8189 .common = {
8190 .tag = HARDWARE_MODULE_TAG,
8191 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8192 .hal_api_version = HARDWARE_HAL_API_VERSION,
8193 .id = AUDIO_HARDWARE_MODULE_ID,
8194 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008195 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008196 .methods = &hal_module_methods,
8197 },
8198};