blob: de149a46e3275ab6d1767150ac0c77311b274fef [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 }
2355
Weiyin Jiang902f7d12019-03-05 23:39:45 +08002356 /* Notify device change info to effect clients registered */
2357 audio_extn_gef_notify_device_config(
2358 usecase->stream.out->devices,
2359 usecase->stream.out->channel_mask,
2360 usecase->stream.out->app_type_cfg.sample_rate,
2361 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302362 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002363 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002364
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002365 /* If input stream is already running then effect needs to be
2366 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002367 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2368 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002369 check_and_enable_effect(adev);
2370
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002371 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002372 /* Enable aanc only if voice call exists */
2373 if (voice_is_call_state_active(adev))
2374 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2375
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002376 /* Enable sidetone only if other voice/voip call already exists */
2377 if (voice_is_call_state_active(adev) ||
2378 voice_extn_compress_voip_is_started(adev))
2379 voice_set_sidetone(adev, out_snd_device, true);
2380 }
2381
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002382 /* Applicable only on the targets that has external modem.
2383 * Enable device command should be sent to modem only after
2384 * enabling voice call mixer controls
2385 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002386 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002387 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2388 out_snd_device,
2389 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302390
2391 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2392
2393 if (usecase->type == VOIP_CALL) {
2394 if (adev->active_input != NULL &&
2395 !adev->active_input->standby) {
2396 if (is_bt_soc_on(adev) == false){
2397 ALOGD("BT SCO MIC disconnected while in connection");
2398 if (adev->active_input->pcm != NULL)
2399 pcm_stop(adev->active_input->pcm);
2400 }
2401 }
2402 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2403 && usecase->stream.out->started) {
2404 if (is_bt_soc_on(adev) == false) {
2405 ALOGD("BT SCO/A2DP disconnected while in connection");
2406 out_standby_l(&usecase->stream.out->stream.common);
2407 }
2408 }
2409 } else if ((usecase->stream.out != NULL) &&
2410 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2411 usecase->stream.out->started) {
2412 if (is_bt_soc_on(adev) == false) {
2413 ALOGD("BT SCO/A2dp disconnected while in connection");
2414 out_standby_l(&usecase->stream.out->stream.common);
2415 }
2416 }
2417 }
2418
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302419 ALOGD("%s: done",__func__);
2420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 return status;
2422}
2423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424static int stop_input_stream(struct stream_in *in)
2425{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302426 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302428
2429 if (in == NULL) {
2430 ALOGE("%s: stream_in ptr is NULL", __func__);
2431 return -EINVAL;
2432 }
2433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434 struct audio_device *adev = in->dev;
2435
Eric Laurent994a6932013-07-17 11:51:42 -07002436 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002437 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 uc_info = get_usecase_from_list(adev, in->usecase);
2439 if (uc_info == NULL) {
2440 ALOGE("%s: Could not find the usecase (%d) in the list",
2441 __func__, in->usecase);
2442 return -EINVAL;
2443 }
2444
Derek Chencdd17c72014-11-24 12:39:14 -08002445 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2446 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2447 ALOGE("%s: failed to stop ext hw plugin", __func__);
2448 }
2449
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002450 /* Close in-call recording streams */
2451 voice_check_and_stop_incall_rec_usecase(adev, in);
2452
Eric Laurent150dbfe2013-02-27 14:31:02 -08002453 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002454 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002455
2456 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002457 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002459 list_remove(&uc_info->list);
2460 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002462 adev->active_input = get_next_active_input(adev);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302463 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002464 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 return ret;
2466}
2467
2468int start_input_stream(struct stream_in *in)
2469{
2470 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002471 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302473
2474 if (in == NULL) {
2475 ALOGE("%s: stream_in ptr is NULL", __func__);
2476 return -EINVAL;
2477 }
2478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002480 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002481 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482
Mingming Yin2664a5b2015-09-03 10:53:11 -07002483 if (get_usecase_from_list(adev, usecase) == NULL)
2484 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302485 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2486 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002487
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302488 if (CARD_STATUS_OFFLINE == in->card_status||
2489 CARD_STATUS_OFFLINE == adev->card_status) {
2490 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302491 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302492 goto error_config;
2493 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302494
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302495 if (audio_is_bluetooth_sco_device(in->device)) {
2496 if (!adev->bt_sco_on) {
2497 ALOGE("%s: SCO profile is not ready, return error", __func__);
2498 ret = -EIO;
2499 goto error_config;
2500 }
2501 }
2502
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002503 /* Check if source matches incall recording usecase criteria */
2504 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2505 if (ret)
2506 goto error_config;
2507 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002508 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2509
2510 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2511 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2512 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002513 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002514 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002515
Eric Laurentb23d5282013-05-14 15:27:20 -07002516 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 if (in->pcm_device_id < 0) {
2518 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2519 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002520 ret = -EINVAL;
2521 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002523
2524 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002526
2527 if (!uc_info) {
2528 ret = -ENOMEM;
2529 goto error_config;
2530 }
2531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 uc_info->id = in->usecase;
2533 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002534 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002535 uc_info->devices = in->device;
2536 uc_info->in_snd_device = SND_DEVICE_NONE;
2537 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002539 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302540 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2541 adev->perf_lock_opts,
2542 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002543 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544
Derek Chencdd17c72014-11-24 12:39:14 -08002545 if (uc_info->in_snd_device != SND_DEVICE_NONE) {
2546 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2547 ALOGE("%s: failed to start ext hw plugin", __func__);
2548 }
2549
Haynes Mathew George16081042017-05-31 17:16:49 -07002550 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302551 ret = audio_extn_cin_start_input_stream(in);
2552 if (ret)
2553 goto error_open;
2554 else
2555 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002556 }
2557
Haynes Mathew George16081042017-05-31 17:16:49 -07002558 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002559 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002560 ALOGE("%s: pcm stream not ready", __func__);
2561 goto error_open;
2562 }
2563 ret = pcm_start(in->pcm);
2564 if (ret < 0) {
2565 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2566 goto error_open;
2567 }
2568 } else {
2569 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2570 unsigned int pcm_open_retry_count = 0;
2571
2572 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2573 flags |= PCM_MMAP | PCM_NOIRQ;
2574 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2575 } else if (in->realtime) {
2576 flags |= PCM_MMAP | PCM_NOIRQ;
2577 }
2578
Garmond Leunge2433c32017-09-28 21:51:22 -07002579 if (audio_extn_ffv_get_stream() == in) {
2580 ALOGD("%s: ffv stream, update pcm config", __func__);
2581 audio_extn_ffv_update_pcm_config(&config);
2582 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002583 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2584 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2585
2586 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002587 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002588 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002589 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002590 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05302591 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
2592 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2593 adev->card_status = CARD_STATUS_OFFLINE;
2594 in->card_status = CARD_STATUS_OFFLINE;
2595 ret = -EIO;
2596 goto error_open;
2597 }
2598
Haynes Mathew George16081042017-05-31 17:16:49 -07002599 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2600 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2601 if (in->pcm != NULL) {
2602 pcm_close(in->pcm);
2603 in->pcm = NULL;
2604 }
2605 if (pcm_open_retry_count-- == 0) {
2606 ret = -EIO;
2607 goto error_open;
2608 }
2609 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2610 continue;
2611 }
2612 break;
2613 }
2614
2615 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002616 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002617 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002618 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002619 if (ret < 0) {
2620 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2621 pcm_close(in->pcm);
2622 in->pcm = NULL;
2623 goto error_open;
2624 }
2625 register_in_stream(in);
2626 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002627 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002628 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002629 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002630 if (ret < 0) {
2631 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002632 pcm_close(in->pcm);
2633 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002634 goto error_open;
2635 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002636 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002637 }
2638
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002639 check_and_enable_effect(adev);
2640
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302641done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302642 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002643 ALOGD("%s: exit", __func__);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302644 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002645 return ret;
2646
2647error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302648 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002650error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302651 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302652 /*
2653 * sleep 50ms to allow sufficient time for kernel
2654 * drivers to recover incases like SSR.
2655 */
2656 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002657 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchaa1358992018-11-14 13:25:08 +05302658 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002659 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660}
2661
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002662void lock_input_stream(struct stream_in *in)
2663{
2664 pthread_mutex_lock(&in->pre_lock);
2665 pthread_mutex_lock(&in->lock);
2666 pthread_mutex_unlock(&in->pre_lock);
2667}
2668
2669void lock_output_stream(struct stream_out *out)
2670{
2671 pthread_mutex_lock(&out->pre_lock);
2672 pthread_mutex_lock(&out->lock);
2673 pthread_mutex_unlock(&out->pre_lock);
2674}
2675
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002676/* must be called with out->lock locked */
2677static int send_offload_cmd_l(struct stream_out* out, int command)
2678{
2679 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2680
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002681 if (!cmd) {
2682 ALOGE("failed to allocate mem for command 0x%x", command);
2683 return -ENOMEM;
2684 }
2685
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002686 ALOGVV("%s %d", __func__, command);
2687
2688 cmd->cmd = command;
2689 list_add_tail(&out->offload_cmd_list, &cmd->node);
2690 pthread_cond_signal(&out->offload_cond);
2691 return 0;
2692}
2693
2694/* must be called iwth out->lock locked */
2695static void stop_compressed_output_l(struct stream_out *out)
2696{
2697 out->offload_state = OFFLOAD_STATE_IDLE;
2698 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002699 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 if (out->compr != NULL) {
2701 compress_stop(out->compr);
2702 while (out->offload_thread_blocked) {
2703 pthread_cond_wait(&out->cond, &out->lock);
2704 }
2705 }
2706}
2707
Varun Balaraje49253e2017-07-06 19:48:56 +05302708bool is_interactive_usecase(audio_usecase_t uc_id)
2709{
2710 unsigned int i;
2711 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2712 if (uc_id == interactive_usecases[i])
2713 return true;
2714 }
2715 return false;
2716}
2717
2718static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2719{
2720 audio_usecase_t ret_uc = USECASE_INVALID;
2721 unsigned int intract_uc_index;
2722 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2723
2724 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2725 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2726 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2727 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2728 ret_uc = interactive_usecases[intract_uc_index];
2729 break;
2730 }
2731 }
2732
2733 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2734 return ret_uc;
2735}
2736
2737static void free_interactive_usecase(struct audio_device *adev,
2738 audio_usecase_t uc_id)
2739{
2740 unsigned int interact_uc_index;
2741 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2742
2743 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2744 if (interactive_usecases[interact_uc_index] == uc_id) {
2745 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2746 break;
2747 }
2748 }
2749 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2750}
2751
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002752bool is_offload_usecase(audio_usecase_t uc_id)
2753{
2754 unsigned int i;
2755 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2756 if (uc_id == offload_usecases[i])
2757 return true;
2758 }
2759 return false;
2760}
2761
Dhananjay Kumarac341582017-02-23 23:42:25 +05302762static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002763{
vivek mehta446c3962015-09-14 10:57:35 -07002764 audio_usecase_t ret_uc = USECASE_INVALID;
2765 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002766 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002767 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302768 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002769 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2770 else
2771 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002772
vivek mehta446c3962015-09-14 10:57:35 -07002773 pthread_mutex_lock(&adev->lock);
2774 if (get_usecase_from_list(adev, ret_uc) != NULL)
2775 ret_uc = USECASE_INVALID;
2776 pthread_mutex_unlock(&adev->lock);
2777
2778 return ret_uc;
2779 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002780
2781 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002782 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2783 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2784 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2785 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002786 break;
2787 }
2788 }
vivek mehta446c3962015-09-14 10:57:35 -07002789
2790 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2791 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002792}
2793
2794static void free_offload_usecase(struct audio_device *adev,
2795 audio_usecase_t uc_id)
2796{
vivek mehta446c3962015-09-14 10:57:35 -07002797 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002798 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002799
2800 if (!adev->multi_offload_enable)
2801 return;
2802
2803 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2804 if (offload_usecases[offload_uc_index] == uc_id) {
2805 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002806 break;
2807 }
2808 }
2809 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2810}
2811
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002812static void *offload_thread_loop(void *context)
2813{
2814 struct stream_out *out = (struct stream_out *) context;
2815 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002816 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2819 set_sched_policy(0, SP_FOREGROUND);
2820 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2821
2822 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002823 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 for (;;) {
2825 struct offload_cmd *cmd = NULL;
2826 stream_callback_event_t event;
2827 bool send_callback = false;
2828
2829 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2830 __func__, list_empty(&out->offload_cmd_list),
2831 out->offload_state);
2832 if (list_empty(&out->offload_cmd_list)) {
2833 ALOGV("%s SLEEPING", __func__);
2834 pthread_cond_wait(&out->offload_cond, &out->lock);
2835 ALOGV("%s RUNNING", __func__);
2836 continue;
2837 }
2838
2839 item = list_head(&out->offload_cmd_list);
2840 cmd = node_to_item(item, struct offload_cmd, node);
2841 list_remove(item);
2842
2843 ALOGVV("%s STATE %d CMD %d out->compr %p",
2844 __func__, out->offload_state, cmd->cmd, out->compr);
2845
2846 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2847 free(cmd);
2848 break;
2849 }
2850
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002851 // allow OFFLOAD_CMD_ERROR reporting during standby
2852 // this is needed to handle failures during compress_open
2853 // Note however that on a pause timeout, the stream is closed
2854 // and no offload usecase will be active. Therefore this
2855 // special case is needed for compress_open failures alone
2856 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2857 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002859 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 pthread_cond_signal(&out->cond);
2861 continue;
2862 }
2863 out->offload_thread_blocked = true;
2864 pthread_mutex_unlock(&out->lock);
2865 send_callback = false;
2866 switch(cmd->cmd) {
2867 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002868 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002870 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 send_callback = true;
2872 event = STREAM_CBK_EVENT_WRITE_READY;
2873 break;
2874 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002875 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302876 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002877 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302878 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002879 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302880 if (ret < 0)
2881 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302882 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302883 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002884 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002885 else
2886 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002887 if (-ENETRESET != ret && !(-EINTR == ret &&
2888 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302889 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302890 pthread_mutex_lock(&out->lock);
2891 out->send_new_metadata = 1;
2892 out->send_next_track_params = true;
2893 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302894 event = STREAM_CBK_EVENT_DRAIN_READY;
2895 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2896 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302897 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 break;
2899 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002900 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002901 ret = compress_drain(out->compr);
2902 ALOGD("copl(%p):out of compress_drain", out);
2903 // EINTR check avoids drain interruption due to SSR
2904 if (-ENETRESET != ret && !(-EINTR == ret &&
2905 CARD_STATUS_OFFLINE == out->card_status)) {
2906 send_callback = true;
2907 event = STREAM_CBK_EVENT_DRAIN_READY;
2908 } else
2909 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302911 case OFFLOAD_CMD_ERROR:
2912 ALOGD("copl(%p): sending error callback to AF", out);
2913 send_callback = true;
2914 event = STREAM_CBK_EVENT_ERROR;
2915 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 default:
2917 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2918 break;
2919 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002920 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 out->offload_thread_blocked = false;
2922 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002923 if (send_callback && out->client_callback) {
2924 ALOGVV("%s: sending client_callback event %d", __func__, event);
2925 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002926 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 free(cmd);
2928 }
2929
2930 pthread_cond_signal(&out->cond);
2931 while (!list_empty(&out->offload_cmd_list)) {
2932 item = list_head(&out->offload_cmd_list);
2933 list_remove(item);
2934 free(node_to_item(item, struct offload_cmd, node));
2935 }
2936 pthread_mutex_unlock(&out->lock);
2937
2938 return NULL;
2939}
2940
2941static int create_offload_callback_thread(struct stream_out *out)
2942{
2943 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2944 list_init(&out->offload_cmd_list);
2945 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2946 offload_thread_loop, out);
2947 return 0;
2948}
2949
2950static int destroy_offload_callback_thread(struct stream_out *out)
2951{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002952 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 stop_compressed_output_l(out);
2954 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2955
2956 pthread_mutex_unlock(&out->lock);
2957 pthread_join(out->offload_thread, (void **) NULL);
2958 pthread_cond_destroy(&out->offload_cond);
2959
2960 return 0;
2961}
2962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963static int stop_output_stream(struct stream_out *out)
2964{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302965 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 struct audio_usecase *uc_info;
2967 struct audio_device *adev = out->dev;
2968
Eric Laurent994a6932013-07-17 11:51:42 -07002969 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002970 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 uc_info = get_usecase_from_list(adev, out->usecase);
2972 if (uc_info == NULL) {
2973 ALOGE("%s: Could not find the usecase (%d) in the list",
2974 __func__, out->usecase);
2975 return -EINVAL;
2976 }
2977
Derek Chencdd17c72014-11-24 12:39:14 -08002978 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
2979 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2980 ALOGE("%s: failed to stop ext hw plugin", __func__);
2981 }
2982
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002983 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302984 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002985 if (adev->visualizer_stop_output != NULL)
2986 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002987
2988 audio_extn_dts_remove_state_notifier_node(out->usecase);
2989
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002990 if (adev->offload_effects_stop_output != NULL)
2991 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2992 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002993
Arun Mirpuridbef0c72018-09-12 18:36:10 -07002994 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
2995 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07002996 voice_set_device_mute_flag(adev, false);
2997
Eric Laurent150dbfe2013-02-27 14:31:02 -08002998 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002999 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003000
3001 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003002 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003004 if (is_offload_usecase(out->usecase)) {
3005 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3006 adev->dsp_bit_width_enforce_mode,
3007 false);
3008 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003009 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3010 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3011 false);
3012
3013 if (ret != 0)
3014 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3015 /* default service interval was successfully updated,
3016 reopen USB backend with new service interval */
3017 ret = 0;
3018 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003019
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003020 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303021 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003022 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303023 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003024 ALOGV("Disable passthrough , reset mixer to pcm");
3025 /* NO_PASSTHROUGH */
3026 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003027 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003028 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3029 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003030
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303031 /* Must be called after removing the usecase from list */
3032 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303033 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303034
Manish Dewangan21a850a2017-08-14 12:03:55 +05303035 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003036 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3037 if (ret < 0)
3038 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3039 }
3040
Garmond Leung5fd0b552018-04-17 11:56:12 -07003041 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003042 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 return ret;
3044}
3045
3046int start_output_stream(struct stream_out *out)
3047{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 struct audio_usecase *uc_info;
3050 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003051 char mixer_ctl_name[128];
3052 struct mixer_ctl *ctl = NULL;
3053 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303054 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055
Haynes Mathew George380745d2017-10-04 15:27:45 -07003056 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003057 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3058 ret = -EINVAL;
3059 goto error_config;
3060 }
3061
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303062 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3063 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3064 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303065
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303066 if (CARD_STATUS_OFFLINE == out->card_status ||
3067 CARD_STATUS_OFFLINE == adev->card_status) {
3068 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303069 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303070 goto error_config;
3071 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303072
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003073 //Update incall music usecase to reflect correct voice session
3074 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3075 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3076 if (ret != 0) {
3077 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3078 __func__, ret);
3079 goto error_config;
3080 }
3081 }
3082
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303083 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3084 if (!audio_extn_a2dp_is_ready()) {
3085 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303086 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303087 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303088 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3089 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3090 ret = -EAGAIN;
3091 goto error_config;
3092 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303093 }
3094 }
3095 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303096 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3097 if (!adev->bt_sco_on) {
3098 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3099 //combo usecase just by pass a2dp
3100 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3101 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3102 } else {
3103 ALOGE("%s: SCO profile is not ready, return error", __func__);
3104 ret = -EAGAIN;
3105 goto error_config;
3106 }
3107 }
3108 }
3109
Eric Laurentb23d5282013-05-14 15:27:20 -07003110 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 if (out->pcm_device_id < 0) {
3112 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3113 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003114 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003115 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 }
3117
3118 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003119
3120 if (!uc_info) {
3121 ret = -ENOMEM;
3122 goto error_config;
3123 }
3124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 uc_info->id = out->usecase;
3126 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003127 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003128 uc_info->devices = out->devices;
3129 uc_info->in_snd_device = SND_DEVICE_NONE;
3130 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003131
3132 /* This must be called before adding this usecase to the list */
3133 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3134 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3135 /* USB backend is not reopened immediately.
3136 This is eventually done as part of select_devices */
3137 }
3138
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003139 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303141 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3142 adev->perf_lock_opts,
3143 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303144
3145 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303146 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303147 if (audio_extn_passthru_is_enabled() &&
3148 audio_extn_passthru_is_passthrough_stream(out)) {
3149 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303150 }
3151 }
3152
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303153 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3154 (!audio_extn_a2dp_is_ready())) {
3155 if (!a2dp_combo) {
3156 check_a2dp_restore_l(adev, out, false);
3157 } else {
3158 audio_devices_t dev = out->devices;
3159 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3160 select_devices(adev, out->usecase);
3161 out->devices = dev;
3162 }
3163 } else {
3164 select_devices(adev, out->usecase);
3165 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003166
Arun Mirpuridbef0c72018-09-12 18:36:10 -07003167 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3168 out->usecase == USECASE_INCALL_MUSIC_UPLINK2)
Arun Mirpurief53ce52018-09-11 18:00:09 -07003169 voice_set_device_mute_flag(adev, true);
3170
Derek Chencdd17c72014-11-24 12:39:14 -08003171 if (uc_info->out_snd_device != SND_DEVICE_NONE) {
3172 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3173 ALOGE("%s: failed to start ext hw plugin", __func__);
3174 }
3175
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003176 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3177 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003178
3179 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003180 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003181 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3182 ALOGE("%s: pcm stream not ready", __func__);
3183 goto error_open;
3184 }
3185 ret = pcm_start(out->pcm);
3186 if (ret < 0) {
3187 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3188 goto error_open;
3189 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07003190 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003191 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003192 unsigned int flags = PCM_OUT;
3193 unsigned int pcm_open_retry_count = 0;
3194 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3195 flags |= PCM_MMAP | PCM_NOIRQ;
3196 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003197 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003198 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003199 } else
3200 flags |= PCM_MONOTONIC;
3201
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003202 if ((adev->vr_audio_mode_enabled) &&
3203 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3204 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3205 "PCM_Dev %d Topology", out->pcm_device_id);
3206 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3207 if (!ctl) {
3208 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3209 __func__, mixer_ctl_name);
3210 } else {
3211 //if success use ULLPP
3212 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3213 __func__, mixer_ctl_name, out->pcm_device_id);
3214 //There is a still a possibility that some sessions
3215 // that request for FAST|RAW when 3D audio is active
3216 //can go through ULLPP. Ideally we expects apps to
3217 //listen to audio focus and stop concurrent playback
3218 //Also, we will look for mode flag (voice_in_communication)
3219 //before enabling the realtime flag.
3220 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3221 }
3222 }
3223
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003224 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003225 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003226 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3227 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003228 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303229 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
3230 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3231 out->card_status = CARD_STATUS_OFFLINE;
3232 adev->card_status = CARD_STATUS_OFFLINE;
3233 ret = -EIO;
3234 goto error_open;
3235 }
3236
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003237 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3238 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3239 if (out->pcm != NULL) {
3240 pcm_close(out->pcm);
3241 out->pcm = NULL;
3242 }
3243 if (pcm_open_retry_count-- == 0) {
3244 ret = -EIO;
3245 goto error_open;
3246 }
3247 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3248 continue;
3249 }
3250 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05303252 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3253 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003254
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003255 ALOGV("%s: pcm_prepare", __func__);
3256 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003257 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003258 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003259 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003260 if (ret < 0) {
3261 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3262 pcm_close(out->pcm);
3263 out->pcm = NULL;
3264 goto error_open;
3265 }
3266 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08003267 // apply volume for voip playback after path is set up
3268 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3269 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003271 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303272 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003273 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3274 adev->dsp_bit_width_enforce_mode,
3275 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003277 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003278 out->compr = compress_open(adev->snd_card,
3279 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003281 ATRACE_END();
Sharad Sangle90e613f2018-05-04 16:15:38 +05303282 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
3283 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3284 adev->card_status = CARD_STATUS_OFFLINE;
3285 out->card_status = CARD_STATUS_OFFLINE;
3286 ret = -EIO;
3287 goto error_open;
3288 }
3289
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003291 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 compress_close(out->compr);
3293 out->compr = NULL;
3294 ret = -EIO;
3295 goto error_open;
3296 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303297 /* compress_open sends params of the track, so reset the flag here */
3298 out->is_compr_metadata_avail = false;
3299
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003300 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003302
Fred Oh3f43e742015-03-04 18:42:34 -08003303 /* Since small bufs uses blocking writes, a write will be blocked
3304 for the default max poll time (20s) in the event of an SSR.
3305 Reduce the poll time to observe and deal with SSR faster.
3306 */
Ashish Jain5106d362016-05-11 19:23:33 +05303307 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003308 compress_set_max_poll_wait(out->compr, 1000);
3309 }
3310
Manish Dewangan69426c82017-01-30 17:35:36 +05303311 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303312 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303313
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003314 audio_extn_dts_create_state_notifier_node(out->usecase);
3315 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3316 popcount(out->channel_mask),
3317 out->playback_started);
3318
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003319#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303320 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003321 audio_extn_dolby_send_ddp_endp_params(adev);
3322#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303323 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3324 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003325 if (adev->visualizer_start_output != NULL)
3326 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3327 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303328 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003329 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003332
3333 if (ret == 0) {
3334 register_out_stream(out);
3335 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003336 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3337 ALOGE("%s: pcm stream not ready", __func__);
3338 goto error_open;
3339 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003340 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003341 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003342 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003343 if (ret < 0)
3344 goto error_open;
3345 }
3346 }
3347
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303348 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003349 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003350
Manish Dewangan21a850a2017-08-14 12:03:55 +05303351 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003352 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003353 if (ret < 0)
3354 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3355 }
3356
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003357 // consider a scenario where on pause lower layers are tear down.
3358 // so on resume, swap mixer control need to be sent only when
3359 // backend is active, hence rather than sending from enable device
3360 // sending it from start of streamtream
3361
3362 platform_set_swap_channels(adev, true);
3363
Haynes Mathew George380745d2017-10-04 15:27:45 -07003364 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303365 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003366 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303368 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003370error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303371 /*
3372 * sleep 50ms to allow sufficient time for kernel
3373 * drivers to recover incases like SSR.
3374 */
3375 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003376 ATRACE_END();
Vatsal Buchaa1358992018-11-14 13:25:08 +05303377 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379}
3380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381static int check_input_parameters(uint32_t sample_rate,
3382 audio_format_t format,
3383 int channel_count)
3384{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003385 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303387 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3388 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3389 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003390 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003391 !audio_extn_compr_cap_format_supported(format))
3392 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003393
3394 switch (channel_count) {
3395 case 1:
3396 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303397 case 3:
3398 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003399 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003400 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003401 break;
3402 default:
3403 ret = -EINVAL;
3404 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405
3406 switch (sample_rate) {
3407 case 8000:
3408 case 11025:
3409 case 12000:
3410 case 16000:
3411 case 22050:
3412 case 24000:
3413 case 32000:
3414 case 44100:
3415 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003416 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303417 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003418 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303419 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 break;
3421 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003422 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 }
3424
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003425 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426}
3427
Naresh Tanniru04f71882018-06-26 17:46:22 +05303428
3429/** Add a value in a list if not already present.
3430 * @return true if value was successfully inserted or already present,
3431 * false if the list is full and does not contain the value.
3432 */
3433static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3434 for (size_t i = 0; i < list_length; i++) {
3435 if (list[i] == value) return true; // value is already present
3436 if (list[i] == 0) { // no values in this slot
3437 list[i] = value;
3438 return true; // value inserted
3439 }
3440 }
3441 return false; // could not insert value
3442}
3443
3444/** Add channel_mask in supported_channel_masks if not already present.
3445 * @return true if channel_mask was successfully inserted or already present,
3446 * false if supported_channel_masks is full and does not contain channel_mask.
3447 */
3448static void register_channel_mask(audio_channel_mask_t channel_mask,
3449 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3450 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3451 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3452}
3453
3454/** Add format in supported_formats if not already present.
3455 * @return true if format was successfully inserted or already present,
3456 * false if supported_formats is full and does not contain format.
3457 */
3458static void register_format(audio_format_t format,
3459 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3460 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3461 "%s: stream can not declare supporting its format %x", __func__, format);
3462}
3463/** Add sample_rate in supported_sample_rates if not already present.
3464 * @return true if sample_rate was successfully inserted or already present,
3465 * false if supported_sample_rates is full and does not contain sample_rate.
3466 */
3467static void register_sample_rate(uint32_t sample_rate,
3468 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3469 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3470 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3471}
3472
Karthikeyan Mani35531922018-11-07 15:44:13 -08003473static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3474{
3475 uint32_t high = num1, low = num2, temp = 0;
3476
3477 if (!num1 || !num2)
3478 return 0;
3479
3480 if (num1 < num2) {
3481 high = num2;
3482 low = num1;
3483 }
3484
3485 while (low != 0) {
3486 temp = low;
3487 low = high % low;
3488 high = temp;
3489 }
3490 return (num1 * num2)/high;
3491}
3492
3493static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3494{
3495 uint32_t remainder = 0;
3496
3497 if (!multiplier)
3498 return num;
3499
3500 remainder = num % multiplier;
3501 if (remainder)
3502 num += (multiplier - remainder);
3503
3504 return num;
3505}
3506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507static size_t get_input_buffer_size(uint32_t sample_rate,
3508 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003509 int channel_count,
3510 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511{
3512 size_t size = 0;
Karthikeyan Mani35531922018-11-07 15:44:13 -08003513 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003515 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3516 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003518 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003519 if (is_low_latency)
3520 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303521
Karthikeyan Mani35531922018-11-07 15:44:13 -08003522 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
3523 size *= bytes_per_period_sample;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003525 /* make sure the size is multiple of 32 bytes
3526 * At 48 kHz mono 16-bit PCM:
3527 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3528 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Mani35531922018-11-07 15:44:13 -08003529 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003530 */
Karthikeyan Mani35531922018-11-07 15:44:13 -08003531 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003532
3533 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534}
3535
Ashish Jain058165c2016-09-28 23:18:48 +05303536static size_t get_output_period_size(uint32_t sample_rate,
3537 audio_format_t format,
3538 int channel_count,
3539 int duration /*in millisecs*/)
3540{
3541 size_t size = 0;
3542 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3543
3544 if ((duration == 0) || (sample_rate == 0) ||
3545 (bytes_per_sample == 0) || (channel_count == 0)) {
3546 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3547 bytes_per_sample, channel_count);
3548 return -EINVAL;
3549 }
3550
3551 size = (sample_rate *
3552 duration *
3553 bytes_per_sample *
3554 channel_count) / 1000;
3555 /*
3556 * To have same PCM samples for all channels, the buffer size requires to
3557 * be multiple of (number of channels * bytes per sample)
3558 * For writes to succeed, the buffer must be written at address which is multiple of 32
3559 */
3560 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3561
3562 return (size/(channel_count * bytes_per_sample));
3563}
3564
Zhou Song48453a02018-01-10 17:50:59 +08003565static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303566{
3567 uint64_t actual_frames_rendered = 0;
3568 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3569
3570 /* This adjustment accounts for buffering after app processor.
3571 * It is based on estimated DSP latency per use case, rather than exact.
3572 */
3573 int64_t platform_latency = platform_render_latency(out->usecase) *
3574 out->sample_rate / 1000000LL;
3575
Zhou Song48453a02018-01-10 17:50:59 +08003576 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303577 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3578 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3579 * hence only estimate.
3580 */
3581 int64_t signed_frames = out->written - kernel_buffer_size;
3582
3583 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3584
Zhou Song48453a02018-01-10 17:50:59 +08003585 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303586 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003587 if (timestamp != NULL )
3588 *timestamp = out->writeAt;
3589 } else if (timestamp != NULL) {
3590 clock_gettime(CLOCK_MONOTONIC, timestamp);
3591 }
3592 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303593
3594 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3595 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3596 (long long int)out->written, (int)kernel_buffer_size,
3597 audio_bytes_per_sample(out->compr_config.codec->format),
3598 popcount(out->channel_mask));
3599
3600 return actual_frames_rendered;
3601}
3602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3604{
3605 struct stream_out *out = (struct stream_out *)stream;
3606
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003607 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608}
3609
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003610static int out_set_sample_rate(struct audio_stream *stream __unused,
3611 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612{
3613 return -ENOSYS;
3614}
3615
3616static size_t out_get_buffer_size(const struct audio_stream *stream)
3617{
3618 struct stream_out *out = (struct stream_out *)stream;
3619
Varun Balaraje49253e2017-07-06 19:48:56 +05303620 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303621 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303622 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303623 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3624 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3625 else
3626 return out->compr_config.fragment_size;
3627 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003628 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003629 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3630 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 +05303631 else if (is_offload_usecase(out->usecase) &&
3632 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303633 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003634
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003635 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003636 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637}
3638
3639static uint32_t out_get_channels(const struct audio_stream *stream)
3640{
3641 struct stream_out *out = (struct stream_out *)stream;
3642
3643 return out->channel_mask;
3644}
3645
3646static audio_format_t out_get_format(const struct audio_stream *stream)
3647{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648 struct stream_out *out = (struct stream_out *)stream;
3649
3650 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651}
3652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003653static int out_set_format(struct audio_stream *stream __unused,
3654 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
3656 return -ENOSYS;
3657}
3658
3659static int out_standby(struct audio_stream *stream)
3660{
3661 struct stream_out *out = (struct stream_out *)stream;
3662 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003663 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303665 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3666 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003668 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003670 if (adev->adm_deregister_stream)
3671 adev->adm_deregister_stream(adev->adm_data, out->handle);
3672
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003673 if (is_offload_usecase(out->usecase))
3674 stop_compressed_output_l(out);
3675
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003676 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003678 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3679 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303680 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003681 pthread_mutex_unlock(&adev->lock);
3682 pthread_mutex_unlock(&out->lock);
3683 ALOGD("VOIP output entered standby");
3684 return 0;
3685 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003686 if (out->pcm) {
3687 pcm_close(out->pcm);
3688 out->pcm = NULL;
3689 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003690 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3691 do_stop = out->playback_started;
3692 out->playback_started = false;
3693 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003694 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003695 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303696 out->send_next_track_params = false;
3697 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003698 out->gapless_mdata.encoder_delay = 0;
3699 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003700 if (out->compr != NULL) {
3701 compress_close(out->compr);
3702 out->compr = NULL;
3703 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003704 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003705 if (do_stop) {
3706 stop_output_stream(out);
3707 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003708 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 }
3710 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303711 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 return 0;
3713}
3714
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303715static int out_on_error(struct audio_stream *stream)
3716{
3717 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003718 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303719
3720 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003721 // always send CMD_ERROR for offload streams, this
3722 // is needed e.g. when SSR happens within compress_open
3723 // since the stream is active, offload_callback_thread is also active.
3724 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3725 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003726 }
3727 pthread_mutex_unlock(&out->lock);
3728
3729 status = out_standby(&out->stream.common);
3730
3731 lock_output_stream(out);
3732 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003733 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303734 }
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05303735
3736 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3737 ALOGD("Setting previous card status if offline");
3738 out->prev_card_status_offline = true;
3739 }
3740
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303741 pthread_mutex_unlock(&out->lock);
3742
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003743 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303744}
3745
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303746/*
3747 *standby implementation without locks, assumes that the callee already
3748 *has taken adev and out lock.
3749 */
3750int out_standby_l(struct audio_stream *stream)
3751{
3752 struct stream_out *out = (struct stream_out *)stream;
3753 struct audio_device *adev = out->dev;
3754
3755 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3756 stream, out->usecase, use_case_table[out->usecase]);
3757
3758 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003759 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303760 if (adev->adm_deregister_stream)
3761 adev->adm_deregister_stream(adev->adm_data, out->handle);
3762
3763 if (is_offload_usecase(out->usecase))
3764 stop_compressed_output_l(out);
3765
3766 out->standby = true;
3767 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3768 voice_extn_compress_voip_close_output_stream(stream);
3769 out->started = 0;
3770 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003771 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303772 return 0;
3773 } else if (!is_offload_usecase(out->usecase)) {
3774 if (out->pcm) {
3775 pcm_close(out->pcm);
3776 out->pcm = NULL;
3777 }
3778 } else {
3779 ALOGD("copl(%p):standby", out);
3780 out->send_next_track_params = false;
3781 out->is_compr_metadata_avail = false;
3782 out->gapless_mdata.encoder_delay = 0;
3783 out->gapless_mdata.encoder_padding = 0;
3784 if (out->compr != NULL) {
3785 compress_close(out->compr);
3786 out->compr = NULL;
3787 }
3788 }
3789 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003790 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303791 }
3792 ALOGD("%s: exit", __func__);
3793 return 0;
3794}
3795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003796static int out_dump(const struct audio_stream *stream __unused,
3797 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798{
3799 return 0;
3800}
3801
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003802static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3803{
3804 int ret = 0;
3805 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003806
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003807 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003808 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003809 return -EINVAL;
3810 }
3811
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303812 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003813
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003814 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3815 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303816 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003817 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003818 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3819 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303820 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003821 }
3822
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003823 ALOGV("%s new encoder delay %u and padding %u", __func__,
3824 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3825
3826 return 0;
3827}
3828
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003829static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3830{
3831 return out == adev->primary_output || out == adev->voice_tx_output;
3832}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003833
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303834// note: this call is safe only if the stream_cb is
3835// removed first in close_output_stream (as is done now).
3836static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3837{
3838 if (!stream || !parms)
3839 return;
3840
3841 struct stream_out *out = (struct stream_out *)stream;
3842 struct audio_device *adev = out->dev;
3843
3844 card_status_t status;
3845 int card;
3846 if (parse_snd_card_status(parms, &card, &status) < 0)
3847 return;
3848
3849 pthread_mutex_lock(&adev->lock);
3850 bool valid_cb = (card == adev->snd_card);
3851 pthread_mutex_unlock(&adev->lock);
3852
3853 if (!valid_cb)
3854 return;
3855
3856 lock_output_stream(out);
3857 if (out->card_status != status)
3858 out->card_status = status;
3859 pthread_mutex_unlock(&out->lock);
3860
3861 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3862 use_case_table[out->usecase],
3863 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3864
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303865 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303866 out_on_error(stream);
Aditya Bavanari9aa0b922019-02-05 17:44:57 +05303867 if (voice_is_call_state_active(adev) &&
3868 out == adev->primary_output) {
3869 ALOGD("%s: SSR/PDR occurred, end all calls", __func__);
3870 pthread_mutex_lock(&adev->lock);
3871 voice_stop_call(adev);
3872 adev->mode = AUDIO_MODE_NORMAL;
3873 pthread_mutex_unlock(&adev->lock);
3874 }
3875 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303876 return;
3877}
3878
Kevin Rocardfce19002017-08-07 19:21:36 -07003879static int get_alive_usb_card(struct str_parms* parms) {
3880 int card;
3881 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3882 !audio_extn_usb_alive(card)) {
3883 return card;
3884 }
3885 return -ENODEV;
3886}
3887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3889{
3890 struct stream_out *out = (struct stream_out *)stream;
3891 struct audio_device *adev = out->dev;
3892 struct str_parms *parms;
3893 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003894 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303895 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003896 bool reconfig = false;
3897 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898
sangwoobc677242013-08-08 16:53:43 +09003899 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003900 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303902 if (!parms)
3903 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003904 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3905 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003907 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003908 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003910 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003911 * When HDMI cable is unplugged the music playback is paused and
3912 * the policy manager sends routing=0. But the audioflinger continues
3913 * to write data until standby time (3sec). As the HDMI core is
3914 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003915 * Avoid this by routing audio to speaker until standby.
3916 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003917 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3918 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303919 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003920 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3921 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003922 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303923 /*
3924 * When A2DP is disconnected the
3925 * music playback is paused and the policy manager sends routing=0
3926 * But the audioflingercontinues to write data until standby time
3927 * (3sec). As BT is turned off, the write gets blocked.
3928 * Avoid this by routing audio to speaker until standby.
3929 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003930 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003931 (val == AUDIO_DEVICE_NONE) &&
3932 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303933 val = AUDIO_DEVICE_OUT_SPEAKER;
3934 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303935 /*
3936 * When USB headset is disconnected the music platback paused
3937 * and the policy manager send routing=0. But if the USB is connected
3938 * back before the standby time, AFE is not closed and opened
3939 * when USB is connected back. So routing to speker will guarantee
3940 * AFE reconfiguration and AFE will be opend once USB is connected again
3941 */
3942 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3943 (val == AUDIO_DEVICE_NONE) &&
3944 !audio_extn_usb_connected(parms)) {
3945 val = AUDIO_DEVICE_OUT_SPEAKER;
3946 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303947 /* To avoid a2dp to sco overlapping / BT device improper state
3948 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303949 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303950 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3951 if (!audio_extn_a2dp_is_ready()) {
3952 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3953 //combo usecase just by pass a2dp
3954 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303955 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303956 } else {
3957 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3958 /* update device to a2dp and don't route as BT returned error
3959 * However it is still possible a2dp routing called because
3960 * of current active device disconnection (like wired headset)
3961 */
3962 out->devices = val;
3963 pthread_mutex_unlock(&out->lock);
3964 pthread_mutex_unlock(&adev->lock);
3965 goto error;
3966 }
3967 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303968 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003969
3970 audio_devices_t new_dev = val;
3971
3972 // Workaround: If routing to an non existing usb device, fail gracefully
3973 // The routing request will otherwise block during 10 second
3974 int card;
3975 if (audio_is_usb_out_device(new_dev) &&
3976 (card = get_alive_usb_card(parms)) >= 0) {
3977
3978 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3979 pthread_mutex_unlock(&adev->lock);
3980 pthread_mutex_unlock(&out->lock);
3981 ret = -ENOSYS;
3982 goto routing_fail;
3983 }
3984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003985 /*
3986 * select_devices() call below switches all the usecases on the same
3987 * backend to the new device. Refer to check_usecases_codec_backend() in
3988 * the select_devices(). But how do we undo this?
3989 *
3990 * For example, music playback is active on headset (deep-buffer usecase)
3991 * and if we go to ringtones and select a ringtone, low-latency usecase
3992 * will be started on headset+speaker. As we can't enable headset+speaker
3993 * and headset devices at the same time, select_devices() switches the music
3994 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3995 * So when the ringtone playback is completed, how do we undo the same?
3996 *
3997 * We are relying on the out_set_parameters() call on deep-buffer output,
3998 * once the ringtone playback is ended.
3999 * NOTE: We should not check if the current devices are same as new devices.
4000 * Because select_devices() must be called to switch back the music
4001 * playback to headset.
4002 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004003 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004004 audio_devices_t new_dev = val;
4005 bool same_dev = out->devices == new_dev;
4006 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004007
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004008 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004009 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004010 if (adev->mode == AUDIO_MODE_IN_CALL) {
4011 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004012 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4013 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4014 audio_extn_usb_set_service_interval(true /*playback*/,
4015 service_interval,
4016 &reconfig);
4017 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4018 }
4019 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004020 }
4021 } else {
4022 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004023 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004024 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004025 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004026
4027 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004028 if (!same_dev) {
4029 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304030 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4031 adev->perf_lock_opts,
4032 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004033 if (adev->adm_on_routing_change)
4034 adev->adm_on_routing_change(adev->adm_data,
4035 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004036 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304037 if (!bypass_a2dp) {
4038 select_devices(adev, out->usecase);
4039 } else {
4040 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
4041 select_devices(adev, out->usecase);
4042 out->devices = new_dev;
4043 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004044
4045 if (!same_dev) {
4046 // on device switch force swap, lower functions will make sure
4047 // to check if swap is allowed or not.
4048 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304049 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004050 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304051 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4052 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08004053 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304054 pthread_mutex_lock(&out->compr_mute_lock);
4055 out->a2dp_compress_mute = false;
4056 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4057 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004058 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4059 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304060 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004061 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004062 }
4063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004065 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004067 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004068
4069 if (out == adev->primary_output) {
4070 pthread_mutex_lock(&adev->lock);
4071 audio_extn_set_parameters(adev, parms);
4072 pthread_mutex_unlock(&adev->lock);
4073 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004074 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004075 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004076 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004077
4078 audio_extn_dts_create_state_notifier_node(out->usecase);
4079 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4080 popcount(out->channel_mask),
4081 out->playback_started);
4082
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004083 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004084 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004085
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304086 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4087 sizeof(value));
4088 if (err >= 0) {
4089 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4090 audio_extn_send_dual_mono_mixing_coefficients(out);
4091 }
4092
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304093 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4094 if (err >= 0) {
4095 strlcpy(out->profile, value, sizeof(out->profile));
4096 ALOGV("updating stream profile with value '%s'", out->profile);
4097 lock_output_stream(out);
4098 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4099 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004100 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304101 out->sample_rate, out->bit_width,
4102 out->channel_mask, out->profile,
4103 &out->app_type_cfg);
4104 pthread_mutex_unlock(&out->lock);
4105 }
4106
Alexy Joseph98988832017-01-13 14:56:59 -08004107 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004108 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4109 // and vendor.audio.hal.output.suspend.supported is set to true
4110 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004111 //check suspend parameter only for low latency and if the property
4112 //is enabled
4113 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4114 ALOGI("%s: got suspend_playback %s", __func__, value);
4115 lock_output_stream(out);
4116 if (!strncmp(value, "false", 5)) {
4117 //suspend_playback=false is supposed to set QOS value back to 75%
4118 //the mixer control sent with value Enable will achieve that
4119 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4120 } else if (!strncmp (value, "true", 4)) {
4121 //suspend_playback=true is supposed to remove QOS value
4122 //resetting the mixer control will set the default value
4123 //for the mixer control which is Disable and this removes the QOS vote
4124 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4125 } else {
4126 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4127 " got %s", __func__, value);
4128 ret = -1;
4129 }
4130
4131 if (ret != 0) {
4132 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4133 __func__, out->pm_qos_mixer_path, ret);
4134 }
4135
4136 pthread_mutex_unlock(&out->lock);
4137 }
4138 }
4139 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304141error:
Eric Laurent994a6932013-07-17 11:51:42 -07004142 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 return ret;
4144}
4145
Ramjee Singhacef98f2019-06-28 11:01:25 +05304146#if ANDROID_PLATFORM_SDK_VERSION >= 29
4147static int in_set_microphone_direction(const struct audio_stream_in *stream,
4148 audio_microphone_direction_t dir) {
4149 int ret_val = -ENOSYS;
4150 (void)stream;
4151 (void)dir;
4152 ALOGV("---- in_set_microphone_direction()");
4153 return ret_val;
4154}
4155
4156static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4157 int ret_val = -ENOSYS;
4158 (void)zoom;
4159 (void)stream;
4160 ALOGV("---- in_set_microphone_field_dimension()");
4161 return ret_val;
4162}
4163#endif
4164
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004165static bool stream_get_parameter_channels(struct str_parms *query,
4166 struct str_parms *reply,
4167 audio_channel_mask_t *supported_channel_masks) {
4168 int ret = -1;
4169 char value[512];
4170 bool first = true;
4171 size_t i, j;
4172
4173 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4174 ret = 0;
4175 value[0] = '\0';
4176 i = 0;
4177 while (supported_channel_masks[i] != 0) {
4178 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4179 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4180 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304181 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004182
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304183 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004184 first = false;
4185 break;
4186 }
4187 }
4188 i++;
4189 }
4190 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4191 }
4192 return ret == 0;
4193}
4194
4195static bool stream_get_parameter_formats(struct str_parms *query,
4196 struct str_parms *reply,
4197 audio_format_t *supported_formats) {
4198 int ret = -1;
4199 char value[256];
4200 size_t i, j;
4201 bool first = true;
4202
4203 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4204 ret = 0;
4205 value[0] = '\0';
4206 i = 0;
4207 while (supported_formats[i] != 0) {
4208 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4209 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4210 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304211 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004212 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304213 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004214 first = false;
4215 break;
4216 }
4217 }
4218 i++;
4219 }
4220 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4221 }
4222 return ret == 0;
4223}
4224
4225static bool stream_get_parameter_rates(struct str_parms *query,
4226 struct str_parms *reply,
4227 uint32_t *supported_sample_rates) {
4228
4229 int i;
4230 char value[256];
4231 int ret = -1;
4232 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4233 ret = 0;
4234 value[0] = '\0';
4235 i=0;
4236 int cursor = 0;
4237 while (supported_sample_rates[i]) {
4238 int avail = sizeof(value) - cursor;
4239 ret = snprintf(value + cursor, avail, "%s%d",
4240 cursor > 0 ? "|" : "",
4241 supported_sample_rates[i]);
4242 if (ret < 0 || ret >= avail) {
4243 // if cursor is at the last element of the array
4244 // overwrite with \0 is duplicate work as
4245 // snprintf already put a \0 in place.
4246 // else
4247 // we had space to write the '|' at value[cursor]
4248 // (which will be overwritten) or no space to fill
4249 // the first element (=> cursor == 0)
4250 value[cursor] = '\0';
4251 break;
4252 }
4253 cursor += ret;
4254 ++i;
4255 }
4256 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4257 value);
4258 }
4259 return ret >= 0;
4260}
4261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4263{
4264 struct stream_out *out = (struct stream_out *)stream;
4265 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004266 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 char value[256];
4268 struct str_parms *reply = str_parms_create();
4269 size_t i, j;
4270 int ret;
4271 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004272
4273 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004274 if (reply) {
4275 str_parms_destroy(reply);
4276 }
4277 if (query) {
4278 str_parms_destroy(query);
4279 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004280 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4281 return NULL;
4282 }
4283
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004284 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4286 if (ret >= 0) {
4287 value[0] = '\0';
4288 i = 0;
4289 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004290 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4291 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004293 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004295 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 first = false;
4297 break;
4298 }
4299 }
4300 i++;
4301 }
4302 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4303 str = str_parms_to_str(reply);
4304 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004305 voice_extn_out_get_parameters(out, query, reply);
4306 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004308
Alexy Joseph62142aa2015-11-16 15:10:34 -08004309
4310 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4311 if (ret >= 0) {
4312 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304313 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4314 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004315 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304316 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004317 } else {
4318 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304319 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004320 }
4321 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004322 if (str)
4323 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004324 str = str_parms_to_str(reply);
4325 }
4326
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004327 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4328 if (ret >= 0) {
4329 value[0] = '\0';
4330 i = 0;
4331 first = true;
4332 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004333 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4334 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004335 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004336 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004337 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004338 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004339 first = false;
4340 break;
4341 }
4342 }
4343 i++;
4344 }
4345 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004346 if (str)
4347 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004348 str = str_parms_to_str(reply);
4349 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004350
4351 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4352 if (ret >= 0) {
4353 value[0] = '\0';
4354 i = 0;
4355 first = true;
4356 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004357 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4358 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004359 if (!first) {
4360 strlcat(value, "|", sizeof(value));
4361 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004362 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004363 first = false;
4364 break;
4365 }
4366 }
4367 i++;
4368 }
4369 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4370 if (str)
4371 free(str);
4372 str = str_parms_to_str(reply);
4373 }
4374
Alexy Joseph98988832017-01-13 14:56:59 -08004375 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4376 //only low latency track supports suspend_resume
4377 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004378 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004379 if (str)
4380 free(str);
4381 str = str_parms_to_str(reply);
4382 }
4383
4384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385 str_parms_destroy(query);
4386 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004387 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 return str;
4389}
4390
4391static uint32_t out_get_latency(const struct audio_stream_out *stream)
4392{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004393 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004395 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396
Alexy Josephaa54c872014-12-03 02:46:47 -08004397 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304398 lock_output_stream(out);
4399 latency = audio_extn_utils_compress_get_dsp_latency(out);
4400 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004401 } else if ((out->realtime) ||
4402 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004403 // since the buffer won't be filled up faster than realtime,
4404 // return a smaller number
4405 if (out->config.rate)
4406 period_ms = (out->af_period_multiplier * out->config.period_size *
4407 1000) / (out->config.rate);
4408 else
4409 period_ms = 0;
4410 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004411 } else {
4412 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004413 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004414 }
4415
yidongh0515e042017-07-06 15:00:34 +08004416 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004417 latency += audio_extn_a2dp_get_encoder_latency();
4418
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304419 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004420 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421}
4422
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304423static float AmpToDb(float amplification)
4424{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304425 float db = DSD_VOLUME_MIN_DB;
4426 if (amplification > 0) {
4427 db = 20 * log10(amplification);
4428 if(db < DSD_VOLUME_MIN_DB)
4429 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304430 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304431 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304432}
4433
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004434static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4435 float right)
4436{
4437 struct stream_out *out = (struct stream_out *)stream;
4438 long volume = 0;
4439 char mixer_ctl_name[128] = "";
4440 struct audio_device *adev = out->dev;
4441 struct mixer_ctl *ctl = NULL;
4442 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4443 PCM_PLAYBACK);
4444
4445 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4446 "Playback %d Volume", pcm_device_id);
4447 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4448 if (!ctl) {
4449 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4450 __func__, mixer_ctl_name);
4451 return -EINVAL;
4452 }
4453 if (left != right)
4454 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4455 __func__, left, right);
4456 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4457 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4458 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4459 __func__, mixer_ctl_name, volume);
4460 return -EINVAL;
4461 }
4462 return 0;
4463}
4464
4465
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304466static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4467 float right)
4468{
4469 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304470 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304471 char mixer_ctl_name[128];
4472 struct audio_device *adev = out->dev;
4473 struct mixer_ctl *ctl;
4474 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4475 PCM_PLAYBACK);
4476
4477 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4478 "Compress Playback %d Volume", pcm_device_id);
4479 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4480 if (!ctl) {
4481 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4482 __func__, mixer_ctl_name);
4483 return -EINVAL;
4484 }
4485 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4486 __func__, mixer_ctl_name, left, right);
4487 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4488 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4489 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4490
4491 return 0;
4492}
4493
Zhou Song2b8f28f2017-09-11 10:51:38 +08004494static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4495 float right)
4496{
4497 struct stream_out *out = (struct stream_out *)stream;
4498 char mixer_ctl_name[] = "App Type Gain";
4499 struct audio_device *adev = out->dev;
4500 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304501 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004502
4503 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4504 if (!ctl) {
4505 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4506 __func__, mixer_ctl_name);
4507 return -EINVAL;
4508 }
4509
4510 set_values[0] = 0; //0: Rx Session 1:Tx Session
4511 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304512 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4513 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004514
4515 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4516 return 0;
4517}
4518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519static int out_set_volume(struct audio_stream_out *stream, float left,
4520 float right)
4521{
Eric Laurenta9024de2013-04-04 09:19:12 -07004522 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004523 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304524 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004526 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
4527
Eric Laurenta9024de2013-04-04 09:19:12 -07004528 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4529 /* only take left channel into account: the API is for stereo anyway */
4530 out->muted = (left == 0.0f);
4531 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004532 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304533 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004534 /*
4535 * Set mute or umute on HDMI passthrough stream.
4536 * Only take left channel into account.
4537 * Mute is 0 and unmute 1
4538 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304539 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304540 } else if (out->format == AUDIO_FORMAT_DSD){
4541 char mixer_ctl_name[128] = "DSD Volume";
4542 struct audio_device *adev = out->dev;
4543 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4544
4545 if (!ctl) {
4546 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4547 __func__, mixer_ctl_name);
4548 return -EINVAL;
4549 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304550 volume[0] = (long)(AmpToDb(left));
4551 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304552 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4553 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004554 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304555 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004556 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304557 if (!out->a2dp_compress_mute)
4558 ret = out_set_compr_volume(stream, left, right);
4559 out->volume_l = left;
4560 out->volume_r = right;
4561 pthread_mutex_unlock(&out->compr_mute_lock);
4562 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004563 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004564 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004565 if (!out->standby)
4566 ret = out_set_voip_volume(stream, left, right);
4567 out->volume_l = left;
4568 out->volume_r = right;
4569 return ret;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07004570 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4571 ALOGV("%s: MMAP set volume called", __func__);
4572 if (!out->standby)
4573 ret = out_set_mmap_volume(stream, left, right);
4574 out->volume_l = left;
4575 out->volume_r = right;
4576 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004577 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 return -ENOSYS;
4580}
4581
Zhou Songc9672822017-08-16 16:01:39 +08004582static void update_frames_written(struct stream_out *out, size_t bytes)
4583{
4584 size_t bpf = 0;
4585
4586 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4587 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4588 bpf = 1;
4589 else if (!is_offload_usecase(out->usecase))
4590 bpf = audio_bytes_per_sample(out->format) *
4591 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004592
4593 pthread_mutex_lock(&out->position_query_lock);
4594 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004595 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004596 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4597 }
4598 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004599}
4600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4602 size_t bytes)
4603{
4604 struct stream_out *out = (struct stream_out *)stream;
4605 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004606 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304607 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004608 const size_t frame_size = audio_stream_out_frame_size(stream);
4609 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304610 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611
Haynes Mathew George380745d2017-10-04 15:27:45 -07004612 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004613 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304614
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304615 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004616
Dhananjay Kumarac341582017-02-23 23:42:25 +05304617 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304618 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304619 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4620 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004621 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304622 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304623 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304624 ALOGD(" %s: sound card is not active/SSR state", __func__);
4625 ret= -EIO;
4626 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304627 }
4628 }
4629
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304630 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304631 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304632 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304633 goto exit;
4634 }
4635
Haynes Mathew George16081042017-05-31 17:16:49 -07004636 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4637 ret = -EINVAL;
4638 goto exit;
4639 }
4640
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304641 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4642 !out->is_iec61937_info_available) {
4643
4644 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4645 out->is_iec61937_info_available = true;
4646 } else if (audio_extn_passthru_is_enabled()) {
4647 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304648 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304649
4650 if((out->format == AUDIO_FORMAT_DTS) ||
4651 (out->format == AUDIO_FORMAT_DTS_HD)) {
4652 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4653 buffer, bytes);
4654 if (ret) {
4655 if (ret != -ENOSYS) {
4656 out->is_iec61937_info_available = false;
4657 ALOGD("iec61937 transmission info not yet updated retry");
4658 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304659 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304660 /* if stream has started and after that there is
4661 * stream config change (iec transmission config)
4662 * then trigger select_device to update backend configuration.
4663 */
4664 out->stream_config_changed = true;
4665 pthread_mutex_lock(&adev->lock);
4666 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304667 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4668 ret = -EINVAL;
4669 goto exit;
4670 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304671 pthread_mutex_unlock(&adev->lock);
4672 out->stream_config_changed = false;
4673 out->is_iec61937_info_available = true;
4674 }
4675 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304676
Garmond Leung317cbf12017-09-13 16:20:50 -07004677 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304678 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4679 (out->is_iec61937_info_available == true)) {
4680 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4681 ret = -EINVAL;
4682 goto exit;
4683 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304684 }
4685 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304686
4687 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4688 (audio_extn_a2dp_is_suspended())) {
4689 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4690 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304691 ret = -EIO;
4692 goto exit;
4693 }
4694 }
4695 }
4696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004698 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004699 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004700 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4701 ret = voice_extn_compress_voip_start_output_stream(out);
4702 else
4703 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004704 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004705 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004707 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 goto exit;
4709 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304710 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004711 if (last_known_cal_step != -1) {
4712 ALOGD("%s: retry previous failed cal level set", __func__);
4713 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304714 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004715 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304716
4717 if ((out->is_iec61937_info_available == true) &&
4718 (audio_extn_passthru_is_passthrough_stream(out))&&
4719 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4720 ret = -EINVAL;
4721 goto exit;
4722 }
Surendar Karka5a18a7a2018-04-26 11:28:38 +05304723 if (out->set_dual_mono)
4724 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726
Ashish Jain81eb2a82015-05-13 10:52:34 +05304727 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004728 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304729 adev->is_channel_status_set = true;
4730 }
4731
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05304732 if ((adev->use_old_pspd_mix_ctrl == true) &&
4733 (out->pspd_coeff_sent == false)) {
4734 /*
4735 * Need to resend pspd coefficients after stream started for
4736 * older kernel version as it does not save the coefficients
4737 * and also stream has to be started for coeff to apply.
4738 */
4739 usecase = get_usecase_from_list(adev, out->usecase);
4740 if (usecase != NULL) {
4741 audio_extn_set_custom_mtmx_params(adev, usecase, true);
4742 out->pspd_coeff_sent = true;
4743 }
4744 }
4745
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004746 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004747 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004748 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004749 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004750 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4751 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304752 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4753 ALOGD("copl(%p):send next track params in gapless", out);
4754 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4755 out->send_next_track_params = false;
4756 out->is_compr_metadata_avail = false;
4757 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004758 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304759 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304760 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004761
Ashish Jain83a6cc22016-06-28 14:34:17 +05304762 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304763 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304764 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304765 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004766 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304767 return -EINVAL;
4768 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304769 audio_format_t dst_format = out->hal_op_format;
4770 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304771
4772 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4773 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4774
Ashish Jain83a6cc22016-06-28 14:34:17 +05304775 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304776 dst_format,
4777 buffer,
4778 src_format,
4779 frames);
4780
Ashish Jain83a6cc22016-06-28 14:34:17 +05304781 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304782 bytes_to_write);
4783
4784 /*Convert written bytes in audio flinger format*/
4785 if (ret > 0)
4786 ret = ((ret * format_to_bitwidth_table[out->format]) /
4787 format_to_bitwidth_table[dst_format]);
4788 }
4789 } else
4790 ret = compress_write(out->compr, buffer, bytes);
4791
Zhou Songc9672822017-08-16 16:01:39 +08004792 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4793 update_frames_written(out, bytes);
4794
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304795 if (ret < 0)
4796 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004797 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304798 /*msg to cb thread only if non blocking write is enabled*/
4799 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304800 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004801 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304802 } else if (-ENETRESET == ret) {
4803 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304804 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304805 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304806 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004807 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304808 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004809 }
Ashish Jain5106d362016-05-11 19:23:33 +05304810
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304811 /* Call compr start only when non-zero bytes of data is there to be rendered */
4812 if (!out->playback_started && ret > 0) {
4813 int status = compress_start(out->compr);
4814 if (status < 0) {
4815 ret = status;
4816 ALOGE("%s: compr start failed with err %d", __func__, errno);
4817 goto exit;
4818 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004819 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004820 out->playback_started = 1;
4821 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004822
4823 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4824 popcount(out->channel_mask),
4825 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004826 }
4827 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004828 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004829 return ret;
4830 } else {
4831 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004832 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004833 if (out->muted)
4834 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004835 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4836 __func__, frames, frame_size, bytes_to_write);
4837
Arun Mirpuridbef0c72018-09-12 18:36:10 -07004838 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4839 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004840 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4841 int16_t *src = (int16_t *)buffer;
4842 int16_t *dst = (int16_t *)buffer;
4843
4844 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4845 out->format != AUDIO_FORMAT_PCM_16_BIT,
4846 "out_write called for incall music use case with wrong properties");
4847
4848 /*
4849 * FIXME: this can be removed once audio flinger mixer supports
4850 * mono output
4851 */
4852
4853 /*
4854 * Code below goes over each frame in the buffer and adds both
4855 * L and R samples and then divides by 2 to convert to mono
4856 */
4857 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4858 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4859 }
4860 bytes_to_write /= 2;
4861 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004862
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304863 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004864
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004865 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004866
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004867 if (out->config.rate)
4868 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4869 out->config.rate;
4870
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004871 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004872 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4873
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004874 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004875 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004876 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304877 out->convert_buffer != NULL) {
4878
4879 memcpy_by_audio_format(out->convert_buffer,
4880 out->hal_op_format,
4881 buffer,
4882 out->hal_ip_format,
4883 out->config.period_size * out->config.channels);
4884
4885 ret = pcm_write(out->pcm, out->convert_buffer,
4886 (out->config.period_size *
4887 out->config.channels *
4888 format_to_bitwidth_table[out->hal_op_format]));
4889 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304890 /*
4891 * To avoid underrun in DSP when the application is not pumping
4892 * data at required rate, check for the no. of bytes and ignore
4893 * pcm_write if it is less than actual buffer size.
4894 * It is a work around to a change in compress VOIP driver.
4895 */
4896 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4897 bytes < (out->config.period_size * out->config.channels *
4898 audio_bytes_per_sample(out->format))) {
4899 size_t voip_buf_size =
4900 out->config.period_size * out->config.channels *
4901 audio_bytes_per_sample(out->format);
4902 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4903 __func__, bytes, voip_buf_size);
4904 usleep(((uint64_t)voip_buf_size - bytes) *
4905 1000000 / audio_stream_out_frame_size(stream) /
4906 out_get_sample_rate(&out->stream.common));
4907 ret = 0;
4908 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004909 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304910 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004911
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004912 release_out_focus(out);
4913
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304914 if (ret < 0)
4915 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004916 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304917 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004918 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 }
4920
4921exit:
Zhou Songc9672822017-08-16 16:01:39 +08004922 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304923 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304924 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004926 pthread_mutex_unlock(&out->lock);
4927
4928 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004929 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004930 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304931 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304932 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304933 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304934 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304935 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304936 out->standby = true;
4937 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304938 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304939 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4940 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4941 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004942
4943 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304944 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004945 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004946 return ret;
4947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004949 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 return bytes;
4951}
4952
4953static int out_get_render_position(const struct audio_stream_out *stream,
4954 uint32_t *dsp_frames)
4955{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004956 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004957
4958 if (dsp_frames == NULL)
4959 return -EINVAL;
4960
4961 *dsp_frames = 0;
4962 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004963 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304964
4965 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4966 * this operation and adev_close_output_stream(where out gets reset).
4967 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304968 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004969 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304970 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004971 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304972 return 0;
4973 }
4974
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004975 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304976 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304977 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004978 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304979 if (ret < 0)
4980 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004981 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304982 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004983 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304984 if (-ENETRESET == ret) {
4985 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304986 out->card_status = CARD_STATUS_OFFLINE;
4987 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304988 } else if(ret < 0) {
4989 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304990 ret = -EINVAL;
4991 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304992 /*
4993 * Handle corner case where compress session is closed during SSR
4994 * and timestamp is queried
4995 */
4996 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304997 ret = -EINVAL;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05304998 } else if (out->prev_card_status_offline) {
4999 ALOGE("ERROR: previously sound card was offline,return error");
5000 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305001 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305002 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005003 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305004 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305005 pthread_mutex_unlock(&out->lock);
5006 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005007 } else if (audio_is_linear_pcm(out->format)) {
5008 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005009 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005010 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005011 } else
5012 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013}
5014
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005015static int out_add_audio_effect(const struct audio_stream *stream __unused,
5016 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017{
5018 return 0;
5019}
5020
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005021static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5022 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005023{
5024 return 0;
5025}
5026
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005027static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5028 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005029{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305030 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031}
5032
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005033static int out_get_presentation_position(const struct audio_stream_out *stream,
5034 uint64_t *frames, struct timespec *timestamp)
5035{
5036 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305037 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005038 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005039
Ashish Jain5106d362016-05-11 19:23:33 +05305040 /* below piece of code is not guarded against any lock because audioFliner serializes
5041 * this operation and adev_close_output_stream( where out gets reset).
5042 */
5043 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305044 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005045 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305046 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5047 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5048 return 0;
5049 }
5050
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005051 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005052
Ashish Jain5106d362016-05-11 19:23:33 +05305053 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5054 ret = compress_get_tstamp(out->compr, &dsp_frames,
5055 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005056 // Adjustment accounts for A2dp encoder latency with offload usecases
5057 // Note: Encoder latency is returned in ms.
5058 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5059 unsigned long offset =
5060 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5061 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5062 }
Ashish Jain5106d362016-05-11 19:23:33 +05305063 ALOGVV("%s rendered frames %ld sample_rate %d",
5064 __func__, dsp_frames, out->sample_rate);
5065 *frames = dsp_frames;
5066 if (ret < 0)
5067 ret = -errno;
5068 if (-ENETRESET == ret) {
5069 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305070 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305071 ret = -EINVAL;
5072 } else
5073 ret = 0;
5074 /* this is the best we can do */
5075 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005076 } else {
5077 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005078 unsigned int avail;
5079 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5080 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5081 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5082 // This adjustment accounts for buffering after app processor.
5083 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005084 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005085 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005086
Weiyin Jiangd4633762018-03-16 12:05:03 +08005087 // Adjustment accounts for A2dp encoder latency with non offload usecases
5088 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5089 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5090 signed_frames -=
5091 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5092 }
5093
5094 // It would be unusual for this value to be negative, but check just in case ...
5095 if (signed_frames >= 0) {
5096 *frames = signed_frames;
5097 ret = 0;
5098 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005099 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305100 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305101 *frames = out->written;
5102 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05305103 if (is_offload_usecase(out->usecase))
5104 ret = -EINVAL;
5105 else
5106 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005107 }
5108 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005109 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005110 return ret;
5111}
5112
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005113static int out_set_callback(struct audio_stream_out *stream,
5114 stream_callback_t callback, void *cookie)
5115{
5116 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005117 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005118
5119 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005120 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005121 out->client_callback = callback;
5122 out->client_cookie = cookie;
5123 if (out->adsp_hdlr_stream_handle) {
5124 ret = audio_extn_adsp_hdlr_stream_set_callback(
5125 out->adsp_hdlr_stream_handle,
5126 callback,
5127 cookie);
5128 if (ret)
5129 ALOGW("%s:adsp hdlr callback registration failed %d",
5130 __func__, ret);
5131 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005132 pthread_mutex_unlock(&out->lock);
5133 return 0;
5134}
5135
5136static int out_pause(struct audio_stream_out* stream)
5137{
5138 struct stream_out *out = (struct stream_out *)stream;
5139 int status = -ENOSYS;
5140 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005141 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005142 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005143 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005144 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305145 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305146 status = compress_pause(out->compr);
5147
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005148 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005149
Mingming Yin21854652016-04-13 11:54:02 -07005150 if (audio_extn_passthru_is_active()) {
5151 ALOGV("offload use case, pause passthru");
5152 audio_extn_passthru_on_pause(out);
5153 }
5154
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305155 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005156 audio_extn_dts_notify_playback_state(out->usecase, 0,
5157 out->sample_rate, popcount(out->channel_mask),
5158 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005159 }
5160 pthread_mutex_unlock(&out->lock);
5161 }
5162 return status;
5163}
5164
5165static int out_resume(struct audio_stream_out* stream)
5166{
5167 struct stream_out *out = (struct stream_out *)stream;
5168 int status = -ENOSYS;
5169 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005170 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005171 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005172 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005173 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005174 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305175 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305176 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005177 }
5178 if (!status) {
5179 out->offload_state = OFFLOAD_STATE_PLAYING;
5180 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305181 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005182 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5183 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005184 }
5185 pthread_mutex_unlock(&out->lock);
5186 }
5187 return status;
5188}
5189
5190static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5191{
5192 struct stream_out *out = (struct stream_out *)stream;
5193 int status = -ENOSYS;
5194 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005195 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005196 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005197 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5198 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5199 else
5200 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5201 pthread_mutex_unlock(&out->lock);
5202 }
5203 return status;
5204}
5205
5206static int out_flush(struct audio_stream_out* stream)
5207{
5208 struct stream_out *out = (struct stream_out *)stream;
5209 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005210 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005211 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005212 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005213 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5214 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005215 } else {
5216 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5217 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005218 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005219 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005220 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005221 return 0;
5222 }
5223 return -ENOSYS;
5224}
5225
Haynes Mathew George16081042017-05-31 17:16:49 -07005226static int out_stop(const struct audio_stream_out* stream)
5227{
5228 struct stream_out *out = (struct stream_out *)stream;
5229 struct audio_device *adev = out->dev;
5230 int ret = -ENOSYS;
5231
5232 ALOGV("%s", __func__);
5233 pthread_mutex_lock(&adev->lock);
5234 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5235 out->playback_started && out->pcm != NULL) {
5236 pcm_stop(out->pcm);
5237 ret = stop_output_stream(out);
5238 out->playback_started = false;
5239 }
5240 pthread_mutex_unlock(&adev->lock);
5241 return ret;
5242}
5243
5244static int out_start(const struct audio_stream_out* stream)
5245{
5246 struct stream_out *out = (struct stream_out *)stream;
5247 struct audio_device *adev = out->dev;
5248 int ret = -ENOSYS;
5249
5250 ALOGV("%s", __func__);
5251 pthread_mutex_lock(&adev->lock);
5252 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5253 !out->playback_started && out->pcm != NULL) {
5254 ret = start_output_stream(out);
5255 if (ret == 0) {
5256 out->playback_started = true;
5257 }
5258 }
5259 pthread_mutex_unlock(&adev->lock);
5260 return ret;
5261}
5262
5263/*
5264 * Modify config->period_count based on min_size_frames
5265 */
5266static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5267{
5268 int periodCountRequested = (min_size_frames + config->period_size - 1)
5269 / config->period_size;
5270 int periodCount = MMAP_PERIOD_COUNT_MIN;
5271
5272 ALOGV("%s original config.period_size = %d config.period_count = %d",
5273 __func__, config->period_size, config->period_count);
5274
5275 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5276 periodCount *= 2;
5277 }
5278 config->period_count = periodCount;
5279
5280 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5281}
5282
5283static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5284 int32_t min_size_frames,
5285 struct audio_mmap_buffer_info *info)
5286{
5287 struct stream_out *out = (struct stream_out *)stream;
5288 struct audio_device *adev = out->dev;
5289 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005290 unsigned int offset1 = 0;
5291 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005292 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005293 uint32_t mmap_size;
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005294 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005295
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005296 ALOGD("%s", __func__);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305297 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005298 pthread_mutex_lock(&adev->lock);
5299
Sharad Sangle90e613f2018-05-04 16:15:38 +05305300 if (CARD_STATUS_OFFLINE == out->card_status ||
5301 CARD_STATUS_OFFLINE == adev->card_status) {
5302 ALOGW("out->card_status or adev->card_status offline, try again");
5303 ret = -EIO;
5304 goto exit;
5305 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005306 if (info == NULL || min_size_frames == 0) {
5307 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5308 ret = -EINVAL;
5309 goto exit;
5310 }
5311 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5312 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5313 ret = -ENOSYS;
5314 goto exit;
5315 }
5316 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5317 if (out->pcm_device_id < 0) {
5318 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5319 __func__, out->pcm_device_id, out->usecase);
5320 ret = -EINVAL;
5321 goto exit;
5322 }
5323
5324 adjust_mmap_period_count(&out->config, min_size_frames);
5325
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005326 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005327 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5328 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5329 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305330 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
5331 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5332 out->card_status = CARD_STATUS_OFFLINE;
5333 adev->card_status = CARD_STATUS_OFFLINE;
5334 ret = -EIO;
5335 goto exit;
5336 }
5337
Haynes Mathew George16081042017-05-31 17:16:49 -07005338 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5339 step = "open";
5340 ret = -ENODEV;
5341 goto exit;
5342 }
5343 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5344 if (ret < 0) {
5345 step = "begin";
5346 goto exit;
5347 }
5348 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005349 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005350 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005351 ret = platform_get_mmap_data_fd(adev->platform,
5352 out->pcm_device_id, 0 /*playback*/,
5353 &info->shared_memory_fd,
5354 &mmap_size);
5355 if (ret < 0) {
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005356 // Fall back to non exclusive mode
5357 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5358 } else {
5359 if (mmap_size < buffer_size) {
5360 step = "mmap";
5361 goto exit;
5362 }
5363 // FIXME: indicate exclusive mode support by returning a negative buffer size
5364 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005365 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005366 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07005367
5368 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5369 if (ret < 0) {
5370 step = "commit";
5371 goto exit;
5372 }
5373
5374 out->standby = false;
5375 ret = 0;
5376
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005377 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005378 __func__, info->shared_memory_address, info->buffer_size_frames);
5379
5380exit:
5381 if (ret != 0) {
5382 if (out->pcm == NULL) {
5383 ALOGE("%s: %s - %d", __func__, step, ret);
5384 } else {
5385 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5386 pcm_close(out->pcm);
5387 out->pcm = NULL;
5388 }
5389 }
5390 pthread_mutex_unlock(&adev->lock);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305391 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005392 return ret;
5393}
5394
5395static int out_get_mmap_position(const struct audio_stream_out *stream,
5396 struct audio_mmap_position *position)
5397{
5398 struct stream_out *out = (struct stream_out *)stream;
5399 ALOGVV("%s", __func__);
5400 if (position == NULL) {
5401 return -EINVAL;
5402 }
5403 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005404 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005405 return -ENOSYS;
5406 }
5407 if (out->pcm == NULL) {
5408 return -ENOSYS;
5409 }
5410
5411 struct timespec ts = { 0, 0 };
5412 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5413 if (ret < 0) {
5414 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5415 return ret;
5416 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005417 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005418 return 0;
5419}
5420
5421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422/** audio_stream_in implementation **/
5423static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5424{
5425 struct stream_in *in = (struct stream_in *)stream;
5426
5427 return in->config.rate;
5428}
5429
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005430static int in_set_sample_rate(struct audio_stream *stream __unused,
5431 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432{
5433 return -ENOSYS;
5434}
5435
5436static size_t in_get_buffer_size(const struct audio_stream *stream)
5437{
5438 struct stream_in *in = (struct stream_in *)stream;
5439
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005440 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5441 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005442 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5443 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 -07005444 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5445 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305446 else if(audio_extn_cin_attached_usecase(in->usecase))
5447 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005448
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005449 return in->config.period_size * in->af_period_multiplier *
5450 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451}
5452
5453static uint32_t in_get_channels(const struct audio_stream *stream)
5454{
5455 struct stream_in *in = (struct stream_in *)stream;
5456
5457 return in->channel_mask;
5458}
5459
5460static audio_format_t in_get_format(const struct audio_stream *stream)
5461{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005462 struct stream_in *in = (struct stream_in *)stream;
5463
5464 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005465}
5466
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005467static int in_set_format(struct audio_stream *stream __unused,
5468 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469{
5470 return -ENOSYS;
5471}
5472
5473static int in_standby(struct audio_stream *stream)
5474{
5475 struct stream_in *in = (struct stream_in *)stream;
5476 struct audio_device *adev = in->dev;
5477 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305478 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5479 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005480 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305481
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005482 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005483 if (!in->standby && in->is_st_session) {
5484 ALOGD("%s: sound trigger pcm stop lab", __func__);
5485 audio_extn_sound_trigger_stop_lab(in);
5486 in->standby = 1;
5487 }
5488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005489 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005490 if (adev->adm_deregister_stream)
5491 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5492
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005493 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005495 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005496 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005497 voice_extn_compress_voip_close_input_stream(stream);
5498 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005499 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5500 do_stop = in->capture_started;
5501 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005502 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305503 if (audio_extn_cin_attached_usecase(in->usecase))
5504 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005505 }
5506
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005507 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005508 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005509 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005510 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005511 in->pcm = NULL;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005512 }
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005513
5514 if (do_stop)
5515 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005516 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005517 }
5518 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005519 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005520 return status;
5521}
5522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005523static int in_dump(const struct audio_stream *stream __unused,
5524 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005525{
5526 return 0;
5527}
5528
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305529static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5530{
5531 if (!stream || !parms)
5532 return;
5533
5534 struct stream_in *in = (struct stream_in *)stream;
5535 struct audio_device *adev = in->dev;
5536
5537 card_status_t status;
5538 int card;
5539 if (parse_snd_card_status(parms, &card, &status) < 0)
5540 return;
5541
5542 pthread_mutex_lock(&adev->lock);
5543 bool valid_cb = (card == adev->snd_card);
5544 pthread_mutex_unlock(&adev->lock);
5545
5546 if (!valid_cb)
5547 return;
5548
5549 lock_input_stream(in);
5550 if (in->card_status != status)
5551 in->card_status = status;
5552 pthread_mutex_unlock(&in->lock);
5553
5554 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5555 use_case_table[in->usecase],
5556 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5557
5558 // a better solution would be to report error back to AF and let
5559 // it put the stream to standby
5560 if (status == CARD_STATUS_OFFLINE)
5561 in_standby(&in->stream.common);
5562
5563 return;
5564}
5565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005566static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5567{
5568 struct stream_in *in = (struct stream_in *)stream;
5569 struct audio_device *adev = in->dev;
5570 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005572 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305574 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005575 parms = str_parms_create_str(kvpairs);
5576
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305577 if (!parms)
5578 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005579 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005580 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005581
5582 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5583 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005584 val = atoi(value);
5585 /* no audio source uses val == 0 */
5586 if ((in->source != val) && (val != 0)) {
5587 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005588 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5589 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5590 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005591 (in->config.rate == 8000 || in->config.rate == 16000 ||
5592 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005593 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005594 err = voice_extn_compress_voip_open_input_stream(in);
5595 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005596 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005597 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005598 }
5599 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 }
5601 }
5602
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005603 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5604 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005606 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5607
5608 // Workaround: If routing to an non existing usb device, fail gracefully
5609 // The routing request will otherwise block during 10 second
5610 int card;
5611 if (audio_is_usb_in_device(val) &&
5612 (card = get_alive_usb_card(parms)) >= 0) {
5613
5614 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5615 ret = -ENOSYS;
5616 } else {
5617
5618 in->device = val;
5619 /* If recording is in progress, change the tx device to new device */
5620 if (!in->standby && !in->is_st_session) {
5621 ALOGV("update input routing change");
5622 // inform adm before actual routing to prevent glitches.
5623 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005624 adev->adm_on_routing_change(adev->adm_data,
5625 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005626 ret = select_devices(adev, in->usecase);
5627 }
5628 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005630 }
5631 }
5632
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305633 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5634 if (err >= 0) {
5635 strlcpy(in->profile, value, sizeof(in->profile));
5636 ALOGV("updating stream profile with value '%s'", in->profile);
5637 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5638 &adev->streams_input_cfg_list,
5639 in->device, in->flags, in->format,
5640 in->sample_rate, in->bit_width,
5641 in->profile, &in->app_type_cfg);
5642 }
5643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005644 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005645 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005646
5647 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305648error:
Eric Laurent994a6932013-07-17 11:51:42 -07005649 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005650 return ret;
5651}
5652
5653static char* in_get_parameters(const struct audio_stream *stream,
5654 const char *keys)
5655{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005656 struct stream_in *in = (struct stream_in *)stream;
5657 struct str_parms *query = str_parms_create_str(keys);
5658 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005659 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005660
5661 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005662 if (reply) {
5663 str_parms_destroy(reply);
5664 }
5665 if (query) {
5666 str_parms_destroy(query);
5667 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005668 ALOGE("in_get_parameters: failed to create query or reply");
5669 return NULL;
5670 }
5671
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005672 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005673
5674 voice_extn_in_get_parameters(in, query, reply);
5675
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005676 stream_get_parameter_channels(query, reply,
5677 &in->supported_channel_masks[0]);
5678 stream_get_parameter_formats(query, reply,
5679 &in->supported_formats[0]);
5680 stream_get_parameter_rates(query, reply,
5681 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005682 str = str_parms_to_str(reply);
5683 str_parms_destroy(query);
5684 str_parms_destroy(reply);
5685
5686 ALOGV("%s: exit: returns - %s", __func__, str);
5687 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005688}
5689
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005690static int in_set_gain(struct audio_stream_in *stream __unused,
5691 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005692{
5693 return 0;
5694}
5695
5696static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5697 size_t bytes)
5698{
5699 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305700
5701 if (in == NULL) {
5702 ALOGE("%s: stream_in ptr is NULL", __func__);
5703 return -EINVAL;
5704 }
5705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005706 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305707 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305708 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005710 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305711
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005712 if (in->is_st_session) {
5713 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5714 /* Read from sound trigger HAL */
5715 audio_extn_sound_trigger_read(in, buffer, bytes);
5716 pthread_mutex_unlock(&in->lock);
5717 return bytes;
5718 }
5719
Haynes Mathew George16081042017-05-31 17:16:49 -07005720 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5721 ret = -ENOSYS;
5722 goto exit;
5723 }
5724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005726 pthread_mutex_lock(&adev->lock);
5727 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5728 ret = voice_extn_compress_voip_start_input_stream(in);
5729 else
5730 ret = start_input_stream(in);
5731 pthread_mutex_unlock(&adev->lock);
5732 if (ret != 0) {
5733 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005734 }
5735 in->standby = 0;
5736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005737
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005738 // what's the duration requested by the client?
5739 long ns = 0;
5740
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305741 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005742 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5743 in->config.rate;
5744
5745 request_in_focus(in, ns);
5746 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005747
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305748 if (audio_extn_cin_attached_usecase(in->usecase)) {
5749 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5750 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305751 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005752 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305753 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005754 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005755 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005756 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005757 } else if (audio_extn_ffv_get_stream() == in) {
5758 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305759 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005760 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305761 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5762 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5763 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5764 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305765 ret = -EINVAL;
5766 goto exit;
5767 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305768 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305769 ret = -errno;
5770 }
5771 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305772 /* bytes read is always set to bytes for non compress usecases */
5773 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005774 }
5775
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005776 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005778 /*
5779 * Instead of writing zeroes here, we could trust the hardware
5780 * to always provide zeroes when muted.
5781 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305782 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5783 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005784 memset(buffer, 0, bytes);
5785
5786exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005787 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305788 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005789 pthread_mutex_unlock(&in->lock);
5790
5791 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305792 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305793 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305794 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305795 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305796 in->standby = true;
5797 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305798 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5799 bytes_read = bytes;
5800 memset(buffer, 0, bytes);
5801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005802 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005803 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305804 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305805 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005806 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305807 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005808}
5809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005810static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005811{
5812 return 0;
5813}
5814
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005815static int add_remove_audio_effect(const struct audio_stream *stream,
5816 effect_handle_t effect,
5817 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005818{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005819 struct stream_in *in = (struct stream_in *)stream;
5820 int status = 0;
5821 effect_descriptor_t desc;
5822
5823 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005824 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5825
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005826 if (status != 0)
5827 return status;
5828
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005829 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005830 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005831 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5832 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005833 in->enable_aec != enable &&
5834 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5835 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005836 if (!in->standby) {
5837 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5838 select_devices(in->dev, in->usecase);
5839 }
5840
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005841 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005842 if (in->enable_ns != enable &&
5843 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5844 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005845 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005846 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5847 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005848 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5849 select_devices(in->dev, in->usecase);
5850 } else
5851 select_devices(in->dev, in->usecase);
5852 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005853 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005854 pthread_mutex_unlock(&in->dev->lock);
5855 pthread_mutex_unlock(&in->lock);
5856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005857 return 0;
5858}
5859
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005860static int in_add_audio_effect(const struct audio_stream *stream,
5861 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005862{
Eric Laurent994a6932013-07-17 11:51:42 -07005863 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005864 return add_remove_audio_effect(stream, effect, true);
5865}
5866
5867static int in_remove_audio_effect(const struct audio_stream *stream,
5868 effect_handle_t effect)
5869{
Eric Laurent994a6932013-07-17 11:51:42 -07005870 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005871 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005872}
5873
Haynes Mathew George16081042017-05-31 17:16:49 -07005874static int in_stop(const struct audio_stream_in* stream)
5875{
5876 struct stream_in *in = (struct stream_in *)stream;
5877 struct audio_device *adev = in->dev;
5878
5879 int ret = -ENOSYS;
5880 ALOGV("%s", __func__);
5881 pthread_mutex_lock(&adev->lock);
5882 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5883 in->capture_started && in->pcm != NULL) {
5884 pcm_stop(in->pcm);
5885 ret = stop_input_stream(in);
5886 in->capture_started = false;
5887 }
5888 pthread_mutex_unlock(&adev->lock);
5889 return ret;
5890}
5891
5892static int in_start(const struct audio_stream_in* stream)
5893{
5894 struct stream_in *in = (struct stream_in *)stream;
5895 struct audio_device *adev = in->dev;
5896 int ret = -ENOSYS;
5897
5898 ALOGV("%s in %p", __func__, in);
5899 pthread_mutex_lock(&adev->lock);
5900 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5901 !in->capture_started && in->pcm != NULL) {
5902 if (!in->capture_started) {
5903 ret = start_input_stream(in);
5904 if (ret == 0) {
5905 in->capture_started = true;
5906 }
5907 }
5908 }
5909 pthread_mutex_unlock(&adev->lock);
5910 return ret;
5911}
5912
5913static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5914 int32_t min_size_frames,
5915 struct audio_mmap_buffer_info *info)
5916{
5917 struct stream_in *in = (struct stream_in *)stream;
5918 struct audio_device *adev = in->dev;
5919 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005920 unsigned int offset1 = 0;
5921 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005922 const char *step = "";
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005923 uint32_t mmap_size = 0;
5924 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005925
5926 pthread_mutex_lock(&adev->lock);
5927 ALOGV("%s in %p", __func__, in);
5928
Sharad Sangle90e613f2018-05-04 16:15:38 +05305929 if (CARD_STATUS_OFFLINE == in->card_status||
5930 CARD_STATUS_OFFLINE == adev->card_status) {
5931 ALOGW("in->card_status or adev->card_status offline, try again");
5932 ret = -EIO;
5933 goto exit;
5934 }
5935
Haynes Mathew George16081042017-05-31 17:16:49 -07005936 if (info == NULL || min_size_frames == 0) {
5937 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5938 ret = -EINVAL;
5939 goto exit;
5940 }
5941 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5942 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5943 ALOGV("%s in %p", __func__, in);
5944 ret = -ENOSYS;
5945 goto exit;
5946 }
5947 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5948 if (in->pcm_device_id < 0) {
5949 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5950 __func__, in->pcm_device_id, in->usecase);
5951 ret = -EINVAL;
5952 goto exit;
5953 }
5954
5955 adjust_mmap_period_count(&in->config, min_size_frames);
5956
5957 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5958 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5959 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5960 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Sharad Sangle90e613f2018-05-04 16:15:38 +05305961 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
5962 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5963 in->card_status = CARD_STATUS_OFFLINE;
5964 adev->card_status = CARD_STATUS_OFFLINE;
5965 ret = -EIO;
5966 goto exit;
5967 }
5968
Haynes Mathew George16081042017-05-31 17:16:49 -07005969 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5970 step = "open";
5971 ret = -ENODEV;
5972 goto exit;
5973 }
5974
5975 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5976 if (ret < 0) {
5977 step = "begin";
5978 goto exit;
5979 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005980
Arun Mirpuriebe78a72018-10-04 18:23:46 -07005981 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5982 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
5983 info->burst_size_frames = in->config.period_size;
5984 ret = platform_get_mmap_data_fd(adev->platform,
5985 in->pcm_device_id, 1 /*capture*/,
5986 &info->shared_memory_fd,
5987 &mmap_size);
5988 if (ret < 0) {
5989 // Fall back to non exclusive mode
5990 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5991 } else {
5992 if (mmap_size < buffer_size) {
5993 step = "mmap";
5994 goto exit;
5995 }
5996 // FIXME: indicate exclusive mode support by returning a negative buffer size
5997 info->buffer_size_frames *= -1;
5998 }
5999
6000 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006001
6002 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6003 if (ret < 0) {
6004 step = "commit";
6005 goto exit;
6006 }
6007
6008 in->standby = false;
6009 ret = 0;
6010
6011 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6012 __func__, info->shared_memory_address, info->buffer_size_frames);
6013
6014exit:
6015 if (ret != 0) {
6016 if (in->pcm == NULL) {
6017 ALOGE("%s: %s - %d", __func__, step, ret);
6018 } else {
6019 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6020 pcm_close(in->pcm);
6021 in->pcm = NULL;
6022 }
6023 }
6024 pthread_mutex_unlock(&adev->lock);
6025 return ret;
6026}
6027
6028static int in_get_mmap_position(const struct audio_stream_in *stream,
6029 struct audio_mmap_position *position)
6030{
6031 struct stream_in *in = (struct stream_in *)stream;
6032 ALOGVV("%s", __func__);
6033 if (position == NULL) {
6034 return -EINVAL;
6035 }
6036 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6037 return -ENOSYS;
6038 }
6039 if (in->pcm == NULL) {
6040 return -ENOSYS;
6041 }
6042 struct timespec ts = { 0, 0 };
6043 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6044 if (ret < 0) {
6045 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6046 return ret;
6047 }
Naresh Tannirua15d7e92018-11-02 09:49:44 +05306048 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006049 return 0;
6050}
6051
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306052static int in_get_active_microphones(const struct audio_stream_in *stream,
6053 struct audio_microphone_characteristic_t *mic_array,
6054 size_t *mic_count) {
6055 struct stream_in *in = (struct stream_in *)stream;
6056 struct audio_device *adev = in->dev;
6057 ALOGVV("%s", __func__);
6058
6059 lock_input_stream(in);
6060 pthread_mutex_lock(&adev->lock);
6061 int ret = platform_get_active_microphones(adev->platform,
6062 audio_channel_count_from_in_mask(in->channel_mask),
6063 in->usecase, mic_array, mic_count);
6064 pthread_mutex_unlock(&adev->lock);
6065 pthread_mutex_unlock(&in->lock);
6066
6067 return ret;
6068}
6069
6070static int adev_get_microphones(const struct audio_hw_device *dev,
6071 struct audio_microphone_characteristic_t *mic_array,
6072 size_t *mic_count) {
6073 struct audio_device *adev = (struct audio_device *)dev;
6074 ALOGVV("%s", __func__);
6075
6076 pthread_mutex_lock(&adev->lock);
6077 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6078 pthread_mutex_unlock(&adev->lock);
6079
6080 return ret;
6081}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306082int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006083 audio_io_handle_t handle,
6084 audio_devices_t devices,
6085 audio_output_flags_t flags,
6086 struct audio_config *config,
6087 struct audio_stream_out **stream_out,
6088 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006089{
6090 struct audio_device *adev = (struct audio_device *)dev;
6091 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306092 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006093 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006094 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306095 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006096 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6097 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6098 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6099 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006100
kunleizdff872d2018-08-20 14:40:33 +08006101 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006102 is_usb_dev = false;
6103 devices = AUDIO_DEVICE_OUT_SPEAKER;
6104 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6105 __func__, devices);
6106 }
6107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006108 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006110 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6111
Mingming Yin3a941d42016-02-17 18:08:05 -08006112 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6113 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306114 devices, flags, &out->stream);
6115
6116
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006117 if (!out) {
6118 return -ENOMEM;
6119 }
6120
Haynes Mathew George204045b2015-02-25 20:32:03 -08006121 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006122 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306123 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006124 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006125 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006127 if (devices == AUDIO_DEVICE_NONE)
6128 devices = AUDIO_DEVICE_OUT_SPEAKER;
6129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006130 out->flags = flags;
6131 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006132 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006133 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006134 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306135 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306136 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6137 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6138 else
6139 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006140 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006141 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006142 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306143 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306144 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306145 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006146 out->hal_output_suspend_supported = 0;
6147 out->dynamic_pm_qos_config_supported = 0;
Surendar Karka5a18a7a2018-04-26 11:28:38 +05306148 out->set_dual_mono = false;
Manisha Agarwal7d3c9fe2019-02-20 14:33:45 +05306149 out->prev_card_status_offline = false;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05306150 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006151
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306152 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306153 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006154 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6155
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006156 if (audio_is_linear_pcm(out->format) &&
6157 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
6158 pthread_mutex_lock(&adev->lock);
6159 if (is_hdmi) {
6160 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6161 ret = read_hdmi_sink_caps(out);
6162 } else if (is_usb_dev) {
6163 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6164 &config->format,
6165 &out->supported_formats[0],
6166 MAX_SUPPORTED_FORMATS,
6167 &config->channel_mask,
6168 &out->supported_channel_masks[0],
6169 MAX_SUPPORTED_CHANNEL_MASKS,
6170 &config->sample_rate,
6171 &out->supported_sample_rates[0],
6172 MAX_SUPPORTED_SAMPLE_RATES);
6173 ALOGV("plugged dev USB ret %d", ret);
6174 } else {
6175 ret = -1;
6176 }
6177 pthread_mutex_unlock(&adev->lock);
6178 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006179 if (ret == -ENOSYS) {
6180 /* ignore and go with default */
6181 ret = 0;
6182 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006183 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006184 goto error_open;
6185 }
6186 }
6187 }
6188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006189 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07006190#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006191 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6192 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6193 out->sample_rate == 32000 || out->sample_rate == 48000)) {
6194 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
6195 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
6196 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6197
6198 out->config = default_pcm_config_voip_copp;
6199 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6200 out->config.rate = out->sample_rate;
6201
6202#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05306203 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006204 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08006205 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006206 ret = voice_extn_compress_voip_open_output_stream(out);
6207 if (ret != 0) {
6208 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6209 __func__, ret);
6210 goto error_open;
6211 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006212#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006213 } else if (audio_is_linear_pcm(out->format) &&
6214 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6215 out->channel_mask = config->channel_mask;
6216 out->sample_rate = config->sample_rate;
6217 out->format = config->format;
6218 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6219 // does this change?
6220 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6221 out->config.rate = config->sample_rate;
6222 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6223 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6224 audio_bytes_per_sample(config->format));
6225 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006226 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306227 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306228 pthread_mutex_lock(&adev->lock);
6229 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6230 pthread_mutex_unlock(&adev->lock);
6231
6232 // reject offload during card offline to allow
6233 // fallback to s/w paths
6234 if (offline) {
6235 ret = -ENODEV;
6236 goto error_open;
6237 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006239 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6240 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6241 ALOGE("%s: Unsupported Offload information", __func__);
6242 ret = -EINVAL;
6243 goto error_open;
6244 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006245
Atul Khare3fa6e542017-08-09 00:56:17 +05306246 if (config->offload_info.format == 0)
6247 config->offload_info.format = config->format;
6248 if (config->offload_info.sample_rate == 0)
6249 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006250
Mingming Yin90310102013-11-13 16:57:00 -08006251 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306252 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006253 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006254 ret = -EINVAL;
6255 goto error_open;
6256 }
6257
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006258 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6259 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6260 (audio_extn_passthru_is_passthrough_stream(out)) &&
6261 !((config->sample_rate == 48000) ||
6262 (config->sample_rate == 96000) ||
6263 (config->sample_rate == 192000))) {
6264 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6265 __func__, config->sample_rate, config->offload_info.format);
6266 ret = -EINVAL;
6267 goto error_open;
6268 }
6269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006270 out->compr_config.codec = (struct snd_codec *)
6271 calloc(1, sizeof(struct snd_codec));
6272
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006273 if (!out->compr_config.codec) {
6274 ret = -ENOMEM;
6275 goto error_open;
6276 }
6277
Dhananjay Kumarac341582017-02-23 23:42:25 +05306278 out->stream.pause = out_pause;
6279 out->stream.resume = out_resume;
6280 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306281 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306282 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006283 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306284 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006285 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306286 } else {
6287 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6288 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006289 }
vivek mehta446c3962015-09-14 10:57:35 -07006290
6291 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006292 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6293 config->format == 0 && config->sample_rate == 0 &&
6294 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006295 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006296 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6297 } else {
6298 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6299 ret = -EEXIST;
6300 goto error_open;
6301 }
vivek mehta446c3962015-09-14 10:57:35 -07006302 }
6303
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006304 if (config->offload_info.channel_mask)
6305 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006306 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006307 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006308 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006309 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306310 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006311 ret = -EINVAL;
6312 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006313 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006314
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006315 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006316 out->sample_rate = config->offload_info.sample_rate;
6317
Mingming Yin3ee55c62014-08-04 14:23:35 -07006318 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006319
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306320 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306321 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306322 audio_extn_dolby_send_ddp_endp_params(adev);
6323 audio_extn_dolby_set_dmid(adev);
6324 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006326 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006327 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006328 out->compr_config.codec->bit_rate =
6329 config->offload_info.bit_rate;
6330 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306331 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006332 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306333 /* Update bit width only for non passthrough usecases.
6334 * For passthrough usecases, the output will always be opened @16 bit
6335 */
6336 if (!audio_extn_passthru_is_passthrough_stream(out))
6337 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306338
6339 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6340 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6341 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6342
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006343 /*TODO: Do we need to change it for passthrough */
6344 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006345
Manish Dewangana6fc5442015-08-24 20:30:31 +05306346 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6347 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306348 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306349 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306350 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6351 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306352
6353 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6354 AUDIO_FORMAT_PCM) {
6355
6356 /*Based on platform support, configure appropriate alsa format for corresponding
6357 *hal input format.
6358 */
6359 out->compr_config.codec->format = hal_format_to_alsa(
6360 config->offload_info.format);
6361
Ashish Jain83a6cc22016-06-28 14:34:17 +05306362 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306363 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306364 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306365
Dhananjay Kumarac341582017-02-23 23:42:25 +05306366 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306367 *hal input format and alsa format might differ based on platform support.
6368 */
6369 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306370 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306371
6372 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6373
6374 /* Check if alsa session is configured with the same format as HAL input format,
6375 * if not then derive correct fragment size needed to accomodate the
6376 * conversion of HAL input format to alsa format.
6377 */
6378 audio_extn_utils_update_direct_pcm_fragment_size(out);
6379
6380 /*if hal input and output fragment size is different this indicates HAL input format is
6381 *not same as the alsa format
6382 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306383 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306384 /*Allocate a buffer to convert input data to the alsa configured format.
6385 *size of convert buffer is equal to the size required to hold one fragment size
6386 *worth of pcm data, this is because flinger does not write more than fragment_size
6387 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306388 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6389 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306390 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6391 ret = -ENOMEM;
6392 goto error_open;
6393 }
6394 }
6395 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6396 out->compr_config.fragment_size =
6397 audio_extn_passthru_get_buffer_size(&config->offload_info);
6398 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6399 } else {
6400 out->compr_config.fragment_size =
6401 platform_get_compress_offload_buffer_size(&config->offload_info);
6402 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6403 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006404
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306405 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6406 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6407 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006408 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306409 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006410
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306411 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6412 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6413 }
6414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006415 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6416 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006417
Manish Dewangan69426c82017-01-30 17:35:36 +05306418 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6419 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6420 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6421 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6422 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6423 } else {
6424 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6425 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006426
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306427 memset(&out->channel_map_param, 0,
6428 sizeof(struct audio_out_channel_map_param));
6429
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006430 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306431 out->send_next_track_params = false;
6432 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006433 out->offload_state = OFFLOAD_STATE_IDLE;
6434 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006435 out->writeAt.tv_sec = 0;
6436 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006437
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006438 audio_extn_dts_create_state_notifier_node(out->usecase);
6439
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006440 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6441 __func__, config->offload_info.version,
6442 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306443
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306444 /* Check if DSD audio format is supported in codec
6445 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306446 */
6447
6448 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306449 (!platform_check_codec_dsd_support(adev->platform) ||
6450 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306451 ret = -EINVAL;
6452 goto error_open;
6453 }
6454
Ashish Jain5106d362016-05-11 19:23:33 +05306455 /* Disable gapless if any of the following is true
6456 * passthrough playback
6457 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306458 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306459 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306460 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306461 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006462 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306463 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306464 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306465 check_and_set_gapless_mode(adev, false);
6466 } else
6467 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006468
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306469 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006470 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6471 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306472 if (config->format == AUDIO_FORMAT_DSD) {
6473 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6474 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6475 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006476
6477 create_offload_callback_thread(out);
6478
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006479 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006480 switch (config->sample_rate) {
6481 case 0:
6482 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6483 break;
6484 case 8000:
6485 case 16000:
6486 case 48000:
6487 out->sample_rate = config->sample_rate;
6488 break;
6489 default:
6490 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6491 config->sample_rate);
6492 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6493 ret = -EINVAL;
6494 goto error_open;
6495 }
6496 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6497 switch (config->channel_mask) {
6498 case AUDIO_CHANNEL_NONE:
6499 case AUDIO_CHANNEL_OUT_STEREO:
6500 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6501 break;
6502 default:
6503 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6504 config->channel_mask);
6505 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6506 ret = -EINVAL;
6507 goto error_open;
6508 }
6509 switch (config->format) {
6510 case AUDIO_FORMAT_DEFAULT:
6511 case AUDIO_FORMAT_PCM_16_BIT:
6512 out->format = AUDIO_FORMAT_PCM_16_BIT;
6513 break;
6514 default:
6515 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6516 config->format);
6517 config->format = AUDIO_FORMAT_PCM_16_BIT;
6518 ret = -EINVAL;
6519 goto error_open;
6520 }
6521
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306522 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006523 if (ret != 0) {
6524 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006525 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006526 goto error_open;
6527 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006528 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006529 if (config->sample_rate == 0)
6530 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6531 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6532 config->sample_rate != 8000) {
6533 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6534 ret = -EINVAL;
6535 goto error_open;
6536 }
6537 out->sample_rate = config->sample_rate;
6538 out->config.rate = config->sample_rate;
6539 if (config->format == AUDIO_FORMAT_DEFAULT)
6540 config->format = AUDIO_FORMAT_PCM_16_BIT;
6541 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6542 config->format = AUDIO_FORMAT_PCM_16_BIT;
6543 ret = -EINVAL;
6544 goto error_open;
6545 }
6546 out->format = config->format;
6547 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6548 out->config = pcm_config_afe_proxy_playback;
6549 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006550 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306551 unsigned int channels = 0;
6552 /*Update config params to default if not set by the caller*/
6553 if (config->sample_rate == 0)
6554 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6555 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6556 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6557 if (config->format == AUDIO_FORMAT_DEFAULT)
6558 config->format = AUDIO_FORMAT_PCM_16_BIT;
6559
6560 channels = audio_channel_count_from_out_mask(out->channel_mask);
6561
Varun Balaraje49253e2017-07-06 19:48:56 +05306562 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6563 out->usecase = get_interactive_usecase(adev);
6564 out->config = pcm_config_low_latency;
6565 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306566 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006567 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6568 out->flags);
6569 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006570 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6571 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6572 out->config = pcm_config_mmap_playback;
6573 out->stream.start = out_start;
6574 out->stream.stop = out_stop;
6575 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6576 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306577 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6578 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006579 out->hal_output_suspend_supported =
6580 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6581 out->dynamic_pm_qos_config_supported =
6582 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6583 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006584 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6585 } else {
6586 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6587 //the mixer path will be a string similar to "low-latency-playback resume"
6588 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6589 strlcat(out->pm_qos_mixer_path,
6590 " resume", MAX_MIXER_PATH_LEN);
6591 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6592 out->pm_qos_mixer_path);
6593 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306594 out->config = pcm_config_low_latency;
6595 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6596 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6597 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306598 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6599 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6600 if (out->config.period_size <= 0) {
6601 ALOGE("Invalid configuration period size is not valid");
6602 ret = -EINVAL;
6603 goto error_open;
6604 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306605 } else {
6606 /* primary path is the default path selected if no other outputs are available/suitable */
6607 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6608 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6609 }
6610 out->hal_ip_format = format = out->format;
6611 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6612 out->hal_op_format = pcm_format_to_hal(out->config.format);
6613 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6614 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006615 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306616 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306617 if (out->hal_ip_format != out->hal_op_format) {
6618 uint32_t buffer_size = out->config.period_size *
6619 format_to_bitwidth_table[out->hal_op_format] *
6620 out->config.channels;
6621 out->convert_buffer = calloc(1, buffer_size);
6622 if (out->convert_buffer == NULL){
6623 ALOGE("Allocation failed for convert buffer for size %d",
6624 out->compr_config.fragment_size);
6625 ret = -ENOMEM;
6626 goto error_open;
6627 }
6628 ALOGD("Convert buffer allocated of size %d", buffer_size);
6629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006630 }
6631
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006632 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6633 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306634
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006635 /* TODO remove this hardcoding and check why width is zero*/
6636 if (out->bit_width == 0)
6637 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306638 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006639 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006640 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306641 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306642 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006643 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6644 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6645 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006646 if(adev->primary_output == NULL)
6647 adev->primary_output = out;
6648 else {
6649 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006650 ret = -EEXIST;
6651 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006652 }
6653 }
6654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006655 /* Check if this usecase is already existing */
6656 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006657 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6658 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006659 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006660 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006661 ret = -EEXIST;
6662 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006665 pthread_mutex_unlock(&adev->lock);
6666
6667 out->stream.common.get_sample_rate = out_get_sample_rate;
6668 out->stream.common.set_sample_rate = out_set_sample_rate;
6669 out->stream.common.get_buffer_size = out_get_buffer_size;
6670 out->stream.common.get_channels = out_get_channels;
6671 out->stream.common.get_format = out_get_format;
6672 out->stream.common.set_format = out_set_format;
6673 out->stream.common.standby = out_standby;
6674 out->stream.common.dump = out_dump;
6675 out->stream.common.set_parameters = out_set_parameters;
6676 out->stream.common.get_parameters = out_get_parameters;
6677 out->stream.common.add_audio_effect = out_add_audio_effect;
6678 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6679 out->stream.get_latency = out_get_latency;
6680 out->stream.set_volume = out_set_volume;
6681 out->stream.write = out_write;
6682 out->stream.get_render_position = out_get_render_position;
6683 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006684 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006685
Haynes Mathew George16081042017-05-31 17:16:49 -07006686 if (out->realtime)
6687 out->af_period_multiplier = af_period_multiplier;
6688 else
6689 out->af_period_multiplier = 1;
6690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006691 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006692 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006693 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006694
6695 config->format = out->stream.common.get_format(&out->stream.common);
6696 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6697 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306698 register_format(out->format, out->supported_formats);
6699 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6700 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306702 /*
6703 By locking output stream before registering, we allow the callback
6704 to update stream's state only after stream's initial state is set to
6705 adev state.
6706 */
6707 lock_output_stream(out);
6708 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6709 pthread_mutex_lock(&adev->lock);
6710 out->card_status = adev->card_status;
6711 pthread_mutex_unlock(&adev->lock);
6712 pthread_mutex_unlock(&out->lock);
6713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306715 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006716 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006717
6718 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6719 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6720 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006721 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306722 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006723 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006724 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306725 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006726 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6727 out->usecase, PCM_PLAYBACK);
6728 hdlr_stream_cfg.flags = out->flags;
6729 hdlr_stream_cfg.type = PCM_PLAYBACK;
6730 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6731 &hdlr_stream_cfg);
6732 if (ret) {
6733 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6734 out->adsp_hdlr_stream_handle = NULL;
6735 }
6736 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306737 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006738 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006739 if (ret < 0) {
6740 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6741 out->ip_hdlr_handle = NULL;
6742 }
6743 }
Eric Laurent994a6932013-07-17 11:51:42 -07006744 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006745 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006746
6747error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306748 if (out->convert_buffer)
6749 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006750 free(out);
6751 *stream_out = NULL;
6752 ALOGD("%s: exit: ret %d", __func__, ret);
6753 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006754}
6755
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306756void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006757 struct audio_stream_out *stream)
6758{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006759 struct stream_out *out = (struct stream_out *)stream;
6760 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006761 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006762
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006763 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306764
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306765 // must deregister from sndmonitor first to prevent races
6766 // between the callback and close_stream
6767 audio_extn_snd_mon_unregister_listener(out);
6768
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006769 /* close adsp hdrl session before standby */
6770 if (out->adsp_hdlr_stream_handle) {
6771 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6772 if (ret)
6773 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6774 out->adsp_hdlr_stream_handle = NULL;
6775 }
6776
Manish Dewangan21a850a2017-08-14 12:03:55 +05306777 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006778 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6779 out->ip_hdlr_handle = NULL;
6780 }
6781
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006782 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306783 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006784 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306785 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306786 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006787 if(ret != 0)
6788 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6789 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006790 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006791 out_standby(&stream->common);
6792
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006793 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006794 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006795 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006796 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006797 if (out->compr_config.codec != NULL)
6798 free(out->compr_config.codec);
6799 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006800
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306801 out->a2dp_compress_mute = false;
6802
Varun Balaraje49253e2017-07-06 19:48:56 +05306803 if (is_interactive_usecase(out->usecase))
6804 free_interactive_usecase(adev, out->usecase);
6805
Ashish Jain83a6cc22016-06-28 14:34:17 +05306806 if (out->convert_buffer != NULL) {
6807 free(out->convert_buffer);
6808 out->convert_buffer = NULL;
6809 }
6810
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006811 if (adev->voice_tx_output == out)
6812 adev->voice_tx_output = NULL;
6813
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306814 if (adev->primary_output == out)
6815 adev->primary_output = NULL;
6816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006817 pthread_cond_destroy(&out->cond);
6818 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006819 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006820 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006821}
6822
6823static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6824{
6825 struct audio_device *adev = (struct audio_device *)dev;
6826 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006827 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006828 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006829 int ret;
6830 int status = 0;
Zhou Songa32012a2019-05-21 18:08:51 +08006831 struct listnode *node;
6832 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006833
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006834 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306837 if (!parms)
6838 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306839
Zhou Songa32012a2019-05-21 18:08:51 +08006840 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306841 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6842 if (ret >= 0) {
6843 /* When set to false, HAL should disable EC and NS */
Zhou Songa32012a2019-05-21 18:08:51 +08006844 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306845 adev->bt_sco_on = true;
Zhou Songa32012a2019-05-21 18:08:51 +08006846 } else {
6847 ALOGD("route device to handset/mic when sco is off");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306848 adev->bt_sco_on = false;
Zhou Songa32012a2019-05-21 18:08:51 +08006849 list_for_each(node, &adev->usecase_list) {
6850 usecase = node_to_item(node, struct audio_usecase, list);
6851 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
6852 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
6853 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
6854 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
6855 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
6856 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
6857 else
6858 continue;
6859 select_devices(adev, usecase->id);
6860 }
6861 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306862 }
6863
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006864 status = voice_set_parameters(adev, parms);
6865 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006866 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006867
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006868 status = platform_set_parameters(adev->platform, parms);
6869 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006870 goto done;
6871
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006872 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6873 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006874 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006875 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6876 adev->bluetooth_nrec = true;
6877 else
6878 adev->bluetooth_nrec = false;
6879 }
6880
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006881 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6882 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006883 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6884 adev->screen_off = false;
6885 else
6886 adev->screen_off = true;
6887 }
6888
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006889 ret = str_parms_get_int(parms, "rotation", &val);
6890 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006891 bool reverse_speakers = false;
6892 switch(val) {
6893 // FIXME: note that the code below assumes that the speakers are in the correct placement
6894 // relative to the user when the device is rotated 90deg from its default rotation. This
6895 // assumption is device-specific, not platform-specific like this code.
6896 case 270:
6897 reverse_speakers = true;
6898 break;
6899 case 0:
6900 case 90:
6901 case 180:
6902 break;
6903 default:
6904 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006905 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006906 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006907 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006908 // check and set swap
6909 // - check if orientation changed and speaker active
6910 // - set rotation and cache the rotation value
6911 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006912 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006913 }
6914
Mingming Yin514a8bc2014-07-29 15:22:21 -07006915 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6916 if (ret >= 0) {
6917 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6918 adev->bt_wb_speech_enabled = true;
6919 else
6920 adev->bt_wb_speech_enabled = false;
6921 }
6922
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006923 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6924 if (ret >= 0) {
6925 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306926 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006927 if (audio_is_output_device(val) &&
6928 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006929 ALOGV("cache new ext disp type and edid");
6930 ret = platform_get_ext_disp_type(adev->platform);
6931 if (ret < 0) {
6932 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306933 } else {
6934 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006935 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306936 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006937 /*
6938 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6939 * Per AudioPolicyManager, USB device is higher priority than WFD.
6940 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6941 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6942 * starting voice call on USB
6943 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006944 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306945 if (ret >= 0)
6946 audio_extn_usb_add_device(device, atoi(value));
6947
Zhou Song6f862822017-11-06 17:27:57 +08006948 if (!audio_extn_usb_is_tunnel_supported()) {
6949 ALOGV("detected USB connect .. disable proxy");
6950 adev->allow_afe_proxy_usage = false;
6951 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006952 }
6953 }
6954
6955 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6956 if (ret >= 0) {
6957 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306958 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006959 /*
6960 * The HDMI / Displayport disconnect handling has been moved to
6961 * audio extension to ensure that its parameters are not
6962 * invalidated prior to updating sysfs of the disconnect event
6963 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6964 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306965 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006966 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306967 if (ret >= 0)
6968 audio_extn_usb_remove_device(device, atoi(value));
6969
Zhou Song6f862822017-11-06 17:27:57 +08006970 if (!audio_extn_usb_is_tunnel_supported()) {
6971 ALOGV("detected USB disconnect .. enable proxy");
6972 adev->allow_afe_proxy_usage = true;
6973 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006974 }
6975 }
6976
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306977 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6978 if (ret >= 0) {
6979 struct audio_usecase *usecase;
6980 struct listnode *node;
6981 list_for_each(node, &adev->usecase_list) {
6982 usecase = node_to_item(node, struct audio_usecase, list);
6983 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006984 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306985 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006986
6987 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306988 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006989 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306990 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306991 //force device switch to re configure encoder
6992 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306993 audio_extn_a2dp_set_handoff_mode(false);
6994 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306995 break;
6996 }
6997 }
6998 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006999
7000 //handle vr audio setparam
7001 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7002 value, sizeof(value));
7003 if (ret >= 0) {
7004 ALOGI("Setting vr mode to be %s", value);
7005 if (!strncmp(value, "true", 4)) {
7006 adev->vr_audio_mode_enabled = true;
7007 ALOGI("Setting vr mode to true");
7008 } else if (!strncmp(value, "false", 5)) {
7009 adev->vr_audio_mode_enabled = false;
7010 ALOGI("Setting vr mode to false");
7011 } else {
7012 ALOGI("wrong vr mode set");
7013 }
7014 }
7015
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307016 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007017done:
7018 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007019 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307020error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007021 ALOGV("%s: exit with code(%d)", __func__, status);
7022 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007023}
7024
7025static char* adev_get_parameters(const struct audio_hw_device *dev,
7026 const char *keys)
7027{
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307028 ALOGD("%s:%s", __func__, keys);
7029
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007030 struct audio_device *adev = (struct audio_device *)dev;
7031 struct str_parms *reply = str_parms_create();
7032 struct str_parms *query = str_parms_create_str(keys);
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307033
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007034 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307035 char value[256] = {0};
7036 int ret = 0;
7037
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007038 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007039 if (reply) {
7040 str_parms_destroy(reply);
7041 }
7042 if (query) {
7043 str_parms_destroy(query);
7044 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007045 ALOGE("adev_get_parameters: failed to create query or reply");
7046 return NULL;
7047 }
7048
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007049 //handle vr audio getparam
7050
7051 ret = str_parms_get_str(query,
7052 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7053 value, sizeof(value));
7054
7055 if (ret >= 0) {
7056 bool vr_audio_enabled = false;
7057 pthread_mutex_lock(&adev->lock);
7058 vr_audio_enabled = adev->vr_audio_mode_enabled;
7059 pthread_mutex_unlock(&adev->lock);
7060
7061 ALOGI("getting vr mode to %d", vr_audio_enabled);
7062
7063 if (vr_audio_enabled) {
7064 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7065 "true");
7066 goto exit;
7067 } else {
7068 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7069 "false");
7070 goto exit;
7071 }
7072 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007073
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007074 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007075 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007076 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007077 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307078 pthread_mutex_unlock(&adev->lock);
7079
Naresh Tannirud7205b62014-06-20 02:54:48 +05307080exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007081 str = str_parms_to_str(reply);
7082 str_parms_destroy(query);
7083 str_parms_destroy(reply);
7084
Sidipotu Ashok090f0bc2018-12-21 09:19:26 +05307085 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007086 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007087}
7088
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007089static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007090{
7091 return 0;
7092}
7093
7094static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7095{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007096 int ret;
7097 struct audio_device *adev = (struct audio_device *)dev;
7098 pthread_mutex_lock(&adev->lock);
7099 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007100 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007101 pthread_mutex_unlock(&adev->lock);
7102 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007103}
7104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007105static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7106 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007107{
7108 return -ENOSYS;
7109}
7110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007111static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7112 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113{
7114 return -ENOSYS;
7115}
7116
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007117static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7118 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007119{
7120 return -ENOSYS;
7121}
7122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007123static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7124 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125{
7126 return -ENOSYS;
7127}
7128
7129static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7130{
7131 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007132 struct listnode *node;
7133 struct audio_usecase *usecase = NULL;
7134 int ret = 0;
kunleiz60c17e72017-05-04 12:15:35 +08007135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007136 pthread_mutex_lock(&adev->lock);
7137 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007138 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139 adev->mode = mode;
Kunlei Zhang0eab0432019-05-21 14:25:57 +08007140 if (voice_is_in_call(adev) &&
7141 (mode == AUDIO_MODE_NORMAL ||
7142 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007143 list_for_each(node, &adev->usecase_list) {
7144 usecase = node_to_item(node, struct audio_usecase, list);
7145 if (usecase->type == VOICE_CALL)
7146 break;
7147 }
7148 if (usecase &&
7149 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7150 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7151 true);
7152 if (ret != 0) {
7153 /* default service interval was successfully updated,
7154 reopen USB backend with new service interval */
7155 check_usecases_codec_backend(adev,
7156 usecase,
7157 usecase->out_snd_device);
7158 }
7159 }
7160
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007161 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007162 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007163 adev->current_call_output = NULL;
kunleiz60c17e72017-05-04 12:15:35 +08007164 // restore device for other active usecases after stop call
7165 list_for_each(node, &adev->usecase_list) {
7166 usecase = node_to_item(node, struct audio_usecase, list);
7167 select_devices(adev, usecase->id);
7168 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 }
7171 pthread_mutex_unlock(&adev->lock);
7172 return 0;
7173}
7174
7175static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7176{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007177 int ret;
7178
7179 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007180 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007181 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Derek Chencdd17c72014-11-24 12:39:14 -08007182 if (adev->ext_hw_plugin)
7183 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007184 pthread_mutex_unlock(&adev->lock);
7185
7186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187}
7188
7189static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7190{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007191 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007192 return 0;
7193}
7194
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007195static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007196 const struct audio_config *config)
7197{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007198 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007200 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7201 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007202}
7203
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007204static bool adev_input_allow_hifi_record(struct audio_device *adev,
7205 audio_devices_t devices,
7206 audio_input_flags_t flags,
7207 audio_source_t source) {
7208 const bool allowed = true;
7209
7210 if (!audio_is_usb_in_device(devices))
7211 return !allowed;
7212
7213 switch (flags) {
7214 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007215 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007216 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7217 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007218 default:
7219 return !allowed;
7220 }
7221
7222 switch (source) {
7223 case AUDIO_SOURCE_DEFAULT:
7224 case AUDIO_SOURCE_MIC:
7225 case AUDIO_SOURCE_UNPROCESSED:
7226 break;
7227 default:
7228 return !allowed;
7229 }
7230
7231 switch (adev->mode) {
7232 case 0:
7233 break;
7234 default:
7235 return !allowed;
7236 }
7237
7238 return allowed;
7239}
7240
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007241static int adev_update_voice_comm_input_stream(struct stream_in *in,
7242 struct audio_config *config)
7243{
7244 bool valid_rate = (config->sample_rate == 8000 ||
7245 config->sample_rate == 16000 ||
7246 config->sample_rate == 32000 ||
7247 config->sample_rate == 48000);
7248 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
7249
7250#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08007251 if (valid_rate && valid_ch &&
7252 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007253 in->usecase = USECASE_AUDIO_RECORD_VOIP;
7254 in->config = default_pcm_config_voip_copp;
7255 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
7256 DEFAULT_VOIP_BUF_DURATION_MS,
7257 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7258 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08007259 ALOGW("%s No valid input in voip, use defaults"
7260 "sample rate %u, channel mask 0x%X",
7261 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007262 }
7263 in->config.rate = config->sample_rate;
7264 in->sample_rate = config->sample_rate;
7265#else
7266 //XXX needed for voice_extn_compress_voip_open_input_stream
7267 in->config.rate = config->sample_rate;
7268 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7269 voice_extn_compress_voip_is_active(in->dev)) &&
7270 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7271 valid_rate && valid_ch) {
7272 voice_extn_compress_voip_open_input_stream(in);
7273 // update rate entries to match config from AF
7274 in->config.rate = config->sample_rate;
7275 in->sample_rate = config->sample_rate;
7276 } else {
7277 ALOGW("%s compress voip not active, use defaults", __func__);
7278 }
7279#endif
7280 return 0;
7281}
7282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007283static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007284 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285 audio_devices_t devices,
7286 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007287 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307288 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007289 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007290 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291{
7292 struct audio_device *adev = (struct audio_device *)dev;
7293 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007294 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007295 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007296 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05307297 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007298 bool is_usb_dev = audio_is_usb_in_device(devices);
7299 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
7300 devices,
7301 flags,
7302 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307303
kunleizdff872d2018-08-20 14:40:33 +08007304 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007305 is_usb_dev = false;
7306 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
7307 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
7308 __func__, devices);
7309 }
7310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007311 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007312
7313 if (!(is_usb_dev && may_use_hifi_record)) {
7314 if (config->sample_rate == 0)
7315 config->sample_rate = 48000;
7316 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7317 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7318 if (config->format == AUDIO_FORMAT_DEFAULT)
7319 config->format = AUDIO_FORMAT_PCM_16_BIT;
7320
7321 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7322
7323 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7324 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307325 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007326
7327 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007328
7329 if (!in) {
7330 ALOGE("failed to allocate input stream");
7331 return -ENOMEM;
7332 }
7333
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307334 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307335 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7336 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007337 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007338 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007340 in->stream.common.get_sample_rate = in_get_sample_rate;
7341 in->stream.common.set_sample_rate = in_set_sample_rate;
7342 in->stream.common.get_buffer_size = in_get_buffer_size;
7343 in->stream.common.get_channels = in_get_channels;
7344 in->stream.common.get_format = in_get_format;
7345 in->stream.common.set_format = in_set_format;
7346 in->stream.common.standby = in_standby;
7347 in->stream.common.dump = in_dump;
7348 in->stream.common.set_parameters = in_set_parameters;
7349 in->stream.common.get_parameters = in_get_parameters;
7350 in->stream.common.add_audio_effect = in_add_audio_effect;
7351 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7352 in->stream.set_gain = in_set_gain;
7353 in->stream.read = in_read;
7354 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307355 in->stream.get_active_microphones = in_get_active_microphones;
Ramjee Singhacef98f2019-06-28 11:01:25 +05307356#if ANDROID_PLATFORM_SDK_VERSION >= 29
7357 in->stream.set_microphone_direction = in_set_microphone_direction;
7358 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
7359#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007360
7361 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007362 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007364 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007365 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007366 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007367 in->bit_width = 16;
7368 in->af_period_multiplier = 1;
7369
7370 /* Update config params with the requested sample rate and channels */
7371 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7372 (adev->mode != AUDIO_MODE_IN_CALL)) {
7373 ret = -EINVAL;
7374 goto err_open;
7375 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007376
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007377 if (is_usb_dev && may_use_hifi_record) {
7378 /* HiFi record selects an appropriate format, channel, rate combo
7379 depending on sink capabilities*/
7380 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7381 &config->format,
7382 &in->supported_formats[0],
7383 MAX_SUPPORTED_FORMATS,
7384 &config->channel_mask,
7385 &in->supported_channel_masks[0],
7386 MAX_SUPPORTED_CHANNEL_MASKS,
7387 &config->sample_rate,
7388 &in->supported_sample_rates[0],
7389 MAX_SUPPORTED_SAMPLE_RATES);
7390 if (ret != 0) {
7391 ret = -EINVAL;
7392 goto err_open;
7393 }
7394 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007395 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307396 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307397 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7398 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7399 in->config.format = PCM_FORMAT_S32_LE;
7400 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307401 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7402 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7403 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7404 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7405 bool ret_error = false;
7406 in->bit_width = 24;
7407 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7408 from HAL is 24_packed and 8_24
7409 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7410 24_packed return error indicating supported format is 24_packed
7411 *> In case of any other source requesting 24 bit or float return error
7412 indicating format supported is 16 bit only.
7413
7414 on error flinger will retry with supported format passed
7415 */
7416 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7417 (source != AUDIO_SOURCE_CAMCORDER)) {
7418 config->format = AUDIO_FORMAT_PCM_16_BIT;
7419 if (config->sample_rate > 48000)
7420 config->sample_rate = 48000;
7421 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007422 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7423 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307424 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7425 ret_error = true;
7426 }
7427
7428 if (ret_error) {
7429 ret = -EINVAL;
7430 goto err_open;
7431 }
7432 }
7433
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007434 in->channel_mask = config->channel_mask;
7435 in->format = config->format;
7436
7437 in->usecase = USECASE_AUDIO_RECORD;
7438 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7439 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7440 is_low_latency = true;
7441#if LOW_LATENCY_CAPTURE_USE_CASE
7442 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7443#endif
7444 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7445 }
7446
7447 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7448 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7449 in->realtime = 0;
7450 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7451 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007452 in->config.format = pcm_format_from_audio_format(config->format);
Weiyin Jiangde7925e2018-11-27 18:45:53 +08007453 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007454 in->stream.start = in_start;
7455 in->stream.stop = in_stop;
7456 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7457 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007458 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007459 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7460 } else if (in->realtime) {
7461 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007462 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007463 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007464 in->sample_rate = in->config.rate;
7465 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007466 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007467 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7468 in->config = pcm_config_audio_capture;
7469 frame_size = audio_stream_in_frame_size(&in->stream);
7470 buffer_size = get_input_buffer_size(config->sample_rate,
7471 config->format,
7472 channel_count,
7473 false /*is_low_latency*/);
7474 in->config.period_size = buffer_size / frame_size;
7475 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007476 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007477 switch (config->format) {
7478 case AUDIO_FORMAT_PCM_32_BIT:
7479 in->bit_width = 32;
7480 break;
7481 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7482 case AUDIO_FORMAT_PCM_8_24_BIT:
7483 in->bit_width = 24;
7484 break;
7485 default:
7486 in->bit_width = 16;
7487 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007488 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007489 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007490 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307491 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007492 if (config->sample_rate == 0)
7493 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7494 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7495 config->sample_rate != 8000) {
7496 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7497 ret = -EINVAL;
7498 goto err_open;
7499 }
7500 if (config->format == AUDIO_FORMAT_DEFAULT)
7501 config->format = AUDIO_FORMAT_PCM_16_BIT;
7502 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7503 config->format = AUDIO_FORMAT_PCM_16_BIT;
7504 ret = -EINVAL;
7505 goto err_open;
7506 }
7507
7508 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7509 in->config = pcm_config_afe_proxy_record;
7510 in->config.channels = channel_count;
7511 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307512 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007513 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307514 int ret_val;
7515 pthread_mutex_lock(&adev->lock);
7516 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7517 in, config, &channel_mask_updated);
7518 pthread_mutex_unlock(&adev->lock);
7519
7520 if (!ret_val) {
7521 if (channel_mask_updated == true) {
7522 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7523 __func__, config->channel_mask);
7524 ret = -EINVAL;
7525 goto err_open;
7526 }
7527 ALOGD("%s: created multi-channel session succesfully",__func__);
7528 } else if (audio_extn_compr_cap_enabled() &&
7529 audio_extn_compr_cap_format_supported(config->format) &&
7530 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7531 audio_extn_compr_cap_init(in);
7532 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307533 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307534 ret = audio_extn_cin_configure_input_stream(in);
7535 if (ret)
7536 goto err_open;
7537 } else {
7538 in->config = pcm_config_audio_capture;
7539 in->config.rate = config->sample_rate;
7540 in->config.format = pcm_format_from_audio_format(config->format);
7541 in->config.channels = channel_count;
7542 in->sample_rate = config->sample_rate;
7543 in->format = config->format;
7544 frame_size = audio_stream_in_frame_size(&in->stream);
7545 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007546 config->format,
7547 channel_count,
7548 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307549 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007550
Revathi Uddarajud2634032017-12-07 14:42:34 +05307551 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7552 /* optionally use VOIP usecase depending on config(s) */
7553 ret = adev_update_voice_comm_input_stream(in, config);
7554 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007555
Revathi Uddarajud2634032017-12-07 14:42:34 +05307556 if (ret) {
7557 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7558 goto err_open;
7559 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007560 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007561 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307562 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7563 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007564 devices, flags, in->format,
7565 in->sample_rate, in->bit_width,
7566 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307567 register_format(in->format, in->supported_formats);
7568 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7569 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307570
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007571 /* This stream could be for sound trigger lab,
7572 get sound trigger pcm if present */
7573 audio_extn_sound_trigger_check_and_get_session(in);
7574
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307575 lock_input_stream(in);
7576 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7577 pthread_mutex_lock(&adev->lock);
7578 in->card_status = adev->card_status;
7579 pthread_mutex_unlock(&adev->lock);
7580 pthread_mutex_unlock(&in->lock);
7581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007582 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007583 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007584 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007585
7586err_open:
7587 free(in);
7588 *stream_in = NULL;
7589 return ret;
7590}
7591
7592static void adev_close_input_stream(struct audio_hw_device *dev,
7593 struct audio_stream_in *stream)
7594{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007595 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007596 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007597 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307598
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307599 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007600
kunleizef40adb2018-12-28 17:50:23 +08007601 /* must deregister from sndmonitor first to prevent races
7602 * between the callback and close_stream
7603 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307604 audio_extn_snd_mon_unregister_listener(stream);
7605
kunleizef40adb2018-12-28 17:50:23 +08007606 /* Disable echo reference if there are no active input, hfp call
7607 * and sound trigger while closing input stream
7608 */
7609 if (!adev->active_input &&
7610 !audio_extn_hfp_is_active(adev) &&
7611 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8405edd2018-11-29 15:04:56 +08007612 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleizef40adb2018-12-28 17:50:23 +08007613 else
7614 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307615
Pallavid7c7a272018-01-16 11:22:55 +05307616 if (in == NULL) {
7617 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7618 return;
7619 }
7620
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007621 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307622 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007623 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307624 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007625 if (ret != 0)
7626 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7627 __func__, ret);
7628 } else
7629 in_standby(&stream->common);
7630
Revathi Uddarajud2634032017-12-07 14:42:34 +05307631 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007632 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007633 audio_extn_ssr_deinit();
7634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007635
Garmond Leunge2433c32017-09-28 21:51:22 -07007636 if (audio_extn_ffv_get_stream() == in) {
7637 audio_extn_ffv_stream_deinit();
7638 }
7639
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307640 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007641 audio_extn_compr_cap_format_supported(in->config.format))
7642 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307643
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307644 if (audio_extn_cin_attached_usecase(in->usecase))
7645 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007646
Mingming Yinfd7607b2016-01-22 12:48:44 -08007647 if (in->is_st_session) {
7648 ALOGV("%s: sound trigger pcm stop lab", __func__);
7649 audio_extn_sound_trigger_stop_lab(in);
7650 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007651 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307652 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007653 return;
7654}
7655
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307656int adev_create_audio_patch(struct audio_hw_device *dev,
7657 unsigned int num_sources,
7658 const struct audio_port_config *sources,
7659 unsigned int num_sinks,
7660 const struct audio_port_config *sinks,
7661 audio_patch_handle_t *handle)
7662{
7663
7664
7665 return audio_extn_hw_loopback_create_audio_patch(dev,
7666 num_sources,
7667 sources,
7668 num_sinks,
7669 sinks,
7670 handle);
7671
7672}
7673
7674int adev_release_audio_patch(struct audio_hw_device *dev,
7675 audio_patch_handle_t handle)
7676{
7677 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7678}
7679
7680int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7681{
7682 return audio_extn_hw_loopback_get_audio_port(dev, config);
7683}
7684
7685int adev_set_audio_port_config(struct audio_hw_device *dev,
7686 const struct audio_port_config *config)
7687{
7688 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7689}
7690
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007691static int adev_dump(const audio_hw_device_t *device __unused,
7692 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007693{
7694 return 0;
7695}
7696
7697static int adev_close(hw_device_t *device)
7698{
7699 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007700
7701 if (!adev)
7702 return 0;
7703
7704 pthread_mutex_lock(&adev_init_lock);
7705
7706 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307707 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007708 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007709 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307710 audio_extn_utils_release_streams_cfg_lists(
7711 &adev->streams_output_cfg_list,
7712 &adev->streams_input_cfg_list);
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307713 if (audio_extn_qap_is_enabled())
7714 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307715 if (audio_extn_qaf_is_enabled())
7716 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007717 audio_route_free(adev->audio_route);
Weiyin Jiang902f7d12019-03-05 23:39:45 +08007718 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07007719 free(adev->snd_dev_ref_cnt);
7720 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007721 if (adev->adm_deinit)
7722 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307723 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007724 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307725 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307726 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007727 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307728 if (adev->device_cfg_params) {
7729 free(adev->device_cfg_params);
7730 adev->device_cfg_params = NULL;
7731 }
Derek Chencdd17c72014-11-24 12:39:14 -08007732 if(adev->ext_hw_plugin)
7733 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Kiran Kandi910e1862013-10-29 13:29:42 -07007734 free(device);
7735 adev = NULL;
7736 }
7737 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchaa1358992018-11-14 13:25:08 +05307738 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007739 return 0;
7740}
7741
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007742/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7743 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7744 * just that it _might_ work.
7745 */
7746static int period_size_is_plausible_for_low_latency(int period_size)
7747{
7748 switch (period_size) {
7749 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007750 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007751 case 240:
7752 case 320:
7753 case 480:
7754 return 1;
7755 default:
7756 return 0;
7757 }
7758}
7759
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307760static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7761{
7762 bool is_snd_card_status = false;
7763 bool is_ext_device_status = false;
7764 char value[32];
7765 int card = -1;
7766 card_status_t status;
7767
7768 if (cookie != adev || !parms)
7769 return;
7770
7771 if (!parse_snd_card_status(parms, &card, &status)) {
7772 is_snd_card_status = true;
7773 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7774 is_ext_device_status = true;
7775 } else {
7776 // not a valid event
7777 return;
7778 }
7779
7780 pthread_mutex_lock(&adev->lock);
7781 if (card == adev->snd_card || is_ext_device_status) {
7782 if (is_snd_card_status && adev->card_status != status) {
7783 adev->card_status = status;
7784 platform_snd_card_update(adev->platform, status);
7785 audio_extn_fm_set_parameters(adev, parms);
7786 } else if (is_ext_device_status) {
7787 platform_set_parameters(adev->platform, parms);
7788 }
7789 }
7790 pthread_mutex_unlock(&adev->lock);
7791 return;
7792}
7793
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307794/* out and adev lock held */
7795static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7796{
7797 struct audio_usecase *uc_info;
7798 float left_p;
7799 float right_p;
7800 audio_devices_t devices;
7801
7802 uc_info = get_usecase_from_list(adev, out->usecase);
7803 if (uc_info == NULL) {
7804 ALOGE("%s: Could not find the usecase (%d) in the list",
7805 __func__, out->usecase);
7806 return -EINVAL;
7807 }
7808
7809 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7810 out->usecase, use_case_table[out->usecase]);
7811
7812 if (restore) {
7813 // restore A2DP device for active usecases and unmute if required
7814 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7815 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7816 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7817 select_devices(adev, uc_info->id);
7818 pthread_mutex_lock(&out->compr_mute_lock);
7819 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7820 (out->a2dp_compress_mute)) {
7821 out->a2dp_compress_mute = false;
7822 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7823 }
7824 pthread_mutex_unlock(&out->compr_mute_lock);
7825 }
7826 } else {
7827 // mute compress stream if suspended
7828 pthread_mutex_lock(&out->compr_mute_lock);
7829 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7830 (!out->a2dp_compress_mute)) {
7831 if (!out->standby) {
7832 ALOGD("%s: selecting speaker and muting stream", __func__);
7833 devices = out->devices;
7834 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7835 left_p = out->volume_l;
7836 right_p = out->volume_r;
7837 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7838 compress_pause(out->compr);
7839 out_set_compr_volume(&out->stream, (float)0, (float)0);
7840 out->a2dp_compress_mute = true;
7841 select_devices(adev, out->usecase);
7842 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7843 compress_resume(out->compr);
7844 out->devices = devices;
7845 out->volume_l = left_p;
7846 out->volume_r = right_p;
7847 }
7848 }
7849 pthread_mutex_unlock(&out->compr_mute_lock);
7850 }
7851 ALOGV("%s: exit", __func__);
7852 return 0;
7853}
7854
7855int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7856{
7857 int ret = 0;
7858
7859 lock_output_stream(out);
7860 pthread_mutex_lock(&adev->lock);
7861
7862 ret = check_a2dp_restore_l(adev, out, restore);
7863
7864 pthread_mutex_unlock(&adev->lock);
7865 pthread_mutex_unlock(&out->lock);
7866 return ret;
7867}
7868
Haynes Mathew George01156f92018-04-13 15:29:54 -07007869void adev_on_battery_status_changed(bool charging)
7870{
7871 pthread_mutex_lock(&adev->lock);
7872 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7873 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007874 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007875 pthread_mutex_unlock(&adev->lock);
7876}
7877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007878static int adev_open(const hw_module_t *module, const char *name,
7879 hw_device_t **device)
7880{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307881 int ret;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307882 char mixer_ctl_name[128] = {0};
7883 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307884
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007885 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007886 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7887
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007888 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007889 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007890 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007891 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007892 ALOGD("%s: returning existing instance of adev", __func__);
7893 ALOGD("%s: exit", __func__);
7894 pthread_mutex_unlock(&adev_init_lock);
7895 return 0;
7896 }
7897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007898 adev = calloc(1, sizeof(struct audio_device));
7899
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007900 if (!adev) {
7901 pthread_mutex_unlock(&adev_init_lock);
7902 return -ENOMEM;
7903 }
7904
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007905 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7906
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307907#ifdef DYNAMIC_LOG_ENABLED
7908 register_for_dynamic_logging("hal");
7909#endif
7910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007911 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7912 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7913 adev->device.common.module = (struct hw_module_t *)module;
7914 adev->device.common.close = adev_close;
7915
7916 adev->device.init_check = adev_init_check;
7917 adev->device.set_voice_volume = adev_set_voice_volume;
7918 adev->device.set_master_volume = adev_set_master_volume;
7919 adev->device.get_master_volume = adev_get_master_volume;
7920 adev->device.set_master_mute = adev_set_master_mute;
7921 adev->device.get_master_mute = adev_get_master_mute;
7922 adev->device.set_mode = adev_set_mode;
7923 adev->device.set_mic_mute = adev_set_mic_mute;
7924 adev->device.get_mic_mute = adev_get_mic_mute;
7925 adev->device.set_parameters = adev_set_parameters;
7926 adev->device.get_parameters = adev_get_parameters;
7927 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7928 adev->device.open_output_stream = adev_open_output_stream;
7929 adev->device.close_output_stream = adev_close_output_stream;
7930 adev->device.open_input_stream = adev_open_input_stream;
7931 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307932 adev->device.create_audio_patch = adev_create_audio_patch;
7933 adev->device.release_audio_patch = adev_release_audio_patch;
7934 adev->device.get_audio_port = adev_get_audio_port;
7935 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007936 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307937 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007938
7939 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007940 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007941 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007942 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007943 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007944 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007945 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007946 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307947 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007948 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007949 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007950 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007951 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007952 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007953 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307954 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307955 adev->perf_lock_opts[0] = 0x101;
7956 adev->perf_lock_opts[1] = 0x20E;
7957 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007958 adev->dsp_bit_width_enforce_mode = 0;
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05307959 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007961 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007962 adev->platform = platform_init(adev);
7963 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007964 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007965 free(adev->snd_dev_ref_cnt);
7966 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007967 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007968 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7969 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007970 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007971 return -EINVAL;
7972 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007973
Sidipotu Ashokafffd202019-05-06 15:41:56 +05307974 if (audio_extn_qap_is_enabled()) {
7975 ret = audio_extn_qap_init(adev);
7976 if (ret < 0) {
7977 pthread_mutex_destroy(&adev->lock);
7978 free(adev);
7979 adev = NULL;
7980 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7981 *device = NULL;
7982 pthread_mutex_unlock(&adev_init_lock);
7983 return ret;
7984 }
7985 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
7986 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
7987 }
7988
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307989 if (audio_extn_qaf_is_enabled()) {
7990 ret = audio_extn_qaf_init(adev);
7991 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007992 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307993 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007994 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307995 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7996 *device = NULL;
7997 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307998 return ret;
7999 }
8000
8001 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
8002 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
8003 }
8004
Derek Chencdd17c72014-11-24 12:39:14 -08008005 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
8006
Eric Laurentc4aef752013-09-12 17:45:53 -07008007 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
8008 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
8009 if (adev->visualizer_lib == NULL) {
8010 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
8011 } else {
8012 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
8013 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008014 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008015 "visualizer_hal_start_output");
8016 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008017 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07008018 "visualizer_hal_stop_output");
8019 }
8020 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05308021 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08008022 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08008023 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308024 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008025 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07008026
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008027 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
8028 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
8029 if (adev->offload_effects_lib == NULL) {
8030 ALOGE("%s: DLOPEN failed for %s", __func__,
8031 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8032 } else {
8033 ALOGV("%s: DLOPEN successful for %s", __func__,
8034 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
8035 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05308036 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008037 "offload_effects_bundle_hal_start_output");
8038 adev->offload_effects_stop_output =
8039 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
8040 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008041 adev->offload_effects_set_hpx_state =
8042 (int (*)(bool))dlsym(adev->offload_effects_lib,
8043 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05308044 adev->offload_effects_get_parameters =
8045 (void (*)(struct str_parms *, struct str_parms *))
8046 dlsym(adev->offload_effects_lib,
8047 "offload_effects_bundle_get_parameters");
8048 adev->offload_effects_set_parameters =
8049 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
8050 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08008051 }
8052 }
8053
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008054 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
8055 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
8056 if (adev->adm_lib == NULL) {
8057 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
8058 } else {
8059 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
8060 adev->adm_init = (adm_init_t)
8061 dlsym(adev->adm_lib, "adm_init");
8062 adev->adm_deinit = (adm_deinit_t)
8063 dlsym(adev->adm_lib, "adm_deinit");
8064 adev->adm_register_input_stream = (adm_register_input_stream_t)
8065 dlsym(adev->adm_lib, "adm_register_input_stream");
8066 adev->adm_register_output_stream = (adm_register_output_stream_t)
8067 dlsym(adev->adm_lib, "adm_register_output_stream");
8068 adev->adm_deregister_stream = (adm_deregister_stream_t)
8069 dlsym(adev->adm_lib, "adm_deregister_stream");
8070 adev->adm_request_focus = (adm_request_focus_t)
8071 dlsym(adev->adm_lib, "adm_request_focus");
8072 adev->adm_abandon_focus = (adm_abandon_focus_t)
8073 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008074 adev->adm_set_config = (adm_set_config_t)
8075 dlsym(adev->adm_lib, "adm_set_config");
8076 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
8077 dlsym(adev->adm_lib, "adm_request_focus_v2");
8078 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
8079 dlsym(adev->adm_lib, "adm_is_noirq_avail");
8080 adev->adm_on_routing_change = (adm_on_routing_change_t)
8081 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008082 }
8083 }
8084
Mingming Yin514a8bc2014-07-29 15:22:21 -07008085 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008086 //initialize this to false for now,
8087 //this will be set to true through set param
8088 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07008089
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07008090 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008091 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008092 adev->dsp_bit_width_enforce_mode =
8093 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008094
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308095 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
8096 &adev->streams_output_cfg_list,
8097 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008098
Kiran Kandi910e1862013-10-29 13:29:42 -07008099 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008100
8101 char value[PROPERTY_VALUE_MAX];
8102 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008103 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008104 trial = atoi(value);
8105 if (period_size_is_plausible_for_low_latency(trial)) {
8106 pcm_config_low_latency.period_size = trial;
8107 pcm_config_low_latency.start_threshold = trial / 4;
8108 pcm_config_low_latency.avail_min = trial / 4;
8109 configured_low_latency_capture_period_size = trial;
8110 }
8111 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008112 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008113 trial = atoi(value);
8114 if (period_size_is_plausible_for_low_latency(trial)) {
8115 configured_low_latency_capture_period_size = trial;
8116 }
8117 }
8118
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08008119 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
8120
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008121 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008122 af_period_multiplier = atoi(value);
8123 if (af_period_multiplier < 0)
8124 af_period_multiplier = 2;
8125 else if (af_period_multiplier > 4)
8126 af_period_multiplier = 4;
8127
8128 ALOGV("new period_multiplier = %d", af_period_multiplier);
8129 }
8130
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07008131 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008132 pthread_mutex_unlock(&adev_init_lock);
8133
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008134 if (adev->adm_init)
8135 adev->adm_data = adev->adm_init();
8136
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308137 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308138 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008139 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308140
8141 audio_extn_snd_mon_init();
8142 pthread_mutex_lock(&adev->lock);
8143 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
8144 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07008145 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
8146 /*
8147 * if the battery state callback happens before charging can be queried,
8148 * it will be guarded with the adev->lock held in the cb function and so
8149 * the callback value will reflect the latest state
8150 */
8151 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308152 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08008153 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
8154 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308155 /* Allocate memory for Device config params */
8156 adev->device_cfg_params = (struct audio_device_config_param*)
8157 calloc(platform_get_max_codec_backend(),
8158 sizeof(struct audio_device_config_param));
8159 if (adev->device_cfg_params == NULL)
8160 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308161
Dhanalakshmi Siddani988a66d2019-01-27 17:31:09 +05308162 /*
8163 * Check if new PSPD matrix mixer control is supported. If not
8164 * supported, then set flag so that old mixer ctrl is sent while
8165 * sending pspd coefficients on older kernel version. Query mixer
8166 * control for default pcm id and channel value one.
8167 */
8168 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
8169 "AudStr %d ChMixer Weight Ch %d", 0, 1);
8170
8171 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
8172 if (!ctl) {
8173 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
8174 __func__, mixer_ctl_name);
8175 adev->use_old_pspd_mix_ctrl = true;
8176 }
8177
Eric Laurent994a6932013-07-17 11:51:42 -07008178 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008179 return 0;
8180}
8181
8182static struct hw_module_methods_t hal_module_methods = {
8183 .open = adev_open,
8184};
8185
8186struct audio_module HAL_MODULE_INFO_SYM = {
8187 .common = {
8188 .tag = HARDWARE_MODULE_TAG,
8189 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
8190 .hal_api_version = HARDWARE_HAL_API_VERSION,
8191 .id = AUDIO_HARDWARE_MODULE_ID,
8192 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08008193 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008194 .methods = &hal_module_methods,
8195 },
8196};