blob: d7f57fac900336c4050ab05823cfe7f7fa2d5413 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05302 * Copyright (c) 2013-2018, 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
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053093#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070095#define PROXY_OPEN_RETRY_COUNT 100
96#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080097
Mingming Yin08c7e312015-03-16 18:10:58 -070098#ifdef USE_LL_AS_PRIMARY_OUTPUT
99#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
100#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
101#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800102#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700103#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
104#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800105
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700106#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700107#define DEFAULT_VOIP_BUF_DURATION_MS 20
108#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
109#define DEFAULT_VOIP_SAMP_RATE 48000
110
111#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
112
113struct pcm_config default_pcm_config_voip_copp = {
114 .channels = 1,
115 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
116 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
117 .period_count = 2,
118 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800119 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
120 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700121};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700123#define MIN_CHANNEL_COUNT 1
124#define DEFAULT_CHANNEL_COUNT 2
125#define MAX_HIFI_CHANNEL_COUNT 8
126
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700127static unsigned int configured_low_latency_capture_period_size =
128 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
129
Haynes Mathew George16081042017-05-31 17:16:49 -0700130#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
131#define MMAP_PERIOD_COUNT_MIN 32
132#define MMAP_PERIOD_COUNT_MAX 512
133#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
134
Eric Laurentb23d5282013-05-14 15:27:20 -0700135struct pcm_config pcm_config_deep_buffer = {
136 .channels = 2,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
139 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
142 .stop_threshold = INT_MAX,
143 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
144};
145
146struct pcm_config pcm_config_low_latency = {
147 .channels = 2,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
150 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
151 .format = PCM_FORMAT_S16_LE,
152 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
153 .stop_threshold = INT_MAX,
154 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
155};
156
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700157static int af_period_multiplier = 4;
158struct pcm_config pcm_config_rt = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = ULL_PERIOD_SIZE, //1 ms
162 .period_count = 512, //=> buffer size is 512ms
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
165 .stop_threshold = INT_MAX,
166 .silence_threshold = 0,
167 .silence_size = 0,
168 .avail_min = ULL_PERIOD_SIZE, //1 ms
169};
170
Eric Laurentb23d5282013-05-14 15:27:20 -0700171struct pcm_config pcm_config_hdmi_multi = {
172 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
173 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
174 .period_size = HDMI_MULTI_PERIOD_SIZE,
175 .period_count = HDMI_MULTI_PERIOD_COUNT,
176 .format = PCM_FORMAT_S16_LE,
177 .start_threshold = 0,
178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
180};
181
Haynes Mathew George16081042017-05-31 17:16:49 -0700182struct pcm_config pcm_config_mmap_playback = {
183 .channels = 2,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = MMAP_PERIOD_SIZE,
186 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = MMAP_PERIOD_SIZE*8,
189 .stop_threshold = INT32_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = MMAP_PERIOD_SIZE, //1 ms
193};
194
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700195struct pcm_config pcm_config_hifi = {
196 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
197 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
198 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
199 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
200 .format = PCM_FORMAT_S24_3LE,
201 .start_threshold = 0,
202 .stop_threshold = INT_MAX,
203 .avail_min = 0,
204};
205
Eric Laurentb23d5282013-05-14 15:27:20 -0700206struct pcm_config pcm_config_audio_capture = {
207 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700208 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
209 .format = PCM_FORMAT_S16_LE,
210};
211
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700212struct pcm_config pcm_config_audio_capture_rt = {
213 .channels = 2,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = ULL_PERIOD_SIZE,
216 .period_count = 512,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = 0,
219 .stop_threshold = INT_MAX,
220 .silence_threshold = 0,
221 .silence_size = 0,
222 .avail_min = ULL_PERIOD_SIZE, //1 ms
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_capture = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = 0,
232 .stop_threshold = INT_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700238#define AFE_PROXY_CHANNEL_COUNT 2
239#define AFE_PROXY_SAMPLING_RATE 48000
240
241#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
242#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
243
244struct pcm_config pcm_config_afe_proxy_playback = {
245 .channels = AFE_PROXY_CHANNEL_COUNT,
246 .rate = AFE_PROXY_SAMPLING_RATE,
247 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
248 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
249 .format = PCM_FORMAT_S16_LE,
250 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
251 .stop_threshold = INT_MAX,
252 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
253};
254
255#define AFE_PROXY_RECORD_PERIOD_SIZE 768
256#define AFE_PROXY_RECORD_PERIOD_COUNT 4
257
258struct pcm_config pcm_config_afe_proxy_record = {
259 .channels = AFE_PROXY_CHANNEL_COUNT,
260 .rate = AFE_PROXY_SAMPLING_RATE,
261 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
262 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
265 .stop_threshold = INT_MAX,
266 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
267};
268
Ashish Jainf1eaa582016-05-23 20:54:24 +0530269#define AUDIO_MAX_PCM_FORMATS 7
270
271const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
272 [AUDIO_FORMAT_DEFAULT] = 0,
273 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
274 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
275 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
276 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
277 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
278 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
279};
280
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800281const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700282 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
283 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700284 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
285 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700286 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700287 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700288 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
289 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
293 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
294 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
295 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700296 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
297 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700298 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700299
Eric Laurentb23d5282013-05-14 15:27:20 -0700300 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700301 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530302 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
303 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
304 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530305 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
306 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700307 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700308 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700309 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700310 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700311
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800312 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800313 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700314 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700316 [USECASE_VOICE2_CALL] = "voice2-call",
317 [USECASE_VOLTE_CALL] = "volte-call",
318 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800319 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800320 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
321 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800322 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700323 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
324 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
325 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800326 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
327 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
328 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
329
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700330 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
331 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700332 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
333 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700334
335 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
336 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530337 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700338
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530339 /* Transcode loopback cases */
340 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700341
342 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
343 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530344 /* For Interactive Audio Streams */
345 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
348 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
349 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
350 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
351 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
352 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700353
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800354 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
355
356 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700357};
358
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700359static const audio_usecase_t offload_usecases[] = {
360 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700361 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
362 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
363 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
364 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
365 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
366 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
367 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
368 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700369};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800370
Varun Balaraje49253e2017-07-06 19:48:56 +0530371static const audio_usecase_t interactive_usecases[] = {
372 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
373 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
374 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
375 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
376 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
377 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
378 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
379 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
380};
381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800382#define STRING_TO_ENUM(string) { #string, string }
383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800384struct string_to_enum {
385 const char *name;
386 uint32_t value;
387};
388
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700389static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800390 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800391 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
392 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
393 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700394 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800395 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
396 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800397 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700398 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
399 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
400 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
401 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
402 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
403 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
404 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
405 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
406 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
407 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
408 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800409};
410
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700411static const struct string_to_enum formats_name_to_enum_table[] = {
412 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
413 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
414 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700415 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
416 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
417 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700418 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800419 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
420 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700421 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800422};
423
424//list of all supported sample rates by HDMI specification.
425static const int out_hdmi_sample_rates[] = {
426 32000, 44100, 48000, 88200, 96000, 176400, 192000,
427};
428
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700429static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800430 STRING_TO_ENUM(32000),
431 STRING_TO_ENUM(44100),
432 STRING_TO_ENUM(48000),
433 STRING_TO_ENUM(88200),
434 STRING_TO_ENUM(96000),
435 STRING_TO_ENUM(176400),
436 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700437};
438
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700439static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700440static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700441static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700442//cache last MBDRC cal step level
443static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700444
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530445static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
446static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800447static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530448
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700449static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
450 int flags __unused)
451{
452 int dir = 0;
453 switch (uc_id) {
454 case USECASE_AUDIO_RECORD_LOW_LATENCY:
455 dir = 1;
456 case USECASE_AUDIO_PLAYBACK_ULL:
457 break;
458 default:
459 return false;
460 }
461
462 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
463 PCM_PLAYBACK : PCM_CAPTURE);
464 if (adev->adm_is_noirq_avail)
465 return adev->adm_is_noirq_avail(adev->adm_data,
466 adev->snd_card, dev_id, dir);
467 return false;
468}
469
470static void register_out_stream(struct stream_out *out)
471{
472 struct audio_device *adev = out->dev;
473 if (is_offload_usecase(out->usecase) ||
474 !adev->adm_register_output_stream)
475 return;
476
477 // register stream first for backward compatibility
478 adev->adm_register_output_stream(adev->adm_data,
479 out->handle,
480 out->flags);
481
482 if (!adev->adm_set_config)
483 return;
484
485 if (out->realtime)
486 adev->adm_set_config(adev->adm_data,
487 out->handle,
488 out->pcm, &out->config);
489}
490
491static void register_in_stream(struct stream_in *in)
492{
493 struct audio_device *adev = in->dev;
494 if (!adev->adm_register_input_stream)
495 return;
496
497 adev->adm_register_input_stream(adev->adm_data,
498 in->capture_handle,
499 in->flags);
500
501 if (!adev->adm_set_config)
502 return;
503
504 if (in->realtime)
505 adev->adm_set_config(adev->adm_data,
506 in->capture_handle,
507 in->pcm,
508 &in->config);
509}
510
511static void request_out_focus(struct stream_out *out, long ns)
512{
513 struct audio_device *adev = out->dev;
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515 if (adev->adm_request_focus_v2)
516 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
517 else if (adev->adm_request_focus)
518 adev->adm_request_focus(adev->adm_data, out->handle);
519}
520
521static void request_in_focus(struct stream_in *in, long ns)
522{
523 struct audio_device *adev = in->dev;
524
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700525 if (adev->adm_request_focus_v2)
526 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
527 else if (adev->adm_request_focus)
528 adev->adm_request_focus(adev->adm_data, in->capture_handle);
529}
530
531static void release_out_focus(struct stream_out *out)
532{
533 struct audio_device *adev = out->dev;
534
535 if (adev->adm_abandon_focus)
536 adev->adm_abandon_focus(adev->adm_data, out->handle);
537}
538
539static void release_in_focus(struct stream_in *in)
540{
541 struct audio_device *adev = in->dev;
542 if (adev->adm_abandon_focus)
543 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
544}
545
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530546static int parse_snd_card_status(struct str_parms *parms, int *card,
547 card_status_t *status)
548{
549 char value[32]={0};
550 char state[32]={0};
551
552 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
553 if (ret < 0)
554 return -1;
555
556 // sscanf should be okay as value is of max length 32.
557 // same as sizeof state.
558 if (sscanf(value, "%d,%s", card, state) < 2)
559 return -1;
560
561 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
562 CARD_STATUS_OFFLINE;
563 return 0;
564}
565
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700566static inline void adjust_frames_for_device_delay(struct stream_out *out,
567 uint32_t *dsp_frames) {
568 // Adjustment accounts for A2dp encoder latency with offload usecases
569 // Note: Encoder latency is returned in ms.
570 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
571 unsigned long offset =
572 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
573 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
574 }
575}
576
vivek mehtaa76401a2015-04-24 14:12:15 -0700577__attribute__ ((visibility ("default")))
578bool audio_hw_send_gain_dep_calibration(int level) {
579 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700580 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700581
582 pthread_mutex_lock(&adev_init_lock);
583
584 if (adev != NULL && adev->platform != NULL) {
585 pthread_mutex_lock(&adev->lock);
586 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700587
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530588 // cache level info for any of the use case which
589 // was not started.
590 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700591
vivek mehtaa76401a2015-04-24 14:12:15 -0700592 pthread_mutex_unlock(&adev->lock);
593 } else {
594 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
595 }
596
597 pthread_mutex_unlock(&adev_init_lock);
598
599 return ret_val;
600}
601
Ashish Jain5106d362016-05-11 19:23:33 +0530602static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
603{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800604 bool gapless_enabled = false;
605 const char *mixer_ctl_name = "Compress Gapless Playback";
606 struct mixer_ctl *ctl;
607
608 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700609 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530610
611 /*Disable gapless if its AV playback*/
612 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800613
614 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
615 if (!ctl) {
616 ALOGE("%s: Could not get ctl for mixer cmd - %s",
617 __func__, mixer_ctl_name);
618 return -EINVAL;
619 }
620
621 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
622 ALOGE("%s: Could not set gapless mode %d",
623 __func__, gapless_enabled);
624 return -EINVAL;
625 }
626 return 0;
627}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700628
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700629__attribute__ ((visibility ("default")))
630int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
631 int table_size) {
632 int ret_val = 0;
633 ALOGV("%s: enter ... ", __func__);
634
635 pthread_mutex_lock(&adev_init_lock);
636 if (adev == NULL) {
637 ALOGW("%s: adev is NULL .... ", __func__);
638 goto done;
639 }
640
641 pthread_mutex_lock(&adev->lock);
642 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
643 pthread_mutex_unlock(&adev->lock);
644done:
645 pthread_mutex_unlock(&adev_init_lock);
646 ALOGV("%s: exit ... ", __func__);
647 return ret_val;
648}
649
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700650static bool is_supported_format(audio_format_t format)
651{
Eric Laurent86e17132013-09-12 17:49:30 -0700652 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530653 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530654 format == AUDIO_FORMAT_AAC_LC ||
655 format == AUDIO_FORMAT_AAC_HE_V1 ||
656 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530657 format == AUDIO_FORMAT_AAC_ADTS_LC ||
658 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
659 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530660 format == AUDIO_FORMAT_AAC_LATM_LC ||
661 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
662 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530663 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
664 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530665 format == AUDIO_FORMAT_PCM_FLOAT ||
666 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700667 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530668 format == AUDIO_FORMAT_AC3 ||
669 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700670 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530671 format == AUDIO_FORMAT_DTS ||
672 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800673 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530674 format == AUDIO_FORMAT_ALAC ||
675 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530676 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530677 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800678 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530679 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700680 format == AUDIO_FORMAT_APTX ||
681 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800682 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700683
684 return false;
685}
686
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700687static inline bool is_mmap_usecase(audio_usecase_t uc_id)
688{
689 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
690 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
691}
692
Avinash Vaish71a8b972014-07-24 15:36:33 +0530693static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
694 struct audio_usecase *uc_info)
695{
696 struct listnode *node;
697 struct audio_usecase *usecase;
698
699 if (uc_info == NULL)
700 return -EINVAL;
701
702 /* Re-route all voice usecases on the shared backend other than the
703 specified usecase to new snd devices */
704 list_for_each(node, &adev->usecase_list) {
705 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800706 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530707 enable_audio_route(adev, usecase);
708 }
709 return 0;
710}
711
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530712static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530713{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530714 ALOGV("%s", __func__);
715 audio_route_apply_and_update_path(adev->audio_route,
716 "asrc-mode");
717 adev->asrc_mode_enabled = true;
718}
719
720static void disable_asrc_mode(struct audio_device *adev)
721{
722 ALOGV("%s", __func__);
723 audio_route_reset_and_update_path(adev->audio_route,
724 "asrc-mode");
725 adev->asrc_mode_enabled = false;
726}
727
728/*
729 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
730 * 44.1 or Native DSD backends are enabled for any of current use case.
731 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
732 * - Disable current mix path use case(Headphone backend) and re-enable it with
733 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
734 * e.g. Naitve DSD or Headphone 44.1 -> + 48
735 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530736static void check_and_set_asrc_mode(struct audio_device *adev,
737 struct audio_usecase *uc_info,
738 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530739{
740 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530741 int i, num_new_devices = 0;
742 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
743 /*
744 *Split snd device for new combo use case
745 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
746 */
747 if (platform_split_snd_device(adev->platform,
748 snd_device,
749 &num_new_devices,
750 split_new_snd_devices) == 0) {
751 for (i = 0; i < num_new_devices; i++)
752 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
753 } else {
754 int new_backend_idx = platform_get_backend_index(snd_device);
755 if (((new_backend_idx == HEADPHONE_BACKEND) ||
756 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
757 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
758 !adev->asrc_mode_enabled) {
759 struct listnode *node = NULL;
760 struct audio_usecase *uc = NULL;
761 struct stream_out *curr_out = NULL;
762 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
763 int i, num_devices, ret = 0;
764 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530765
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530766 list_for_each(node, &adev->usecase_list) {
767 uc = node_to_item(node, struct audio_usecase, list);
768 curr_out = (struct stream_out*) uc->stream.out;
769 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
770 /*
771 *Split snd device for existing combo use case
772 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
773 */
774 ret = platform_split_snd_device(adev->platform,
775 uc->out_snd_device,
776 &num_devices,
777 split_snd_devices);
778 if (ret < 0 || num_devices == 0) {
779 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
780 split_snd_devices[0] = uc->out_snd_device;
781 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800782 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530783 for (i = 0; i < num_devices; i++) {
784 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
785 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
786 if((new_backend_idx == HEADPHONE_BACKEND) &&
787 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
788 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
789 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
790 __func__);
791 enable_asrc_mode(adev);
792 break;
793 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
794 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
795 (usecase_backend_idx == HEADPHONE_BACKEND)) {
796 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
797 __func__);
798 disable_audio_route(adev, uc);
799 disable_snd_device(adev, uc->out_snd_device);
800 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
801 if (new_backend_idx == DSD_NATIVE_BACKEND)
802 audio_route_apply_and_update_path(adev->audio_route,
803 "hph-true-highquality-mode");
804 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
805 (curr_out->bit_width >= 24))
806 audio_route_apply_and_update_path(adev->audio_route,
807 "hph-highquality-mode");
808 enable_asrc_mode(adev);
809 enable_snd_device(adev, uc->out_snd_device);
810 enable_audio_route(adev, uc);
811 break;
812 }
813 }
814 // reset split devices count
815 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800816 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530817 if (adev->asrc_mode_enabled)
818 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530819 }
820 }
821 }
822}
823
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700824#ifdef DYNAMIC_ECNS_ENABLED
825static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
826 struct audio_effect_config effect_config,
827 unsigned int param_value)
828{
829 char mixer_ctl_name[] = "Audio Effect";
830 struct mixer_ctl *ctl;
831 long set_values[6];
832 struct stream_in *in = adev->active_input;
833
834 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
835 if (!ctl) {
836 ALOGE("%s: Could not get mixer ctl - %s",
837 __func__, mixer_ctl_name);
838 return -EINVAL;
839 }
840
841 set_values[0] = 1; //0:Rx 1:Tx
842 set_values[1] = in->app_type_cfg.app_type;
843 set_values[2] = (long)effect_config.module_id;
844 set_values[3] = (long)effect_config.instance_id;
845 set_values[4] = (long)effect_config.param_id;
846 set_values[5] = param_value;
847
848 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
849
850 return 0;
851
852}
853
854static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
855 int effect_type, unsigned int *param_value)
856{
857 int ret = 0;
858 struct audio_effect_config other_effect_config;
859 struct audio_usecase *usecase = NULL;
860 struct stream_in *in = adev->active_input;
861
862 usecase = get_usecase_from_list(adev, in->usecase);
863 if (!usecase)
864 return -EINVAL;
865
866 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
867 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
868 if (ret < 0) {
869 ALOGE("%s Failed to get effect params %d", __func__, ret);
870 return ret;
871 }
872
873 if (module_id == other_effect_config.module_id) {
874 //Same module id for AEC/NS. Values need to be combined
875 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
876 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
877 *param_value |= other_effect_config.param_value;
878 }
879 }
880
881 return ret;
882}
883
884static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
885{
886 struct audio_effect_config effect_config;
887 struct audio_usecase *usecase = NULL;
888 int ret = 0;
889 unsigned int param_value = 0;
890 struct stream_in *in = adev->active_input;
891
892 if (!in) {
893 ALOGE("%s: Invalid input stream", __func__);
894 return -EINVAL;
895 }
896
897 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
898
899 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800900 if (usecase == NULL) {
901 ALOGE("%s: Could not find the usecase (%d) in the list",
902 __func__, in->usecase);
903 return -EINVAL;
904 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700905
906 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
907 if (ret < 0) {
908 ALOGE("%s Failed to get module id %d", __func__, ret);
909 return ret;
910 }
911 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
912 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
913
914 if(enable)
915 param_value = effect_config.param_value;
916
917 /*Special handling for AEC & NS effects Param values need to be
918 updated if module ids are same*/
919
920 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
921 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
922 if (ret < 0)
923 return ret;
924 }
925
926 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
927
928 return ret;
929}
930
931static void check_and_enable_effect(struct audio_device *adev)
932{
933
934 if (adev->active_input->enable_aec) {
935 enable_disable_effect(adev, EFFECT_AEC, true);
936 }
937
938 if (adev->active_input->enable_ns &&
939 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
940 enable_disable_effect(adev, EFFECT_NS, true);
941 }
942}
943#else
944#define enable_disable_effect(x, y, z) ENOSYS
945#define check_and_enable_effect(x) ENOSYS
946#endif
947
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700948int pcm_ioctl(struct pcm *pcm, int request, ...)
949{
950 va_list ap;
951 void * arg;
952 int pcm_fd = *(int*)pcm;
953
954 va_start(ap, request);
955 arg = va_arg(ap, void *);
956 va_end(ap);
957
958 return ioctl(pcm_fd, request, arg);
959}
960
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700961int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700965 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530966 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800967
968 if (usecase == NULL)
969 return -EINVAL;
970
971 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
972
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800973 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800975 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800977
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800978#ifdef DS1_DOLBY_DAP_ENABLED
979 audio_extn_dolby_set_dmid(adev);
980 audio_extn_dolby_set_endpoint(adev);
981#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700982 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700983 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530984 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700985 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530986 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530987 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
988 out = usecase->stream.out;
989 if (out && out->compr)
990 audio_extn_utils_compress_set_clk_rec_mode(usecase);
991 }
992
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800993 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700994 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700995 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700996 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 ALOGV("%s: exit", __func__);
998 return 0;
999}
1000
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001001int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001002 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001005 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001006
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301007 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001008 return -EINVAL;
1009
1010 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011 if (usecase->type == PCM_CAPTURE)
1012 snd_device = usecase->in_snd_device;
1013 else
1014 snd_device = usecase->out_snd_device;
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: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001018 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001019 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301020 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 ALOGV("%s: exit", __func__);
1022 return 0;
1023}
1024
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001025int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001026 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301028 int i, num_devices = 0;
1029 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001030 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1031
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001032 if (snd_device < SND_DEVICE_MIN ||
1033 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001034 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001035 return -EINVAL;
1036 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037
1038 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001039
1040 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1041 ALOGE("%s: Invalid sound device returned", __func__);
1042 return -EINVAL;
1043 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001045 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001046 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 return 0;
1048 }
1049
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301050
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001051 if (audio_extn_spkr_prot_is_enabled())
1052 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001053
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001054 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1055 audio_extn_spkr_prot_is_enabled()) {
1056 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001057 adev->snd_dev_ref_cnt[snd_device]--;
1058 return -EINVAL;
1059 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001060 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001061 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001062 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001063 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001064 return -EINVAL;
1065 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001066 } else if (platform_split_snd_device(adev->platform,
1067 snd_device,
1068 &num_devices,
1069 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301070 for (i = 0; i < num_devices; i++) {
1071 enable_snd_device(adev, new_snd_devices[i]);
1072 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001073 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001074 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301075
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301076
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301077 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1078 (audio_extn_a2dp_start_playback() < 0)) {
1079 ALOGE(" fail to configure A2dp control path ");
1080 return -EINVAL;
1081 }
1082
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001083 /* due to the possibility of calibration overwrite between listen
1084 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001085 audio_extn_sound_trigger_update_device_status(snd_device,
1086 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301087 audio_extn_listen_update_device_status(snd_device,
1088 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001089 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001090 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001091 audio_extn_sound_trigger_update_device_status(snd_device,
1092 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301093 audio_extn_listen_update_device_status(snd_device,
1094 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001095 return -EINVAL;
1096 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001097 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001098 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301099
1100 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1101 !adev->native_playback_enabled &&
1102 audio_is_true_native_stream_active(adev)) {
1103 ALOGD("%s: %d: napb: enabling native mode in hardware",
1104 __func__, __LINE__);
1105 audio_route_apply_and_update_path(adev->audio_route,
1106 "true-native-mode");
1107 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301108 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001109 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1110 (audio_extn_ffv_get_stream() == adev->active_input)) {
1111 ALOGD("%s: init ec ref loopback", __func__);
1112 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 return 0;
1116}
1117
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001118int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001119 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301121 int i, num_devices = 0;
1122 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001123 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1124
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001125 if (snd_device < SND_DEVICE_MIN ||
1126 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001127 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001128 return -EINVAL;
1129 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1131 ALOGE("%s: device ref cnt is already 0", __func__);
1132 return -EINVAL;
1133 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001136
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001137 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1138 ALOGE("%s: Invalid sound device returned", __func__);
1139 return -EINVAL;
1140 }
1141
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001143 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301144
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001145 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1146 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001147 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001148
1149 // when speaker device is disabled, reset swap.
1150 // will be renabled on usecase start
1151 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001152 } else if (platform_split_snd_device(adev->platform,
1153 snd_device,
1154 &num_devices,
1155 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301156 for (i = 0; i < num_devices; i++) {
1157 disable_snd_device(adev, new_snd_devices[i]);
1158 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001159 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001160 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001161 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001162
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301163 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1164 audio_extn_a2dp_stop_playback();
1165
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001166 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301167 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301168 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1169 adev->native_playback_enabled) {
1170 ALOGD("%s: %d: napb: disabling native mode in hardware",
1171 __func__, __LINE__);
1172 audio_route_reset_and_update_path(adev->audio_route,
1173 "true-native-mode");
1174 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301175 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1176 adev->asrc_mode_enabled) {
1177 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301178 disable_asrc_mode(adev);
1179 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301180 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001181 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1182 (audio_extn_ffv_get_stream() == adev->active_input)) {
1183 ALOGD("%s: deinit ec ref loopback", __func__);
1184 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1185 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001186 audio_extn_utils_release_snd_device(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189 return 0;
1190}
1191
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001192/*
1193 legend:
1194 uc - existing usecase
1195 new_uc - new usecase
1196 d1, d11, d2 - SND_DEVICE enums
1197 a1, a2 - corresponding ANDROID device enums
1198 B1, B2 - backend strings
1199
1200case 1
1201 uc->dev d1 (a1) B1
1202 new_uc->dev d1 (a1), d2 (a2) B1, B2
1203
1204 resolution: disable and enable uc->dev on d1
1205
1206case 2
1207 uc->dev d1 (a1) B1
1208 new_uc->dev d11 (a1) B1
1209
1210 resolution: need to switch uc since d1 and d11 are related
1211 (e.g. speaker and voice-speaker)
1212 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1213
1214case 3
1215 uc->dev d1 (a1) B1
1216 new_uc->dev d2 (a2) B2
1217
1218 resolution: no need to switch uc
1219
1220case 4
1221 uc->dev d1 (a1) B1
1222 new_uc->dev d2 (a2) B1
1223
1224 resolution: disable enable uc-dev on d2 since backends match
1225 we cannot enable two streams on two different devices if they
1226 share the same backend. e.g. if offload is on speaker device using
1227 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1228 using the same backend, offload must also be switched to voice-handset.
1229
1230case 5
1231 uc->dev d1 (a1) B1
1232 new_uc->dev d1 (a1), d2 (a2) B1
1233
1234 resolution: disable enable uc-dev on d2 since backends match
1235 we cannot enable two streams on two different devices if they
1236 share the same backend.
1237
1238case 6
1239 uc->dev d1 (a1) B1
1240 new_uc->dev d2 (a1) B2
1241
1242 resolution: no need to switch
1243
1244case 7
1245 uc->dev d1 (a1), d2 (a2) B1, B2
1246 new_uc->dev d1 (a1) B1
1247
1248 resolution: no need to switch
1249
Zhou Song4ba65882018-07-09 14:48:07 +08001250case 8
1251 uc->dev d1 (a1) B1
1252 new_uc->dev d11 (a1), d2 (a2) B1, B2
1253 resolution: compared to case 1, for this case, d1 and d11 are related
1254 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001255*/
1256static snd_device_t derive_playback_snd_device(void * platform,
1257 struct audio_usecase *uc,
1258 struct audio_usecase *new_uc,
1259 snd_device_t new_snd_device)
1260{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301261 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001262
1263 snd_device_t d1 = uc->out_snd_device;
1264 snd_device_t d2 = new_snd_device;
1265
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301266 switch (uc->type) {
1267 case TRANSCODE_LOOPBACK :
1268 a1 = uc->stream.inout->out_config.devices;
1269 a2 = new_uc->stream.inout->out_config.devices;
1270 break;
1271 default :
1272 a1 = uc->stream.out->devices;
1273 a2 = new_uc->stream.out->devices;
1274 break;
1275 }
1276
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001277 // Treat as a special case when a1 and a2 are not disjoint
1278 if ((a1 != a2) && (a1 & a2)) {
1279 snd_device_t d3[2];
1280 int num_devices = 0;
1281 int ret = platform_split_snd_device(platform,
1282 popcount(a1) > 1 ? d1 : d2,
1283 &num_devices,
1284 d3);
1285 if (ret < 0) {
1286 if (ret != -ENOSYS) {
1287 ALOGW("%s failed to split snd_device %d",
1288 __func__,
1289 popcount(a1) > 1 ? d1 : d2);
1290 }
1291 goto end;
1292 }
1293
1294 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1295 // But if it does happen, we need to give priority to d2 if
1296 // the combo devices active on the existing usecase share a backend.
1297 // This is because we cannot have a usecase active on a combo device
1298 // and a new usecase requests one device in this combo pair.
1299 if (platform_check_backends_match(d3[0], d3[1])) {
1300 return d2; // case 5
1301 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001302 // check if d1 is related to any of d3's
1303 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001304 return d1; // case 1
1305 else
1306 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001307 }
1308 } else {
1309 if (platform_check_backends_match(d1, d2)) {
1310 return d2; // case 2, 4
1311 } else {
1312 return d1; // case 6, 3
1313 }
1314 }
1315
1316end:
1317 return d2; // return whatever was calculated before.
1318}
1319
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001320static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301321 struct audio_usecase *uc_info,
1322 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323{
1324 struct listnode *node;
1325 struct audio_usecase *usecase;
1326 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301327 snd_device_t uc_derive_snd_device;
1328 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001329 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1330 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001331 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301332 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001333 /*
1334 * This function is to make sure that all the usecases that are active on
1335 * the hardware codec backend are always routed to any one device that is
1336 * handled by the hardware codec.
1337 * For example, if low-latency and deep-buffer usecases are currently active
1338 * on speaker and out_set_parameters(headset) is received on low-latency
1339 * output, then we have to make sure deep-buffer is also switched to headset,
1340 * because of the limitation that both the devices cannot be enabled
1341 * at the same time as they share the same backend.
1342 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001343 /*
1344 * This call is to check if we need to force routing for a particular stream
1345 * If there is a backend configuration change for the device when a
1346 * new stream starts, then ADM needs to be closed and re-opened with the new
1347 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001348 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001349 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001350 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1351 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301352 /* For a2dp device reconfigure all active sessions
1353 * with new AFE encoder format based on a2dp state
1354 */
1355 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1356 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1357 audio_extn_a2dp_is_force_device_switch()) {
1358 force_routing = true;
1359 force_restart_session = true;
1360 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301361 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1362
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001363 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001364 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001365 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1367 switch_device[i] = false;
1368
1369 list_for_each(node, &adev->usecase_list) {
1370 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001371
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301372 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1373 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301374 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301375 platform_get_snd_device_name(usecase->out_snd_device),
1376 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301377 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1378 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1379 usecase, uc_info, snd_device);
1380 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1381 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1382 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1383 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001384 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301385 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1386 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1387 ((force_restart_session) ||
1388 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301389 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1390 __func__, use_case_table[usecase->id],
1391 platform_get_snd_device_name(usecase->out_snd_device));
1392 disable_audio_route(adev, usecase);
1393 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301394 /* Enable existing usecase on derived playback device */
1395 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301396 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301397 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001398 }
1399 }
1400
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301401 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1402 num_uc_to_switch);
1403
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001405 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001406
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301407 /* Make sure the previous devices to be disabled first and then enable the
1408 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409 list_for_each(node, &adev->usecase_list) {
1410 usecase = node_to_item(node, struct audio_usecase, list);
1411 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001412 /* Check if output sound device to be switched can be split and if any
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001413 of the split devices match with derived sound device */
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001414 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1415 &num_devices, split_snd_devices) == 0) {
1416 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1417 if (adev->snd_dev_ref_cnt[usecase->out_snd_device] == 0) {
1418 ALOGD("%s: disabling snd_device(%d)", __func__, usecase->out_snd_device);
1419 for (i = 0; i < num_devices; i++) {
1420 /* Disable devices that do not match with derived sound device */
1421 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1422 disable_snd_device(adev, split_snd_devices[i]);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001423 }
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001424 audio_extn_utils_release_snd_device(usecase->out_snd_device);
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001425 }
1426 } else {
1427 disable_snd_device(adev, usecase->out_snd_device);
1428 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429 }
1430 }
1431
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001432 list_for_each(node, &adev->usecase_list) {
1433 usecase = node_to_item(node, struct audio_usecase, list);
1434 if (switch_device[usecase->id]) {
Aniket Kumar Lata1be15992018-10-15 12:12:59 -07001435 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1436 &num_devices, split_snd_devices) == 0) {
1437 /* Enable derived sound device only if it does not match with
1438 one of the split sound devices. This is because the matching
1439 sound device was not disabled */
1440 bool should_enable = true;
1441 for (i = 0; i < num_devices; i++) {
1442 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1443 should_enable = false;
1444 break;
1445 }
1446 }
1447 if (should_enable)
1448 enable_snd_device(adev, derive_snd_device[usecase->id]);
1449 } else {
1450 enable_snd_device(adev, derive_snd_device[usecase->id]);
1451 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001452 }
1453 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001455 /* Re-route all the usecases on the shared backend other than the
1456 specified usecase to new snd devices */
1457 list_for_each(node, &adev->usecase_list) {
1458 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301459 /* Update the out_snd_device only before enabling the audio route */
1460 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301461 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301462 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301463 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301464 use_case_table[usecase->id],
1465 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001466 /* Update voc calibration before enabling VoIP route */
1467 if (usecase->type == VOIP_CALL)
1468 status = platform_switch_voice_call_device_post(adev->platform,
1469 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001470 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301471 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001472 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1473 out_set_voip_volume(&usecase->stream.out->stream,
1474 usecase->stream.out->volume_l,
1475 usecase->stream.out->volume_r);
1476 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001477 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1478 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1479 if (parms)
1480 audio_extn_fm_set_parameters(adev, parms);
1481 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301482 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 }
1484 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 }
1486}
1487
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301488static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001489 struct audio_usecase *uc_info,
1490 snd_device_t snd_device)
1491{
1492 struct listnode *node;
1493 struct audio_usecase *usecase;
1494 bool switch_device[AUDIO_USECASE_MAX];
1495 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301496 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001497 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001498
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301499 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1500 snd_device);
1501 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301502
1503 /*
1504 * Make sure out devices is checked against out codec backend device and
1505 * also in devices against in codec backend. Checking out device against in
1506 * codec backend or vice versa causes issues.
1507 */
1508 if (uc_info->type == PCM_CAPTURE)
1509 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001510 /*
1511 * This function is to make sure that all the active capture usecases
1512 * are always routed to the same input sound device.
1513 * For example, if audio-record and voice-call usecases are currently
1514 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1515 * is received for voice call then we have to make sure that audio-record
1516 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1517 * because of the limitation that two devices cannot be enabled
1518 * at the same time if they share the same backend.
1519 */
1520 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1521 switch_device[i] = false;
1522
1523 list_for_each(node, &adev->usecase_list) {
1524 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301525 /*
1526 * TODO: Enhance below condition to handle BT sco/USB multi recording
1527 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001528 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001529 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301530 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301531 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301532 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301533 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001534 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001535 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1536 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001537 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001538 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001539 switch_device[usecase->id] = true;
1540 num_uc_to_switch++;
1541 }
1542 }
1543
1544 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001545 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001546
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301547 /* Make sure the previous devices to be disabled first and then enable the
1548 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001549 list_for_each(node, &adev->usecase_list) {
1550 usecase = node_to_item(node, struct audio_usecase, list);
1551 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001552 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001553 }
1554 }
1555
1556 list_for_each(node, &adev->usecase_list) {
1557 usecase = node_to_item(node, struct audio_usecase, list);
1558 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001559 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001560 }
1561 }
1562
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001563 /* Re-route all the usecases on the shared backend other than the
1564 specified usecase to new snd devices */
1565 list_for_each(node, &adev->usecase_list) {
1566 usecase = node_to_item(node, struct audio_usecase, list);
1567 /* Update the in_snd_device only before enabling the audio route */
1568 if (switch_device[usecase->id] ) {
1569 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001570 if (usecase->type != VOICE_CALL) {
1571 /* Update voc calibration before enabling VoIP route */
1572 if (usecase->type == VOIP_CALL)
1573 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001574 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001575 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301576 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001577 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001578 }
1579 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001580 }
1581}
1582
Mingming Yin3a941d42016-02-17 18:08:05 -08001583static void reset_hdmi_sink_caps(struct stream_out *out) {
1584 int i = 0;
1585
1586 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1587 out->supported_channel_masks[i] = 0;
1588 }
1589 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1590 out->supported_formats[i] = 0;
1591 }
1592 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1593 out->supported_sample_rates[i] = 0;
1594 }
1595}
1596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001598static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599{
Mingming Yin3a941d42016-02-17 18:08:05 -08001600 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001601 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602
Mingming Yin3a941d42016-02-17 18:08:05 -08001603 reset_hdmi_sink_caps(out);
1604
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001605 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001606 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001607 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001608 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001609 }
1610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001613 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001614 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001615 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1616 case 6:
1617 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1618 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1619 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1620 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1621 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1622 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 break;
1624 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001625 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001626 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 break;
1628 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001629
1630 // check channel format caps
1631 i = 0;
1632 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1633 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1634 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1635 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1636 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1637 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1638 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1639 }
1640
Ben Romberger1aaaf862017-04-06 17:49:46 -07001641 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1642 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1643 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1644 }
1645
Mingming Yin3a941d42016-02-17 18:08:05 -08001646 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1647 ALOGV(":%s HDMI supports DTS format", __func__);
1648 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1649 }
1650
1651 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1652 ALOGV(":%s HDMI supports DTS HD format", __func__);
1653 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1654 }
1655
Naresh Tanniru928f0862017-04-07 16:44:23 -07001656 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1657 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1658 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1659 }
1660
Mingming Yin3a941d42016-02-17 18:08:05 -08001661
1662 // check sample rate caps
1663 i = 0;
1664 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1665 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1666 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1667 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1668 }
1669 }
1670
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001671 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672}
1673
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001674static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1675 uint32_t *supported_sample_rates __unused,
1676 uint32_t max_rates __unused)
1677{
1678 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1679 supported_sample_rates,
1680 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301681 ssize_t i = 0;
1682
1683 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001684 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1685 supported_sample_rates[i]);
1686 }
1687 return count;
1688}
1689
1690static inline int read_usb_sup_channel_masks(bool is_playback,
1691 audio_channel_mask_t *supported_channel_masks,
1692 uint32_t max_masks)
1693{
1694 int channels = audio_extn_usb_get_max_channels(is_playback);
1695 int channel_count;
1696 uint32_t num_masks = 0;
1697 if (channels > MAX_HIFI_CHANNEL_COUNT)
1698 channels = MAX_HIFI_CHANNEL_COUNT;
1699
1700 if (is_playback) {
1701 // For playback we never report mono because the framework always outputs stereo
1702 channel_count = DEFAULT_CHANNEL_COUNT;
1703 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1704 // above 2 but we want indexed masks here. So we
1705 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1706 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1707 }
1708 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1709 supported_channel_masks[num_masks++] =
1710 audio_channel_mask_for_index_assignment_from_count(channel_count);
1711 }
1712 } else {
1713 // For capture we report all supported channel masks from 1 channel up.
1714 channel_count = MIN_CHANNEL_COUNT;
1715 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1716 // indexed mask
1717 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1718 supported_channel_masks[num_masks++] =
1719 audio_channel_in_mask_from_count(channel_count);
1720 }
1721 }
1722 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1723 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1724 return num_masks;
1725}
1726
1727static inline int read_usb_sup_formats(bool is_playback __unused,
1728 audio_format_t *supported_formats,
1729 uint32_t max_formats __unused)
1730{
1731 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1732 switch (bitwidth) {
1733 case 24:
1734 // XXX : usb.c returns 24 for s24 and s24_le?
1735 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1736 break;
1737 case 32:
1738 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1739 break;
1740 case 16:
1741 default :
1742 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1743 break;
1744 }
1745 ALOGV("%s: %s supported format %d", __func__,
1746 is_playback ? "P" : "C", bitwidth);
1747 return 1;
1748}
1749
1750static inline int read_usb_sup_params_and_compare(bool is_playback,
1751 audio_format_t *format,
1752 audio_format_t *supported_formats,
1753 uint32_t max_formats,
1754 audio_channel_mask_t *mask,
1755 audio_channel_mask_t *supported_channel_masks,
1756 uint32_t max_masks,
1757 uint32_t *rate,
1758 uint32_t *supported_sample_rates,
1759 uint32_t max_rates) {
1760 int ret = 0;
1761 int num_formats;
1762 int num_masks;
1763 int num_rates;
1764 int i;
1765
1766 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1767 max_formats);
1768 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1769 max_masks);
1770
1771 num_rates = read_usb_sup_sample_rates(is_playback,
1772 supported_sample_rates, max_rates);
1773
1774#define LUT(table, len, what, dflt) \
1775 for (i=0; i<len && (table[i] != what); i++); \
1776 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1777
1778 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1779 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1780 LUT(supported_sample_rates, num_rates, *rate, 0);
1781
1782#undef LUT
1783 return ret < 0 ? -EINVAL : 0; // HACK TBD
1784}
1785
Alexy Josephb1379942016-01-29 15:49:38 -08001786audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001787 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001788{
1789 struct audio_usecase *usecase;
1790 struct listnode *node;
1791
1792 list_for_each(node, &adev->usecase_list) {
1793 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001794 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001795 ALOGV("%s: usecase id %d", __func__, usecase->id);
1796 return usecase->id;
1797 }
1798 }
1799 return USECASE_INVALID;
1800}
1801
Alexy Josephb1379942016-01-29 15:49:38 -08001802struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001803 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001804{
1805 struct audio_usecase *usecase;
1806 struct listnode *node;
1807
1808 list_for_each(node, &adev->usecase_list) {
1809 usecase = node_to_item(node, struct audio_usecase, list);
1810 if (usecase->id == uc_id)
1811 return usecase;
1812 }
1813 return NULL;
1814}
1815
Dhananjay Kumard4833242016-10-06 22:09:12 +05301816struct stream_in *get_next_active_input(const struct audio_device *adev)
1817{
1818 struct audio_usecase *usecase;
1819 struct listnode *node;
1820
1821 list_for_each_reverse(node, &adev->usecase_list) {
1822 usecase = node_to_item(node, struct audio_usecase, list);
1823 if (usecase->type == PCM_CAPTURE)
1824 return usecase->stream.in;
1825 }
1826 return NULL;
1827}
1828
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301829/*
1830 * is a true native playback active
1831 */
1832bool audio_is_true_native_stream_active(struct audio_device *adev)
1833{
1834 bool active = false;
1835 int i = 0;
1836 struct listnode *node;
1837
1838 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1839 ALOGV("%s:napb: not in true mode or non hdphones device",
1840 __func__);
1841 active = false;
1842 goto exit;
1843 }
1844
1845 list_for_each(node, &adev->usecase_list) {
1846 struct audio_usecase *uc;
1847 uc = node_to_item(node, struct audio_usecase, list);
1848 struct stream_out *curr_out =
1849 (struct stream_out*) uc->stream.out;
1850
1851 if (curr_out && PCM_PLAYBACK == uc->type) {
1852 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1853 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1854 uc->id, curr_out->sample_rate,
1855 curr_out->bit_width,
1856 platform_get_snd_device_name(uc->out_snd_device));
1857
1858 if (is_offload_usecase(uc->id) &&
1859 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1860 active = true;
1861 ALOGD("%s:napb:native stream detected", __func__);
1862 }
1863 }
1864 }
1865exit:
1866 return active;
1867}
1868
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001869uint32_t adev_get_dsp_bit_width_enforce_mode()
1870{
1871 if (adev == NULL) {
1872 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1873 return 0;
1874 }
1875 return adev->dsp_bit_width_enforce_mode;
1876}
1877
1878static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1879{
1880 char value[PROPERTY_VALUE_MAX];
1881 int trial;
1882 uint32_t dsp_bit_width_enforce_mode = 0;
1883
1884 if (!mixer) {
1885 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1886 __func__);
1887 return 0;
1888 }
1889
1890 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1891 value, NULL) > 0) {
1892 trial = atoi(value);
1893 switch (trial) {
1894 case 16:
1895 dsp_bit_width_enforce_mode = 16;
1896 break;
1897 case 24:
1898 dsp_bit_width_enforce_mode = 24;
1899 break;
1900 case 32:
1901 dsp_bit_width_enforce_mode = 32;
1902 break;
1903 default:
1904 dsp_bit_width_enforce_mode = 0;
1905 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1906 break;
1907 }
1908 }
1909
1910 return dsp_bit_width_enforce_mode;
1911}
1912
1913static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1914 uint32_t enforce_mode,
1915 bool enable)
1916{
1917 struct mixer_ctl *ctl = NULL;
1918 const char *mixer_ctl_name = "ASM Bit Width";
1919 uint32_t asm_bit_width_mode = 0;
1920
1921 if (enforce_mode == 0) {
1922 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1923 return;
1924 }
1925
1926 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1927 if (!ctl) {
1928 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1929 __func__, mixer_ctl_name);
1930 return;
1931 }
1932
1933 if (enable)
1934 asm_bit_width_mode = enforce_mode;
1935 else
1936 asm_bit_width_mode = 0;
1937
1938 ALOGV("%s DSP bit width feature status is %d width=%d",
1939 __func__, enable, asm_bit_width_mode);
1940 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1941 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1942 asm_bit_width_mode);
1943
1944 return;
1945}
1946
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301947/*
1948 * if native DSD playback active
1949 */
1950bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1951{
1952 bool active = false;
1953 struct listnode *node = NULL;
1954 struct audio_usecase *uc = NULL;
1955 struct stream_out *curr_out = NULL;
1956
1957 list_for_each(node, &adev->usecase_list) {
1958 uc = node_to_item(node, struct audio_usecase, list);
1959 curr_out = (struct stream_out*) uc->stream.out;
1960
1961 if (curr_out && PCM_PLAYBACK == uc->type &&
1962 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1963 active = true;
1964 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301965 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301966 }
1967 }
1968 return active;
1969}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301970
1971static bool force_device_switch(struct audio_usecase *usecase)
1972{
1973 bool ret = false;
1974 bool is_it_true_mode = false;
1975
Zhou Song30f2c3e2018-02-08 14:02:15 +08001976 if (usecase->type == PCM_CAPTURE ||
1977 usecase->type == TRANSCODE_LOOPBACK) {
1978 return false;
1979 }
1980
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001981 if(usecase->stream.out == NULL) {
1982 ALOGE("%s: stream.out is NULL", __func__);
1983 return false;
1984 }
1985
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301986 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001987 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1988 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1989 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301990 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1991 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1992 (!is_it_true_mode && adev->native_playback_enabled)){
1993 ret = true;
1994 ALOGD("napb: time to toggle native mode");
1995 }
1996 }
1997
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301998 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301999 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2000 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002001 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302002 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302003 ALOGD("Force a2dp device switch to update new encoder config");
2004 ret = true;
2005 }
2006
Manish Dewangan671a4202017-08-18 17:30:46 +05302007 if (usecase->stream.out->stream_config_changed) {
2008 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2009 return true;
2010 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302011 return ret;
2012}
2013
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302014bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2015{
2016 bool ret=false;
2017 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2018 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2019 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2020 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2021 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2022 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2023 ret = true;
2024
2025 return ret;
2026}
2027
2028bool is_a2dp_device(snd_device_t out_snd_device)
2029{
2030 bool ret=false;
2031 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2032 ret = true;
2033
2034 return ret;
2035}
2036
2037bool is_bt_soc_on(struct audio_device *adev)
2038{
2039 struct mixer_ctl *ctl;
2040 char *mixer_ctl_name = "BT SOC status";
2041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2042 bool bt_soc_status = true;
2043 if (!ctl) {
2044 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2045 __func__, mixer_ctl_name);
2046 /*This is to ensure we dont break targets which dont have the kernel change*/
2047 return true;
2048 }
2049 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2050 ALOGD("BT SOC status: %d",bt_soc_status);
2051 return bt_soc_status;
2052}
2053
2054int out_standby_l(struct audio_stream *stream);
2055
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002056int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002058 snd_device_t out_snd_device = SND_DEVICE_NONE;
2059 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002060 struct audio_usecase *usecase = NULL;
2061 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002062 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002063 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302064 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002065 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002066 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002067 audio_devices_t audio_device;
2068 audio_channel_mask_t channel_mask;
2069 int sample_rate;
2070 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302072 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2073
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002074 usecase = get_usecase_from_list(adev, uc_id);
2075 if (usecase == NULL) {
2076 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2077 return -EINVAL;
2078 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002080 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002081 (usecase->type == VOIP_CALL) ||
2082 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302083 if(usecase->stream.out == NULL) {
2084 ALOGE("%s: stream.out is NULL", __func__);
2085 return -EINVAL;
2086 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002087 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002088 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002089 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002090 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302091 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2092 if (usecase->stream.inout == NULL) {
2093 ALOGE("%s: stream.inout is NULL", __func__);
2094 return -EINVAL;
2095 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302096 stream_out.devices = usecase->stream.inout->out_config.devices;
2097 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2098 stream_out.format = usecase->stream.inout->out_config.format;
2099 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2100 out_snd_device = platform_get_output_snd_device(adev->platform,
2101 &stream_out);
2102 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302103 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002104 } else {
2105 /*
2106 * If the voice call is active, use the sound devices of voice call usecase
2107 * so that it would not result any device switch. All the usecases will
2108 * be switched to new device when select_devices() is called for voice call
2109 * usecase. This is to avoid switching devices for voice call when
2110 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002111 * choose voice call device only if the use case device is
2112 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002113 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002114 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002115 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002116 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002117 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2118 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302119 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2120 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002121 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002122 in_snd_device = vc_usecase->in_snd_device;
2123 out_snd_device = vc_usecase->out_snd_device;
2124 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002125 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002126 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002127 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002128 if ((voip_usecase != NULL) &&
2129 (usecase->type == PCM_PLAYBACK) &&
2130 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002131 out_snd_device_backend_match = platform_check_backends_match(
2132 voip_usecase->out_snd_device,
2133 platform_get_output_snd_device(
2134 adev->platform,
2135 usecase->stream.out));
2136 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002137 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002138 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2139 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002140 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002141 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002142 in_snd_device = voip_usecase->in_snd_device;
2143 out_snd_device = voip_usecase->out_snd_device;
2144 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002145 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002146 hfp_ucid = audio_extn_hfp_get_usecase();
2147 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002148 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002149 in_snd_device = hfp_usecase->in_snd_device;
2150 out_snd_device = hfp_usecase->out_snd_device;
2151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 }
2153 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302154 if (usecase->stream.out == NULL) {
2155 ALOGE("%s: stream.out is NULL", __func__);
2156 return -EINVAL;
2157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002158 usecase->devices = usecase->stream.out->devices;
2159 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002160 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002161 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002162 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002163 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleiz3ca773f2018-10-12 15:49:35 +08002164 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002165 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2166
2167 if ((usecase->stream.out != NULL &&
2168 voip_usecase != NULL &&
2169 usecase->stream.out->usecase == voip_usecase->id) &&
2170 adev->active_input &&
kunleiz3ca773f2018-10-12 15:49:35 +08002171 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002172 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002173 select_devices(adev, adev->active_input->usecase);
2174 }
2175 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002176 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302177 if (usecase->stream.in == NULL) {
2178 ALOGE("%s: stream.in is NULL", __func__);
2179 return -EINVAL;
2180 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 usecase->devices = usecase->stream.in->device;
2182 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002183 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002185 if (adev->active_input &&
2186 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302187 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002188 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2189 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2190 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2191 out_device = voip_usecase->stream.out->devices;
2192 else if (adev->primary_output && !adev->primary_output->standby)
2193 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002194 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002195 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2196 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002197 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002198 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002199 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200 }
2201 }
2202
2203 if (out_snd_device == usecase->out_snd_device &&
2204 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302205
2206 if (!force_device_switch(usecase))
2207 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 }
2209
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302210 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2211 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2212 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2213 return 0;
2214 }
2215
sangwoobc677242013-08-08 16:53:43 +09002216 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002217 out_snd_device, platform_get_snd_device_name(out_snd_device),
2218 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 /*
2221 * Limitation: While in call, to do a device switch we need to disable
2222 * and enable both RX and TX devices though one of them is same as current
2223 * device.
2224 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002225 if ((usecase->type == VOICE_CALL) &&
2226 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2227 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002228 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002229 }
2230
2231 if (((usecase->type == VOICE_CALL) ||
2232 (usecase->type == VOIP_CALL)) &&
2233 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2234 /* Disable sidetone only if voice/voip call already exists */
2235 if (voice_is_call_state_active(adev) ||
2236 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002237 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002238
2239 /* Disable aanc only if voice call exists */
2240 if (voice_is_call_state_active(adev))
2241 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002242 }
2243
Zhou Songc66eb7e2017-08-08 18:29:07 +08002244 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302245 (!audio_extn_a2dp_is_ready())) {
2246 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002247 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302248 }
2249
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002250 /* Disable current sound devices */
2251 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002252 disable_audio_route(adev, usecase);
2253 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 }
2255
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002256 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002257 disable_audio_route(adev, usecase);
2258 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
2260
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002261 /* Applicable only on the targets that has external modem.
2262 * New device information should be sent to modem before enabling
2263 * the devices to reduce in-call device switch time.
2264 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002265 if ((usecase->type == VOICE_CALL) &&
2266 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2267 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002268 status = platform_switch_voice_call_enable_device_config(adev->platform,
2269 out_snd_device,
2270 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002271 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002273 /* Enable new sound devices */
2274 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002275 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302276 if (platform_check_codec_asrc_support(adev->platform))
2277 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002278 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 }
2280
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002281 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302282 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002283 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002284 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002285
Avinash Vaish71a8b972014-07-24 15:36:33 +05302286 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002287 status = platform_switch_voice_call_device_post(adev->platform,
2288 out_snd_device,
2289 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302290 enable_audio_route_for_voice_usecases(adev, usecase);
2291 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002292
sangwoo170731f2013-06-08 15:36:36 +09002293 usecase->in_snd_device = in_snd_device;
2294 usecase->out_snd_device = out_snd_device;
2295
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302296 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2297 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302298 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002299 if ((24 == usecase->stream.out->bit_width) &&
2300 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2301 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2302 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2303 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2304 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2305 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2306 /*
2307 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2308 * configured device sample rate, if not update the COPP rate to be equal to the
2309 * device sample rate, else open COPP at stream sample rate
2310 */
2311 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2312 usecase->stream.out->sample_rate,
2313 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302314 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2315 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002316 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2317 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2318 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2319 }
2320
Weiyin Jiang5d608082018-02-01 17:24:33 +08002321 /* Cache stream information to be notified to gef clients */
2322 audio_device = usecase->stream.out->devices;
2323 channel_mask = usecase->stream.out->channel_mask;
2324 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2325 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302326 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002327 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002328
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002329 /* If input stream is already running then effect needs to be
2330 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002331 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2332 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002333 check_and_enable_effect(adev);
2334
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002335 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002336 /* Enable aanc only if voice call exists */
2337 if (voice_is_call_state_active(adev))
2338 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2339
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002340 /* Enable sidetone only if other voice/voip call already exists */
2341 if (voice_is_call_state_active(adev) ||
2342 voice_extn_compress_voip_is_started(adev))
2343 voice_set_sidetone(adev, out_snd_device, true);
2344 }
2345
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002346 /* Applicable only on the targets that has external modem.
2347 * Enable device command should be sent to modem only after
2348 * enabling voice call mixer controls
2349 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002350 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002351 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2352 out_snd_device,
2353 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302354
2355 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2356
2357 if (usecase->type == VOIP_CALL) {
2358 if (adev->active_input != NULL &&
2359 !adev->active_input->standby) {
2360 if (is_bt_soc_on(adev) == false){
2361 ALOGD("BT SCO MIC disconnected while in connection");
2362 if (adev->active_input->pcm != NULL)
2363 pcm_stop(adev->active_input->pcm);
2364 }
2365 }
2366 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2367 && usecase->stream.out->started) {
2368 if (is_bt_soc_on(adev) == false) {
2369 ALOGD("BT SCO/A2DP disconnected while in connection");
2370 out_standby_l(&usecase->stream.out->stream.common);
2371 }
2372 }
2373 } else if ((usecase->stream.out != NULL) &&
2374 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2375 usecase->stream.out->started) {
2376 if (is_bt_soc_on(adev) == false) {
2377 ALOGD("BT SCO/A2dp disconnected while in connection");
2378 out_standby_l(&usecase->stream.out->stream.common);
2379 }
2380 }
2381 }
2382
Weiyin Jiang5d608082018-02-01 17:24:33 +08002383 /* Notify device change info to effect clients registered
2384 * NOTE: device lock has to be unlock temporarily here.
2385 * To the worst case, we notify stale info to clients.
2386 */
2387 if (usecase->type == PCM_PLAYBACK) {
2388 pthread_mutex_unlock(&adev->lock);
2389 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2390 pthread_mutex_lock(&adev->lock);
2391 }
2392
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302393 ALOGD("%s: done",__func__);
2394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 return status;
2396}
2397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398static int stop_input_stream(struct stream_in *in)
2399{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302400 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302402
2403 if (in == NULL) {
2404 ALOGE("%s: stream_in ptr is NULL", __func__);
2405 return -EINVAL;
2406 }
2407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 struct audio_device *adev = in->dev;
2409
Eric Laurent994a6932013-07-17 11:51:42 -07002410 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002411 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 uc_info = get_usecase_from_list(adev, in->usecase);
2413 if (uc_info == NULL) {
2414 ALOGE("%s: Could not find the usecase (%d) in the list",
2415 __func__, in->usecase);
2416 return -EINVAL;
2417 }
2418
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002419 /* Close in-call recording streams */
2420 voice_check_and_stop_incall_rec_usecase(adev, in);
2421
Eric Laurent150dbfe2013-02-27 14:31:02 -08002422 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002423 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002424
2425 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002426 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002428 list_remove(&uc_info->list);
2429 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002431 adev->active_input = get_next_active_input(adev);
2432
Eric Laurent994a6932013-07-17 11:51:42 -07002433 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434 return ret;
2435}
2436
2437int start_input_stream(struct stream_in *in)
2438{
2439 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002440 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302442
2443 if (in == NULL) {
2444 ALOGE("%s: stream_in ptr is NULL", __func__);
2445 return -EINVAL;
2446 }
2447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002449 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002450 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451
Mingming Yin2664a5b2015-09-03 10:53:11 -07002452 if (get_usecase_from_list(adev, usecase) == NULL)
2453 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302454 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2455 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002456
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302457 if (CARD_STATUS_OFFLINE == in->card_status||
2458 CARD_STATUS_OFFLINE == adev->card_status) {
2459 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302460 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302461 goto error_config;
2462 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302463
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302464 if (audio_is_bluetooth_sco_device(in->device)) {
2465 if (!adev->bt_sco_on) {
2466 ALOGE("%s: SCO profile is not ready, return error", __func__);
2467 ret = -EIO;
2468 goto error_config;
2469 }
2470 }
2471
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002472 /* Check if source matches incall recording usecase criteria */
2473 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2474 if (ret)
2475 goto error_config;
2476 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002477 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2478
2479 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2480 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2481 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002482 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002483 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002484
Eric Laurentb23d5282013-05-14 15:27:20 -07002485 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 if (in->pcm_device_id < 0) {
2487 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2488 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002489 ret = -EINVAL;
2490 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002492
2493 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002495
2496 if (!uc_info) {
2497 ret = -ENOMEM;
2498 goto error_config;
2499 }
2500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 uc_info->id = in->usecase;
2502 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002503 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002504 uc_info->devices = in->device;
2505 uc_info->in_snd_device = SND_DEVICE_NONE;
2506 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002508 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302509 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2510 adev->perf_lock_opts,
2511 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002512 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513
Haynes Mathew George16081042017-05-31 17:16:49 -07002514 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302515 ret = audio_extn_cin_start_input_stream(in);
2516 if (ret)
2517 goto error_open;
2518 else
2519 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002520 }
2521
Haynes Mathew George16081042017-05-31 17:16:49 -07002522 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002523 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002524 ALOGE("%s: pcm stream not ready", __func__);
2525 goto error_open;
2526 }
2527 ret = pcm_start(in->pcm);
2528 if (ret < 0) {
2529 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2530 goto error_open;
2531 }
2532 } else {
2533 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2534 unsigned int pcm_open_retry_count = 0;
2535
2536 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2537 flags |= PCM_MMAP | PCM_NOIRQ;
2538 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2539 } else if (in->realtime) {
2540 flags |= PCM_MMAP | PCM_NOIRQ;
2541 }
2542
Garmond Leunge2433c32017-09-28 21:51:22 -07002543 if (audio_extn_ffv_get_stream() == in) {
2544 ALOGD("%s: ffv stream, update pcm config", __func__);
2545 audio_extn_ffv_update_pcm_config(&config);
2546 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002547 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2548 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2549
2550 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002551 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002552 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002553 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002554 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002555 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2556 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2557 if (in->pcm != NULL) {
2558 pcm_close(in->pcm);
2559 in->pcm = NULL;
2560 }
2561 if (pcm_open_retry_count-- == 0) {
2562 ret = -EIO;
2563 goto error_open;
2564 }
2565 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2566 continue;
2567 }
2568 break;
2569 }
2570
2571 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002572 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002573 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002574 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002575 if (ret < 0) {
2576 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2577 pcm_close(in->pcm);
2578 in->pcm = NULL;
2579 goto error_open;
2580 }
2581 register_in_stream(in);
2582 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002583 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002584 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002585 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002586 if (ret < 0) {
2587 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002588 pcm_close(in->pcm);
2589 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002590 goto error_open;
2591 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002592 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002593 }
2594
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002595 check_and_enable_effect(adev);
2596
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302597done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302598 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002599 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002600
Eric Laurentc8400632013-02-14 19:04:54 -08002601 return ret;
2602
2603error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302604 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002606error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302607 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302608 /*
2609 * sleep 50ms to allow sufficient time for kernel
2610 * drivers to recover incases like SSR.
2611 */
2612 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002613 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002614
2615 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616}
2617
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002618void lock_input_stream(struct stream_in *in)
2619{
2620 pthread_mutex_lock(&in->pre_lock);
2621 pthread_mutex_lock(&in->lock);
2622 pthread_mutex_unlock(&in->pre_lock);
2623}
2624
2625void lock_output_stream(struct stream_out *out)
2626{
2627 pthread_mutex_lock(&out->pre_lock);
2628 pthread_mutex_lock(&out->lock);
2629 pthread_mutex_unlock(&out->pre_lock);
2630}
2631
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002632/* must be called with out->lock locked */
2633static int send_offload_cmd_l(struct stream_out* out, int command)
2634{
2635 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2636
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002637 if (!cmd) {
2638 ALOGE("failed to allocate mem for command 0x%x", command);
2639 return -ENOMEM;
2640 }
2641
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002642 ALOGVV("%s %d", __func__, command);
2643
2644 cmd->cmd = command;
2645 list_add_tail(&out->offload_cmd_list, &cmd->node);
2646 pthread_cond_signal(&out->offload_cond);
2647 return 0;
2648}
2649
2650/* must be called iwth out->lock locked */
2651static void stop_compressed_output_l(struct stream_out *out)
2652{
2653 out->offload_state = OFFLOAD_STATE_IDLE;
2654 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002655 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 if (out->compr != NULL) {
2657 compress_stop(out->compr);
2658 while (out->offload_thread_blocked) {
2659 pthread_cond_wait(&out->cond, &out->lock);
2660 }
2661 }
2662}
2663
Varun Balaraje49253e2017-07-06 19:48:56 +05302664bool is_interactive_usecase(audio_usecase_t uc_id)
2665{
2666 unsigned int i;
2667 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2668 if (uc_id == interactive_usecases[i])
2669 return true;
2670 }
2671 return false;
2672}
2673
2674static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2675{
2676 audio_usecase_t ret_uc = USECASE_INVALID;
2677 unsigned int intract_uc_index;
2678 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2679
2680 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2681 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2682 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2683 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2684 ret_uc = interactive_usecases[intract_uc_index];
2685 break;
2686 }
2687 }
2688
2689 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2690 return ret_uc;
2691}
2692
2693static void free_interactive_usecase(struct audio_device *adev,
2694 audio_usecase_t uc_id)
2695{
2696 unsigned int interact_uc_index;
2697 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2698
2699 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2700 if (interactive_usecases[interact_uc_index] == uc_id) {
2701 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2702 break;
2703 }
2704 }
2705 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2706}
2707
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002708bool is_offload_usecase(audio_usecase_t uc_id)
2709{
2710 unsigned int i;
2711 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2712 if (uc_id == offload_usecases[i])
2713 return true;
2714 }
2715 return false;
2716}
2717
Dhananjay Kumarac341582017-02-23 23:42:25 +05302718static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002719{
vivek mehta446c3962015-09-14 10:57:35 -07002720 audio_usecase_t ret_uc = USECASE_INVALID;
2721 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002722 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002723 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302724 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002725 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2726 else
2727 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002728
vivek mehta446c3962015-09-14 10:57:35 -07002729 pthread_mutex_lock(&adev->lock);
2730 if (get_usecase_from_list(adev, ret_uc) != NULL)
2731 ret_uc = USECASE_INVALID;
2732 pthread_mutex_unlock(&adev->lock);
2733
2734 return ret_uc;
2735 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002736
2737 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002738 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2739 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2740 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2741 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002742 break;
2743 }
2744 }
vivek mehta446c3962015-09-14 10:57:35 -07002745
2746 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2747 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002748}
2749
2750static void free_offload_usecase(struct audio_device *adev,
2751 audio_usecase_t uc_id)
2752{
vivek mehta446c3962015-09-14 10:57:35 -07002753 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002754 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002755
2756 if (!adev->multi_offload_enable)
2757 return;
2758
2759 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2760 if (offload_usecases[offload_uc_index] == uc_id) {
2761 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002762 break;
2763 }
2764 }
2765 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2766}
2767
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002768static void *offload_thread_loop(void *context)
2769{
2770 struct stream_out *out = (struct stream_out *) context;
2771 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002772 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002773
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002774 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2775 set_sched_policy(0, SP_FOREGROUND);
2776 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2777
2778 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002779 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 for (;;) {
2781 struct offload_cmd *cmd = NULL;
2782 stream_callback_event_t event;
2783 bool send_callback = false;
2784
2785 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2786 __func__, list_empty(&out->offload_cmd_list),
2787 out->offload_state);
2788 if (list_empty(&out->offload_cmd_list)) {
2789 ALOGV("%s SLEEPING", __func__);
2790 pthread_cond_wait(&out->offload_cond, &out->lock);
2791 ALOGV("%s RUNNING", __func__);
2792 continue;
2793 }
2794
2795 item = list_head(&out->offload_cmd_list);
2796 cmd = node_to_item(item, struct offload_cmd, node);
2797 list_remove(item);
2798
2799 ALOGVV("%s STATE %d CMD %d out->compr %p",
2800 __func__, out->offload_state, cmd->cmd, out->compr);
2801
2802 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2803 free(cmd);
2804 break;
2805 }
2806
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002807 // allow OFFLOAD_CMD_ERROR reporting during standby
2808 // this is needed to handle failures during compress_open
2809 // Note however that on a pause timeout, the stream is closed
2810 // and no offload usecase will be active. Therefore this
2811 // special case is needed for compress_open failures alone
2812 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2813 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002815 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816 pthread_cond_signal(&out->cond);
2817 continue;
2818 }
2819 out->offload_thread_blocked = true;
2820 pthread_mutex_unlock(&out->lock);
2821 send_callback = false;
2822 switch(cmd->cmd) {
2823 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002824 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002826 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002827 send_callback = true;
2828 event = STREAM_CBK_EVENT_WRITE_READY;
2829 break;
2830 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002831 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302832 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002833 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302834 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002835 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302836 if (ret < 0)
2837 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302838 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302839 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002840 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002841 else
2842 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002843 if (-ENETRESET != ret && !(-EINTR == ret &&
2844 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302845 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302846 pthread_mutex_lock(&out->lock);
2847 out->send_new_metadata = 1;
2848 out->send_next_track_params = true;
2849 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302850 event = STREAM_CBK_EVENT_DRAIN_READY;
2851 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2852 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302853 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854 break;
2855 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002856 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002857 ret = compress_drain(out->compr);
2858 ALOGD("copl(%p):out of compress_drain", out);
2859 // EINTR check avoids drain interruption due to SSR
2860 if (-ENETRESET != ret && !(-EINTR == ret &&
2861 CARD_STATUS_OFFLINE == out->card_status)) {
2862 send_callback = true;
2863 event = STREAM_CBK_EVENT_DRAIN_READY;
2864 } else
2865 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302867 case OFFLOAD_CMD_ERROR:
2868 ALOGD("copl(%p): sending error callback to AF", out);
2869 send_callback = true;
2870 event = STREAM_CBK_EVENT_ERROR;
2871 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 default:
2873 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2874 break;
2875 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002876 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->offload_thread_blocked = false;
2878 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002879 if (send_callback && out->client_callback) {
2880 ALOGVV("%s: sending client_callback event %d", __func__, event);
2881 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002882 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 free(cmd);
2884 }
2885
2886 pthread_cond_signal(&out->cond);
2887 while (!list_empty(&out->offload_cmd_list)) {
2888 item = list_head(&out->offload_cmd_list);
2889 list_remove(item);
2890 free(node_to_item(item, struct offload_cmd, node));
2891 }
2892 pthread_mutex_unlock(&out->lock);
2893
2894 return NULL;
2895}
2896
2897static int create_offload_callback_thread(struct stream_out *out)
2898{
2899 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2900 list_init(&out->offload_cmd_list);
2901 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2902 offload_thread_loop, out);
2903 return 0;
2904}
2905
2906static int destroy_offload_callback_thread(struct stream_out *out)
2907{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002908 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909 stop_compressed_output_l(out);
2910 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2911
2912 pthread_mutex_unlock(&out->lock);
2913 pthread_join(out->offload_thread, (void **) NULL);
2914 pthread_cond_destroy(&out->offload_cond);
2915
2916 return 0;
2917}
2918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919static int stop_output_stream(struct stream_out *out)
2920{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302921 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 struct audio_usecase *uc_info;
2923 struct audio_device *adev = out->dev;
2924
Eric Laurent994a6932013-07-17 11:51:42 -07002925 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002926 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 uc_info = get_usecase_from_list(adev, out->usecase);
2928 if (uc_info == NULL) {
2929 ALOGE("%s: Could not find the usecase (%d) in the list",
2930 __func__, out->usecase);
2931 return -EINVAL;
2932 }
2933
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002934 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302935 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002936 if (adev->visualizer_stop_output != NULL)
2937 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002938
2939 audio_extn_dts_remove_state_notifier_node(out->usecase);
2940
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002941 if (adev->offload_effects_stop_output != NULL)
2942 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2943 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002944
Arun Mirpurief53ce52018-09-11 18:00:09 -07002945 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2946 voice_set_device_mute_flag(adev, false);
2947
Eric Laurent150dbfe2013-02-27 14:31:02 -08002948 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002949 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002950
2951 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002952 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002954 if (is_offload_usecase(out->usecase)) {
2955 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2956 adev->dsp_bit_width_enforce_mode,
2957 false);
2958 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002959 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2960 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2961 false);
2962
2963 if (ret != 0)
2964 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2965 /* default service interval was successfully updated,
2966 reopen USB backend with new service interval */
2967 ret = 0;
2968 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002969
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002970 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302971 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002972 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302973 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002974 ALOGV("Disable passthrough , reset mixer to pcm");
2975 /* NO_PASSTHROUGH */
2976 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002977 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002978 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2979 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002980
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302981 /* Must be called after removing the usecase from list */
2982 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302983 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302984
Manish Dewangan21a850a2017-08-14 12:03:55 +05302985 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002986 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2987 if (ret < 0)
2988 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2989 }
2990
Garmond Leung5fd0b552018-04-17 11:56:12 -07002991 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002992 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 return ret;
2994}
2995
2996int start_output_stream(struct stream_out *out)
2997{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 struct audio_usecase *uc_info;
3000 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003001 char mixer_ctl_name[128];
3002 struct mixer_ctl *ctl = NULL;
3003 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303004 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Haynes Mathew George380745d2017-10-04 15:27:45 -07003006 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003007 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3008 ret = -EINVAL;
3009 goto error_config;
3010 }
3011
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303012 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
3013 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
3014 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303015
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303016 if (CARD_STATUS_OFFLINE == out->card_status ||
3017 CARD_STATUS_OFFLINE == adev->card_status) {
3018 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303019 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303020 goto error_config;
3021 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303022
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303023 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3024 if (!audio_extn_a2dp_is_ready()) {
3025 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303026 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303027 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303028 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3029 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3030 ret = -EAGAIN;
3031 goto error_config;
3032 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303033 }
3034 }
3035 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303036 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3037 if (!adev->bt_sco_on) {
3038 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3039 //combo usecase just by pass a2dp
3040 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3041 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3042 } else {
3043 ALOGE("%s: SCO profile is not ready, return error", __func__);
3044 ret = -EAGAIN;
3045 goto error_config;
3046 }
3047 }
3048 }
3049
Eric Laurentb23d5282013-05-14 15:27:20 -07003050 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 if (out->pcm_device_id < 0) {
3052 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3053 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003054 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003055 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 }
3057
3058 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003059
3060 if (!uc_info) {
3061 ret = -ENOMEM;
3062 goto error_config;
3063 }
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 uc_info->id = out->usecase;
3066 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003067 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003068 uc_info->devices = out->devices;
3069 uc_info->in_snd_device = SND_DEVICE_NONE;
3070 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003071
3072 /* This must be called before adding this usecase to the list */
3073 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3074 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3075 /* USB backend is not reopened immediately.
3076 This is eventually done as part of select_devices */
3077 }
3078
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003079 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303081 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3082 adev->perf_lock_opts,
3083 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303084
3085 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303086 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303087 if (audio_extn_passthru_is_enabled() &&
3088 audio_extn_passthru_is_passthrough_stream(out)) {
3089 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303090 }
3091 }
3092
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303093 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3094 (!audio_extn_a2dp_is_ready())) {
3095 if (!a2dp_combo) {
3096 check_a2dp_restore_l(adev, out, false);
3097 } else {
3098 audio_devices_t dev = out->devices;
3099 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3100 select_devices(adev, out->usecase);
3101 out->devices = dev;
3102 }
3103 } else {
3104 select_devices(adev, out->usecase);
3105 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003106
Arun Mirpurief53ce52018-09-11 18:00:09 -07003107 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3108 voice_set_device_mute_flag(adev, true);
3109
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003110 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3111 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003112
3113 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3114 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3115 ALOGE("%s: pcm stream not ready", __func__);
3116 goto error_open;
3117 }
3118 ret = pcm_start(out->pcm);
3119 if (ret < 0) {
3120 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3121 goto error_open;
3122 }
3123 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003124 unsigned int flags = PCM_OUT;
3125 unsigned int pcm_open_retry_count = 0;
3126 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3127 flags |= PCM_MMAP | PCM_NOIRQ;
3128 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003129 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003130 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003131 } else
3132 flags |= PCM_MONOTONIC;
3133
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003134 if ((adev->vr_audio_mode_enabled) &&
3135 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3136 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3137 "PCM_Dev %d Topology", out->pcm_device_id);
3138 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3139 if (!ctl) {
3140 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3141 __func__, mixer_ctl_name);
3142 } else {
3143 //if success use ULLPP
3144 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3145 __func__, mixer_ctl_name, out->pcm_device_id);
3146 //There is a still a possibility that some sessions
3147 // that request for FAST|RAW when 3D audio is active
3148 //can go through ULLPP. Ideally we expects apps to
3149 //listen to audio focus and stop concurrent playback
3150 //Also, we will look for mode flag (voice_in_communication)
3151 //before enabling the realtime flag.
3152 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3153 }
3154 }
3155
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003156 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003157 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003158 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3159 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003160 ATRACE_END();
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003161 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3162 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3163 if (out->pcm != NULL) {
3164 pcm_close(out->pcm);
3165 out->pcm = NULL;
3166 }
3167 if (pcm_open_retry_count-- == 0) {
3168 ret = -EIO;
3169 goto error_open;
3170 }
3171 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3172 continue;
3173 }
3174 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003175 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003176
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003177 ALOGV("%s: pcm_prepare", __func__);
3178 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003179 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003180 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003181 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003182 if (ret < 0) {
3183 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3184 pcm_close(out->pcm);
3185 out->pcm = NULL;
3186 goto error_open;
3187 }
3188 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303189 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303190 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003191 // apply volume for voip playback after path is set up
3192 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3193 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003194 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003195 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303196 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003197 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3198 adev->dsp_bit_width_enforce_mode,
3199 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003201 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003202 out->compr = compress_open(adev->snd_card,
3203 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003204 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003205 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003206 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003207 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003208 compress_close(out->compr);
3209 out->compr = NULL;
3210 ret = -EIO;
3211 goto error_open;
3212 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303213 /* compress_open sends params of the track, so reset the flag here */
3214 out->is_compr_metadata_avail = false;
3215
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003216 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003218
Fred Oh3f43e742015-03-04 18:42:34 -08003219 /* Since small bufs uses blocking writes, a write will be blocked
3220 for the default max poll time (20s) in the event of an SSR.
3221 Reduce the poll time to observe and deal with SSR faster.
3222 */
Ashish Jain5106d362016-05-11 19:23:33 +05303223 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003224 compress_set_max_poll_wait(out->compr, 1000);
3225 }
3226
Manish Dewangan69426c82017-01-30 17:35:36 +05303227 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303228 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303229
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003230 audio_extn_dts_create_state_notifier_node(out->usecase);
3231 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3232 popcount(out->channel_mask),
3233 out->playback_started);
3234
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003235#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303236 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003237 audio_extn_dolby_send_ddp_endp_params(adev);
3238#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303239 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3240 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003241 if (adev->visualizer_start_output != NULL)
3242 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3243 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303244 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003245 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003248
3249 if (ret == 0) {
3250 register_out_stream(out);
3251 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003252 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3253 ALOGE("%s: pcm stream not ready", __func__);
3254 goto error_open;
3255 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003256 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003257 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003258 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003259 if (ret < 0)
3260 goto error_open;
3261 }
3262 }
3263
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303264 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003265 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003266
Manish Dewangan21a850a2017-08-14 12:03:55 +05303267 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003268 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003269 if (ret < 0)
3270 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3271 }
3272
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003273 // consider a scenario where on pause lower layers are tear down.
3274 // so on resume, swap mixer control need to be sent only when
3275 // backend is active, hence rather than sending from enable device
3276 // sending it from start of streamtream
3277
3278 platform_set_swap_channels(adev, true);
3279
Haynes Mathew George380745d2017-10-04 15:27:45 -07003280 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003281 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303283 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003285error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303286 /*
3287 * sleep 50ms to allow sufficient time for kernel
3288 * drivers to recover incases like SSR.
3289 */
3290 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003291 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003292 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293}
3294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295static int check_input_parameters(uint32_t sample_rate,
3296 audio_format_t format,
3297 int channel_count)
3298{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003299 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303301 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3302 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3303 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003304 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003305 !audio_extn_compr_cap_format_supported(format))
3306 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003307
3308 switch (channel_count) {
3309 case 1:
3310 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303311 case 3:
3312 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003313 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003314 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003315 break;
3316 default:
3317 ret = -EINVAL;
3318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319
3320 switch (sample_rate) {
3321 case 8000:
3322 case 11025:
3323 case 12000:
3324 case 16000:
3325 case 22050:
3326 case 24000:
3327 case 32000:
3328 case 44100:
3329 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003330 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303331 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003332 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303333 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334 break;
3335 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003336 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 }
3338
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340}
3341
Naresh Tanniru04f71882018-06-26 17:46:22 +05303342
3343/** Add a value in a list if not already present.
3344 * @return true if value was successfully inserted or already present,
3345 * false if the list is full and does not contain the value.
3346 */
3347static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3348 for (size_t i = 0; i < list_length; i++) {
3349 if (list[i] == value) return true; // value is already present
3350 if (list[i] == 0) { // no values in this slot
3351 list[i] = value;
3352 return true; // value inserted
3353 }
3354 }
3355 return false; // could not insert value
3356}
3357
3358/** Add channel_mask in supported_channel_masks if not already present.
3359 * @return true if channel_mask was successfully inserted or already present,
3360 * false if supported_channel_masks is full and does not contain channel_mask.
3361 */
3362static void register_channel_mask(audio_channel_mask_t channel_mask,
3363 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3364 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3365 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3366}
3367
3368/** Add format in supported_formats if not already present.
3369 * @return true if format was successfully inserted or already present,
3370 * false if supported_formats is full and does not contain format.
3371 */
3372static void register_format(audio_format_t format,
3373 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3374 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3375 "%s: stream can not declare supporting its format %x", __func__, format);
3376}
3377/** Add sample_rate in supported_sample_rates if not already present.
3378 * @return true if sample_rate was successfully inserted or already present,
3379 * false if supported_sample_rates is full and does not contain sample_rate.
3380 */
3381static void register_sample_rate(uint32_t sample_rate,
3382 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3383 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3384 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3385}
3386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387static size_t get_input_buffer_size(uint32_t sample_rate,
3388 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003389 int channel_count,
3390 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
3392 size_t size = 0;
3393
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003394 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3395 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003397 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003398 if (is_low_latency)
3399 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303400
3401 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003403 /* make sure the size is multiple of 32 bytes
3404 * At 48 kHz mono 16-bit PCM:
3405 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3406 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3407 */
3408 size += 0x1f;
3409 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003410
3411 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412}
3413
Ashish Jain058165c2016-09-28 23:18:48 +05303414static size_t get_output_period_size(uint32_t sample_rate,
3415 audio_format_t format,
3416 int channel_count,
3417 int duration /*in millisecs*/)
3418{
3419 size_t size = 0;
3420 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3421
3422 if ((duration == 0) || (sample_rate == 0) ||
3423 (bytes_per_sample == 0) || (channel_count == 0)) {
3424 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3425 bytes_per_sample, channel_count);
3426 return -EINVAL;
3427 }
3428
3429 size = (sample_rate *
3430 duration *
3431 bytes_per_sample *
3432 channel_count) / 1000;
3433 /*
3434 * To have same PCM samples for all channels, the buffer size requires to
3435 * be multiple of (number of channels * bytes per sample)
3436 * For writes to succeed, the buffer must be written at address which is multiple of 32
3437 */
3438 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3439
3440 return (size/(channel_count * bytes_per_sample));
3441}
3442
Zhou Song48453a02018-01-10 17:50:59 +08003443static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303444{
3445 uint64_t actual_frames_rendered = 0;
3446 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3447
3448 /* This adjustment accounts for buffering after app processor.
3449 * It is based on estimated DSP latency per use case, rather than exact.
3450 */
3451 int64_t platform_latency = platform_render_latency(out->usecase) *
3452 out->sample_rate / 1000000LL;
3453
Zhou Song48453a02018-01-10 17:50:59 +08003454 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303455 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3456 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3457 * hence only estimate.
3458 */
3459 int64_t signed_frames = out->written - kernel_buffer_size;
3460
3461 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3462
Zhou Song48453a02018-01-10 17:50:59 +08003463 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303464 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003465 if (timestamp != NULL )
3466 *timestamp = out->writeAt;
3467 } else if (timestamp != NULL) {
3468 clock_gettime(CLOCK_MONOTONIC, timestamp);
3469 }
3470 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303471
3472 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3473 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3474 (long long int)out->written, (int)kernel_buffer_size,
3475 audio_bytes_per_sample(out->compr_config.codec->format),
3476 popcount(out->channel_mask));
3477
3478 return actual_frames_rendered;
3479}
3480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3482{
3483 struct stream_out *out = (struct stream_out *)stream;
3484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486}
3487
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003488static int out_set_sample_rate(struct audio_stream *stream __unused,
3489 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490{
3491 return -ENOSYS;
3492}
3493
3494static size_t out_get_buffer_size(const struct audio_stream *stream)
3495{
3496 struct stream_out *out = (struct stream_out *)stream;
3497
Varun Balaraje49253e2017-07-06 19:48:56 +05303498 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303499 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303500 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303501 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3502 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3503 else
3504 return out->compr_config.fragment_size;
3505 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003506 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003507 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3508 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 +05303509 else if (is_offload_usecase(out->usecase) &&
3510 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303511 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003513 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003514 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515}
3516
3517static uint32_t out_get_channels(const struct audio_stream *stream)
3518{
3519 struct stream_out *out = (struct stream_out *)stream;
3520
3521 return out->channel_mask;
3522}
3523
3524static audio_format_t out_get_format(const struct audio_stream *stream)
3525{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526 struct stream_out *out = (struct stream_out *)stream;
3527
3528 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529}
3530
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003531static int out_set_format(struct audio_stream *stream __unused,
3532 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533{
3534 return -ENOSYS;
3535}
3536
3537static int out_standby(struct audio_stream *stream)
3538{
3539 struct stream_out *out = (struct stream_out *)stream;
3540 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003541 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303543 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3544 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003546 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003548 if (adev->adm_deregister_stream)
3549 adev->adm_deregister_stream(adev->adm_data, out->handle);
3550
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003551 if (is_offload_usecase(out->usecase))
3552 stop_compressed_output_l(out);
3553
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003554 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003556 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3557 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303558 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003559 pthread_mutex_unlock(&adev->lock);
3560 pthread_mutex_unlock(&out->lock);
3561 ALOGD("VOIP output entered standby");
3562 return 0;
3563 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003564 if (out->pcm) {
3565 pcm_close(out->pcm);
3566 out->pcm = NULL;
3567 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003568 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3569 do_stop = out->playback_started;
3570 out->playback_started = false;
3571 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003572 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003573 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303574 out->send_next_track_params = false;
3575 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003576 out->gapless_mdata.encoder_delay = 0;
3577 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 if (out->compr != NULL) {
3579 compress_close(out->compr);
3580 out->compr = NULL;
3581 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003582 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003583 if (do_stop) {
3584 stop_output_stream(out);
3585 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003586 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 }
3588 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303589 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 return 0;
3591}
3592
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303593static int out_on_error(struct audio_stream *stream)
3594{
3595 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003596 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303597
3598 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003599 // always send CMD_ERROR for offload streams, this
3600 // is needed e.g. when SSR happens within compress_open
3601 // since the stream is active, offload_callback_thread is also active.
3602 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3603 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003604 }
3605 pthread_mutex_unlock(&out->lock);
3606
3607 status = out_standby(&out->stream.common);
3608
3609 lock_output_stream(out);
3610 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003611 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303612 }
3613 pthread_mutex_unlock(&out->lock);
3614
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003615 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303616}
3617
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303618/*
3619 *standby implementation without locks, assumes that the callee already
3620 *has taken adev and out lock.
3621 */
3622int out_standby_l(struct audio_stream *stream)
3623{
3624 struct stream_out *out = (struct stream_out *)stream;
3625 struct audio_device *adev = out->dev;
3626
3627 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3628 stream, out->usecase, use_case_table[out->usecase]);
3629
3630 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003631 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303632 if (adev->adm_deregister_stream)
3633 adev->adm_deregister_stream(adev->adm_data, out->handle);
3634
3635 if (is_offload_usecase(out->usecase))
3636 stop_compressed_output_l(out);
3637
3638 out->standby = true;
3639 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3640 voice_extn_compress_voip_close_output_stream(stream);
3641 out->started = 0;
3642 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003643 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303644 return 0;
3645 } else if (!is_offload_usecase(out->usecase)) {
3646 if (out->pcm) {
3647 pcm_close(out->pcm);
3648 out->pcm = NULL;
3649 }
3650 } else {
3651 ALOGD("copl(%p):standby", out);
3652 out->send_next_track_params = false;
3653 out->is_compr_metadata_avail = false;
3654 out->gapless_mdata.encoder_delay = 0;
3655 out->gapless_mdata.encoder_padding = 0;
3656 if (out->compr != NULL) {
3657 compress_close(out->compr);
3658 out->compr = NULL;
3659 }
3660 }
3661 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003662 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303663 }
3664 ALOGD("%s: exit", __func__);
3665 return 0;
3666}
3667
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003668static int out_dump(const struct audio_stream *stream __unused,
3669 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670{
3671 return 0;
3672}
3673
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003674static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3675{
3676 int ret = 0;
3677 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003678
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003679 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003680 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003681 return -EINVAL;
3682 }
3683
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303684 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003685
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003686 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3687 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303688 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003689 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003690 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3691 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303692 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003693 }
3694
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003695 ALOGV("%s new encoder delay %u and padding %u", __func__,
3696 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3697
3698 return 0;
3699}
3700
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003701static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3702{
3703 return out == adev->primary_output || out == adev->voice_tx_output;
3704}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003705
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303706// note: this call is safe only if the stream_cb is
3707// removed first in close_output_stream (as is done now).
3708static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3709{
3710 if (!stream || !parms)
3711 return;
3712
3713 struct stream_out *out = (struct stream_out *)stream;
3714 struct audio_device *adev = out->dev;
3715
3716 card_status_t status;
3717 int card;
3718 if (parse_snd_card_status(parms, &card, &status) < 0)
3719 return;
3720
3721 pthread_mutex_lock(&adev->lock);
3722 bool valid_cb = (card == adev->snd_card);
3723 pthread_mutex_unlock(&adev->lock);
3724
3725 if (!valid_cb)
3726 return;
3727
3728 lock_output_stream(out);
3729 if (out->card_status != status)
3730 out->card_status = status;
3731 pthread_mutex_unlock(&out->lock);
3732
3733 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3734 use_case_table[out->usecase],
3735 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3736
3737 if (status == CARD_STATUS_OFFLINE)
3738 out_on_error(stream);
3739
3740 return;
3741}
3742
Kevin Rocardfce19002017-08-07 19:21:36 -07003743static int get_alive_usb_card(struct str_parms* parms) {
3744 int card;
3745 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3746 !audio_extn_usb_alive(card)) {
3747 return card;
3748 }
3749 return -ENODEV;
3750}
3751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3753{
3754 struct stream_out *out = (struct stream_out *)stream;
3755 struct audio_device *adev = out->dev;
3756 struct str_parms *parms;
3757 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003758 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303759 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003760 bool reconfig = false;
3761 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762
sangwoobc677242013-08-08 16:53:43 +09003763 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003764 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303766 if (!parms)
3767 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003768 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3769 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003771 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003774 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003775 * When HDMI cable is unplugged the music playback is paused and
3776 * the policy manager sends routing=0. But the audioflinger continues
3777 * to write data until standby time (3sec). As the HDMI core is
3778 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003779 * Avoid this by routing audio to speaker until standby.
3780 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003781 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3782 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303783 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003784 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3785 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003786 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303787 /*
3788 * When A2DP is disconnected the
3789 * music playback is paused and the policy manager sends routing=0
3790 * But the audioflingercontinues to write data until standby time
3791 * (3sec). As BT is turned off, the write gets blocked.
3792 * Avoid this by routing audio to speaker until standby.
3793 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003794 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003795 (val == AUDIO_DEVICE_NONE) &&
3796 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303797 val = AUDIO_DEVICE_OUT_SPEAKER;
3798 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303799 /*
3800 * When USB headset is disconnected the music platback paused
3801 * and the policy manager send routing=0. But if the USB is connected
3802 * back before the standby time, AFE is not closed and opened
3803 * when USB is connected back. So routing to speker will guarantee
3804 * AFE reconfiguration and AFE will be opend once USB is connected again
3805 */
3806 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3807 (val == AUDIO_DEVICE_NONE) &&
3808 !audio_extn_usb_connected(parms)) {
3809 val = AUDIO_DEVICE_OUT_SPEAKER;
3810 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303811 /* To avoid a2dp to sco overlapping / BT device improper state
3812 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303813 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303814 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3815 if (!audio_extn_a2dp_is_ready()) {
3816 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3817 //combo usecase just by pass a2dp
3818 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303819 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303820 } else {
3821 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3822 /* update device to a2dp and don't route as BT returned error
3823 * However it is still possible a2dp routing called because
3824 * of current active device disconnection (like wired headset)
3825 */
3826 out->devices = val;
3827 pthread_mutex_unlock(&out->lock);
3828 pthread_mutex_unlock(&adev->lock);
3829 goto error;
3830 }
3831 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303832 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003833
3834 audio_devices_t new_dev = val;
3835
3836 // Workaround: If routing to an non existing usb device, fail gracefully
3837 // The routing request will otherwise block during 10 second
3838 int card;
3839 if (audio_is_usb_out_device(new_dev) &&
3840 (card = get_alive_usb_card(parms)) >= 0) {
3841
3842 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3843 pthread_mutex_unlock(&adev->lock);
3844 pthread_mutex_unlock(&out->lock);
3845 ret = -ENOSYS;
3846 goto routing_fail;
3847 }
3848
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003849 /*
3850 * select_devices() call below switches all the usecases on the same
3851 * backend to the new device. Refer to check_usecases_codec_backend() in
3852 * the select_devices(). But how do we undo this?
3853 *
3854 * For example, music playback is active on headset (deep-buffer usecase)
3855 * and if we go to ringtones and select a ringtone, low-latency usecase
3856 * will be started on headset+speaker. As we can't enable headset+speaker
3857 * and headset devices at the same time, select_devices() switches the music
3858 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3859 * So when the ringtone playback is completed, how do we undo the same?
3860 *
3861 * We are relying on the out_set_parameters() call on deep-buffer output,
3862 * once the ringtone playback is ended.
3863 * NOTE: We should not check if the current devices are same as new devices.
3864 * Because select_devices() must be called to switch back the music
3865 * playback to headset.
3866 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003867 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003868 audio_devices_t new_dev = val;
3869 bool same_dev = out->devices == new_dev;
3870 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003871
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003872 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003873 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003874 if (adev->mode == AUDIO_MODE_IN_CALL) {
3875 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003876 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3877 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3878 audio_extn_usb_set_service_interval(true /*playback*/,
3879 service_interval,
3880 &reconfig);
3881 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3882 }
3883 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003884 }
3885 } else {
3886 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003887 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003888 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003889 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003890
3891 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003892 if (!same_dev) {
3893 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303894 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3895 adev->perf_lock_opts,
3896 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003897 if (adev->adm_on_routing_change)
3898 adev->adm_on_routing_change(adev->adm_data,
3899 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003900 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303901 if (!bypass_a2dp) {
3902 select_devices(adev, out->usecase);
3903 } else {
3904 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3905 select_devices(adev, out->usecase);
3906 out->devices = new_dev;
3907 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003908
3909 if (!same_dev) {
3910 // on device switch force swap, lower functions will make sure
3911 // to check if swap is allowed or not.
3912 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303913 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003914 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303915 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3916 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003917 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303918 pthread_mutex_lock(&out->compr_mute_lock);
3919 out->a2dp_compress_mute = false;
3920 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3921 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003922 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3923 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303924 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003925 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003926 }
3927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003929 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003931 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003932
3933 if (out == adev->primary_output) {
3934 pthread_mutex_lock(&adev->lock);
3935 audio_extn_set_parameters(adev, parms);
3936 pthread_mutex_unlock(&adev->lock);
3937 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003938 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003939 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003940 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003941
3942 audio_extn_dts_create_state_notifier_node(out->usecase);
3943 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3944 popcount(out->channel_mask),
3945 out->playback_started);
3946
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003947 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003948 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003949
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303950 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3951 if (err >= 0) {
3952 strlcpy(out->profile, value, sizeof(out->profile));
3953 ALOGV("updating stream profile with value '%s'", out->profile);
3954 lock_output_stream(out);
3955 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3956 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003957 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303958 out->sample_rate, out->bit_width,
3959 out->channel_mask, out->profile,
3960 &out->app_type_cfg);
3961 pthread_mutex_unlock(&out->lock);
3962 }
3963
Alexy Joseph98988832017-01-13 14:56:59 -08003964 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003965 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3966 // and vendor.audio.hal.output.suspend.supported is set to true
3967 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003968 //check suspend parameter only for low latency and if the property
3969 //is enabled
3970 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3971 ALOGI("%s: got suspend_playback %s", __func__, value);
3972 lock_output_stream(out);
3973 if (!strncmp(value, "false", 5)) {
3974 //suspend_playback=false is supposed to set QOS value back to 75%
3975 //the mixer control sent with value Enable will achieve that
3976 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3977 } else if (!strncmp (value, "true", 4)) {
3978 //suspend_playback=true is supposed to remove QOS value
3979 //resetting the mixer control will set the default value
3980 //for the mixer control which is Disable and this removes the QOS vote
3981 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3982 } else {
3983 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3984 " got %s", __func__, value);
3985 ret = -1;
3986 }
3987
3988 if (ret != 0) {
3989 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3990 __func__, out->pm_qos_mixer_path, ret);
3991 }
3992
3993 pthread_mutex_unlock(&out->lock);
3994 }
3995 }
3996 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303998error:
Eric Laurent994a6932013-07-17 11:51:42 -07003999 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000 return ret;
4001}
4002
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004003static bool stream_get_parameter_channels(struct str_parms *query,
4004 struct str_parms *reply,
4005 audio_channel_mask_t *supported_channel_masks) {
4006 int ret = -1;
4007 char value[512];
4008 bool first = true;
4009 size_t i, j;
4010
4011 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4012 ret = 0;
4013 value[0] = '\0';
4014 i = 0;
4015 while (supported_channel_masks[i] != 0) {
4016 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4017 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4018 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304019 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004020
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304021 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004022 first = false;
4023 break;
4024 }
4025 }
4026 i++;
4027 }
4028 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4029 }
4030 return ret == 0;
4031}
4032
4033static bool stream_get_parameter_formats(struct str_parms *query,
4034 struct str_parms *reply,
4035 audio_format_t *supported_formats) {
4036 int ret = -1;
4037 char value[256];
4038 size_t i, j;
4039 bool first = true;
4040
4041 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4042 ret = 0;
4043 value[0] = '\0';
4044 i = 0;
4045 while (supported_formats[i] != 0) {
4046 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4047 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4048 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304049 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004050 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304051 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004052 first = false;
4053 break;
4054 }
4055 }
4056 i++;
4057 }
4058 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4059 }
4060 return ret == 0;
4061}
4062
4063static bool stream_get_parameter_rates(struct str_parms *query,
4064 struct str_parms *reply,
4065 uint32_t *supported_sample_rates) {
4066
4067 int i;
4068 char value[256];
4069 int ret = -1;
4070 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4071 ret = 0;
4072 value[0] = '\0';
4073 i=0;
4074 int cursor = 0;
4075 while (supported_sample_rates[i]) {
4076 int avail = sizeof(value) - cursor;
4077 ret = snprintf(value + cursor, avail, "%s%d",
4078 cursor > 0 ? "|" : "",
4079 supported_sample_rates[i]);
4080 if (ret < 0 || ret >= avail) {
4081 // if cursor is at the last element of the array
4082 // overwrite with \0 is duplicate work as
4083 // snprintf already put a \0 in place.
4084 // else
4085 // we had space to write the '|' at value[cursor]
4086 // (which will be overwritten) or no space to fill
4087 // the first element (=> cursor == 0)
4088 value[cursor] = '\0';
4089 break;
4090 }
4091 cursor += ret;
4092 ++i;
4093 }
4094 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4095 value);
4096 }
4097 return ret >= 0;
4098}
4099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4101{
4102 struct stream_out *out = (struct stream_out *)stream;
4103 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004104 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 char value[256];
4106 struct str_parms *reply = str_parms_create();
4107 size_t i, j;
4108 int ret;
4109 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004110
4111 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004112 if (reply) {
4113 str_parms_destroy(reply);
4114 }
4115 if (query) {
4116 str_parms_destroy(query);
4117 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004118 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4119 return NULL;
4120 }
4121
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004122 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4124 if (ret >= 0) {
4125 value[0] = '\0';
4126 i = 0;
4127 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004128 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4129 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004131 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004133 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 first = false;
4135 break;
4136 }
4137 }
4138 i++;
4139 }
4140 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4141 str = str_parms_to_str(reply);
4142 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004143 voice_extn_out_get_parameters(out, query, reply);
4144 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004146
Alexy Joseph62142aa2015-11-16 15:10:34 -08004147
4148 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4149 if (ret >= 0) {
4150 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304151 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4152 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004153 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304154 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004155 } else {
4156 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304157 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004158 }
4159 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004160 if (str)
4161 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004162 str = str_parms_to_str(reply);
4163 }
4164
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004165 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4166 if (ret >= 0) {
4167 value[0] = '\0';
4168 i = 0;
4169 first = true;
4170 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004171 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4172 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004173 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004174 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004175 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004176 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004177 first = false;
4178 break;
4179 }
4180 }
4181 i++;
4182 }
4183 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004184 if (str)
4185 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004186 str = str_parms_to_str(reply);
4187 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004188
4189 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4190 if (ret >= 0) {
4191 value[0] = '\0';
4192 i = 0;
4193 first = true;
4194 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004195 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4196 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004197 if (!first) {
4198 strlcat(value, "|", sizeof(value));
4199 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004200 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004201 first = false;
4202 break;
4203 }
4204 }
4205 i++;
4206 }
4207 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4208 if (str)
4209 free(str);
4210 str = str_parms_to_str(reply);
4211 }
4212
Alexy Joseph98988832017-01-13 14:56:59 -08004213 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4214 //only low latency track supports suspend_resume
4215 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004216 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004217 if (str)
4218 free(str);
4219 str = str_parms_to_str(reply);
4220 }
4221
4222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 str_parms_destroy(query);
4224 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004225 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 return str;
4227}
4228
4229static uint32_t out_get_latency(const struct audio_stream_out *stream)
4230{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004231 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004233 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234
Alexy Josephaa54c872014-12-03 02:46:47 -08004235 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304236 lock_output_stream(out);
4237 latency = audio_extn_utils_compress_get_dsp_latency(out);
4238 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004239 } else if ((out->realtime) ||
4240 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004241 // since the buffer won't be filled up faster than realtime,
4242 // return a smaller number
4243 if (out->config.rate)
4244 period_ms = (out->af_period_multiplier * out->config.period_size *
4245 1000) / (out->config.rate);
4246 else
4247 period_ms = 0;
4248 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004249 } else {
4250 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004251 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004252 }
4253
yidongh0515e042017-07-06 15:00:34 +08004254 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004255 latency += audio_extn_a2dp_get_encoder_latency();
4256
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304257 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004258 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259}
4260
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304261static float AmpToDb(float amplification)
4262{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304263 float db = DSD_VOLUME_MIN_DB;
4264 if (amplification > 0) {
4265 db = 20 * log10(amplification);
4266 if(db < DSD_VOLUME_MIN_DB)
4267 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304268 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304269 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304270}
4271
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304272static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4273 float right)
4274{
4275 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304276 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304277 char mixer_ctl_name[128];
4278 struct audio_device *adev = out->dev;
4279 struct mixer_ctl *ctl;
4280 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4281 PCM_PLAYBACK);
4282
4283 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4284 "Compress Playback %d Volume", pcm_device_id);
4285 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4286 if (!ctl) {
4287 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4288 __func__, mixer_ctl_name);
4289 return -EINVAL;
4290 }
4291 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4292 __func__, mixer_ctl_name, left, right);
4293 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4294 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4295 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4296
4297 return 0;
4298}
4299
Zhou Song2b8f28f2017-09-11 10:51:38 +08004300static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4301 float right)
4302{
4303 struct stream_out *out = (struct stream_out *)stream;
4304 char mixer_ctl_name[] = "App Type Gain";
4305 struct audio_device *adev = out->dev;
4306 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304307 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004308
4309 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4310 if (!ctl) {
4311 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4312 __func__, mixer_ctl_name);
4313 return -EINVAL;
4314 }
4315
4316 set_values[0] = 0; //0: Rx Session 1:Tx Session
4317 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304318 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4319 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004320
4321 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4322 return 0;
4323}
4324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325static int out_set_volume(struct audio_stream_out *stream, float left,
4326 float right)
4327{
Eric Laurenta9024de2013-04-04 09:19:12 -07004328 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004329 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304330 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004331
Eric Laurenta9024de2013-04-04 09:19:12 -07004332 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4333 /* only take left channel into account: the API is for stereo anyway */
4334 out->muted = (left == 0.0f);
4335 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004336 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304337 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004338 /*
4339 * Set mute or umute on HDMI passthrough stream.
4340 * Only take left channel into account.
4341 * Mute is 0 and unmute 1
4342 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304343 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304344 } else if (out->format == AUDIO_FORMAT_DSD){
4345 char mixer_ctl_name[128] = "DSD Volume";
4346 struct audio_device *adev = out->dev;
4347 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4348
4349 if (!ctl) {
4350 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4351 __func__, mixer_ctl_name);
4352 return -EINVAL;
4353 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304354 volume[0] = (long)(AmpToDb(left));
4355 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304356 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4357 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004358 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304359 pthread_mutex_lock(&out->compr_mute_lock);
4360 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4361 if (!out->a2dp_compress_mute)
4362 ret = out_set_compr_volume(stream, left, right);
4363 out->volume_l = left;
4364 out->volume_r = right;
4365 pthread_mutex_unlock(&out->compr_mute_lock);
4366 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004367 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004368 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004369 if (!out->standby)
4370 ret = out_set_voip_volume(stream, left, right);
4371 out->volume_l = left;
4372 out->volume_r = right;
4373 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004374 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376 return -ENOSYS;
4377}
4378
Zhou Songc9672822017-08-16 16:01:39 +08004379static void update_frames_written(struct stream_out *out, size_t bytes)
4380{
4381 size_t bpf = 0;
4382
4383 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4384 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4385 bpf = 1;
4386 else if (!is_offload_usecase(out->usecase))
4387 bpf = audio_bytes_per_sample(out->format) *
4388 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004389
4390 pthread_mutex_lock(&out->position_query_lock);
4391 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004392 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004393 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4394 }
4395 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004396}
4397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4399 size_t bytes)
4400{
4401 struct stream_out *out = (struct stream_out *)stream;
4402 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004403 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304404 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004405 const size_t frame_size = audio_stream_out_frame_size(stream);
4406 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004407
Haynes Mathew George380745d2017-10-04 15:27:45 -07004408 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004409 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304410
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304411 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004412
Dhananjay Kumarac341582017-02-23 23:42:25 +05304413 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304414 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304415 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4416 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004417 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304418 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304419 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304420 ALOGD(" %s: sound card is not active/SSR state", __func__);
4421 ret= -EIO;
4422 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304423 }
4424 }
4425
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304426 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304427 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304428 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304429 goto exit;
4430 }
4431
Haynes Mathew George16081042017-05-31 17:16:49 -07004432 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4433 ret = -EINVAL;
4434 goto exit;
4435 }
4436
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304437 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4438 !out->is_iec61937_info_available) {
4439
4440 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4441 out->is_iec61937_info_available = true;
4442 } else if (audio_extn_passthru_is_enabled()) {
4443 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304444 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304445
4446 if((out->format == AUDIO_FORMAT_DTS) ||
4447 (out->format == AUDIO_FORMAT_DTS_HD)) {
4448 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4449 buffer, bytes);
4450 if (ret) {
4451 if (ret != -ENOSYS) {
4452 out->is_iec61937_info_available = false;
4453 ALOGD("iec61937 transmission info not yet updated retry");
4454 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304455 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304456 /* if stream has started and after that there is
4457 * stream config change (iec transmission config)
4458 * then trigger select_device to update backend configuration.
4459 */
4460 out->stream_config_changed = true;
4461 pthread_mutex_lock(&adev->lock);
4462 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304463 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4464 ret = -EINVAL;
4465 goto exit;
4466 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304467 pthread_mutex_unlock(&adev->lock);
4468 out->stream_config_changed = false;
4469 out->is_iec61937_info_available = true;
4470 }
4471 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304472
Garmond Leung317cbf12017-09-13 16:20:50 -07004473 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304474 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4475 (out->is_iec61937_info_available == true)) {
4476 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4477 ret = -EINVAL;
4478 goto exit;
4479 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304480 }
4481 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304482
4483 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4484 (audio_extn_a2dp_is_suspended())) {
4485 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4486 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304487 ret = -EIO;
4488 goto exit;
4489 }
4490 }
4491 }
4492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004494 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004495 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004496 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4497 ret = voice_extn_compress_voip_start_output_stream(out);
4498 else
4499 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004500 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004501 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004503 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504 goto exit;
4505 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304506 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004507 if (last_known_cal_step != -1) {
4508 ALOGD("%s: retry previous failed cal level set", __func__);
4509 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304510 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004511 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304512
4513 if ((out->is_iec61937_info_available == true) &&
4514 (audio_extn_passthru_is_passthrough_stream(out))&&
4515 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4516 ret = -EINVAL;
4517 goto exit;
4518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520
Ashish Jain81eb2a82015-05-13 10:52:34 +05304521 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004522 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304523 adev->is_channel_status_set = true;
4524 }
4525
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004526 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004527 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004528 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004529 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004530 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4531 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304532 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4533 ALOGD("copl(%p):send next track params in gapless", out);
4534 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4535 out->send_next_track_params = false;
4536 out->is_compr_metadata_avail = false;
4537 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004538 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304539 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304540 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004541
Ashish Jain83a6cc22016-06-28 14:34:17 +05304542 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304543 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304544 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304545 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004546 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304547 return -EINVAL;
4548 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304549 audio_format_t dst_format = out->hal_op_format;
4550 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304551
4552 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4553 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4554
Ashish Jain83a6cc22016-06-28 14:34:17 +05304555 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304556 dst_format,
4557 buffer,
4558 src_format,
4559 frames);
4560
Ashish Jain83a6cc22016-06-28 14:34:17 +05304561 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304562 bytes_to_write);
4563
4564 /*Convert written bytes in audio flinger format*/
4565 if (ret > 0)
4566 ret = ((ret * format_to_bitwidth_table[out->format]) /
4567 format_to_bitwidth_table[dst_format]);
4568 }
4569 } else
4570 ret = compress_write(out->compr, buffer, bytes);
4571
Zhou Songc9672822017-08-16 16:01:39 +08004572 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4573 update_frames_written(out, bytes);
4574
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304575 if (ret < 0)
4576 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004577 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304578 /*msg to cb thread only if non blocking write is enabled*/
4579 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304580 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004581 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304582 } else if (-ENETRESET == ret) {
4583 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304584 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304585 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304586 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004587 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304588 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004589 }
Ashish Jain5106d362016-05-11 19:23:33 +05304590
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304591 /* Call compr start only when non-zero bytes of data is there to be rendered */
4592 if (!out->playback_started && ret > 0) {
4593 int status = compress_start(out->compr);
4594 if (status < 0) {
4595 ret = status;
4596 ALOGE("%s: compr start failed with err %d", __func__, errno);
4597 goto exit;
4598 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004599 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004600 out->playback_started = 1;
4601 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004602
4603 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4604 popcount(out->channel_mask),
4605 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004606 }
4607 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004608 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004609 return ret;
4610 } else {
4611 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004612 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004613 if (out->muted)
4614 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004615 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4616 __func__, frames, frame_size, bytes_to_write);
4617
4618 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4619 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4620 int16_t *src = (int16_t *)buffer;
4621 int16_t *dst = (int16_t *)buffer;
4622
4623 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4624 out->format != AUDIO_FORMAT_PCM_16_BIT,
4625 "out_write called for incall music use case with wrong properties");
4626
4627 /*
4628 * FIXME: this can be removed once audio flinger mixer supports
4629 * mono output
4630 */
4631
4632 /*
4633 * Code below goes over each frame in the buffer and adds both
4634 * L and R samples and then divides by 2 to convert to mono
4635 */
4636 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4637 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4638 }
4639 bytes_to_write /= 2;
4640 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004641
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304642 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004643
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004644 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004645
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004646 if (out->config.rate)
4647 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4648 out->config.rate;
4649
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004650 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004651 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4652
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004653 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004654 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004655 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304656 out->convert_buffer != NULL) {
4657
4658 memcpy_by_audio_format(out->convert_buffer,
4659 out->hal_op_format,
4660 buffer,
4661 out->hal_ip_format,
4662 out->config.period_size * out->config.channels);
4663
4664 ret = pcm_write(out->pcm, out->convert_buffer,
4665 (out->config.period_size *
4666 out->config.channels *
4667 format_to_bitwidth_table[out->hal_op_format]));
4668 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304669 /*
4670 * To avoid underrun in DSP when the application is not pumping
4671 * data at required rate, check for the no. of bytes and ignore
4672 * pcm_write if it is less than actual buffer size.
4673 * It is a work around to a change in compress VOIP driver.
4674 */
4675 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4676 bytes < (out->config.period_size * out->config.channels *
4677 audio_bytes_per_sample(out->format))) {
4678 size_t voip_buf_size =
4679 out->config.period_size * out->config.channels *
4680 audio_bytes_per_sample(out->format);
4681 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4682 __func__, bytes, voip_buf_size);
4683 usleep(((uint64_t)voip_buf_size - bytes) *
4684 1000000 / audio_stream_out_frame_size(stream) /
4685 out_get_sample_rate(&out->stream.common));
4686 ret = 0;
4687 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004688 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304689 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004690
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004691 release_out_focus(out);
4692
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304693 if (ret < 0)
4694 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004695 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304696 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698 }
4699
4700exit:
Zhou Songc9672822017-08-16 16:01:39 +08004701 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304702 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304703 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705 pthread_mutex_unlock(&out->lock);
4706
4707 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004708 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004709 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304710 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304711 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304712 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304713 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304714 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304715 out->standby = true;
4716 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304717 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304718 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4719 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4720 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004721
4722 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304723 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004724 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004725 return ret;
4726 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004727 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004728 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004729 return bytes;
4730}
4731
4732static int out_get_render_position(const struct audio_stream_out *stream,
4733 uint32_t *dsp_frames)
4734{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004735 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004736
4737 if (dsp_frames == NULL)
4738 return -EINVAL;
4739
4740 *dsp_frames = 0;
4741 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004742 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304743
4744 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4745 * this operation and adev_close_output_stream(where out gets reset).
4746 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304747 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004748 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304749 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004750 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304751 return 0;
4752 }
4753
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004754 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304755 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304756 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004757 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304758 if (ret < 0)
4759 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004760 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304761 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004762 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304763 if (-ENETRESET == ret) {
4764 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304765 out->card_status = CARD_STATUS_OFFLINE;
4766 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304767 } else if(ret < 0) {
4768 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304769 ret = -EINVAL;
4770 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304771 /*
4772 * Handle corner case where compress session is closed during SSR
4773 * and timestamp is queried
4774 */
4775 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304776 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304777 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304778 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004779 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304780 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304781 pthread_mutex_unlock(&out->lock);
4782 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004783 } else if (audio_is_linear_pcm(out->format)) {
4784 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004785 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004786 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004787 } else
4788 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789}
4790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004791static int out_add_audio_effect(const struct audio_stream *stream __unused,
4792 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793{
4794 return 0;
4795}
4796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004797static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4798 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799{
4800 return 0;
4801}
4802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004803static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4804 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304806 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807}
4808
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004809static int out_get_presentation_position(const struct audio_stream_out *stream,
4810 uint64_t *frames, struct timespec *timestamp)
4811{
4812 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304813 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004814 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004815
Ashish Jain5106d362016-05-11 19:23:33 +05304816 /* below piece of code is not guarded against any lock because audioFliner serializes
4817 * this operation and adev_close_output_stream( where out gets reset).
4818 */
4819 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304820 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004821 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304822 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4823 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4824 return 0;
4825 }
4826
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004827 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004828
Ashish Jain5106d362016-05-11 19:23:33 +05304829 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4830 ret = compress_get_tstamp(out->compr, &dsp_frames,
4831 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004832 // Adjustment accounts for A2dp encoder latency with offload usecases
4833 // Note: Encoder latency is returned in ms.
4834 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4835 unsigned long offset =
4836 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4837 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4838 }
Ashish Jain5106d362016-05-11 19:23:33 +05304839 ALOGVV("%s rendered frames %ld sample_rate %d",
4840 __func__, dsp_frames, out->sample_rate);
4841 *frames = dsp_frames;
4842 if (ret < 0)
4843 ret = -errno;
4844 if (-ENETRESET == ret) {
4845 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304846 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304847 ret = -EINVAL;
4848 } else
4849 ret = 0;
4850 /* this is the best we can do */
4851 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004852 } else {
4853 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004854 unsigned int avail;
4855 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4856 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4857 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4858 // This adjustment accounts for buffering after app processor.
4859 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004860 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004861 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004862
Weiyin Jiangd4633762018-03-16 12:05:03 +08004863 // Adjustment accounts for A2dp encoder latency with non offload usecases
4864 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4865 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4866 signed_frames -=
4867 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4868 }
4869
4870 // It would be unusual for this value to be negative, but check just in case ...
4871 if (signed_frames >= 0) {
4872 *frames = signed_frames;
4873 ret = 0;
4874 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004875 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304876 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304877 *frames = out->written;
4878 clock_gettime(CLOCK_MONOTONIC, timestamp);
4879 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004880 }
4881 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004882 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004883 return ret;
4884}
4885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004886static int out_set_callback(struct audio_stream_out *stream,
4887 stream_callback_t callback, void *cookie)
4888{
4889 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004890 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004891
4892 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004893 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004894 out->client_callback = callback;
4895 out->client_cookie = cookie;
4896 if (out->adsp_hdlr_stream_handle) {
4897 ret = audio_extn_adsp_hdlr_stream_set_callback(
4898 out->adsp_hdlr_stream_handle,
4899 callback,
4900 cookie);
4901 if (ret)
4902 ALOGW("%s:adsp hdlr callback registration failed %d",
4903 __func__, ret);
4904 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004905 pthread_mutex_unlock(&out->lock);
4906 return 0;
4907}
4908
4909static int out_pause(struct audio_stream_out* stream)
4910{
4911 struct stream_out *out = (struct stream_out *)stream;
4912 int status = -ENOSYS;
4913 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004914 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004915 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004916 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004917 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304918 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304919 status = compress_pause(out->compr);
4920
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004921 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004922
Mingming Yin21854652016-04-13 11:54:02 -07004923 if (audio_extn_passthru_is_active()) {
4924 ALOGV("offload use case, pause passthru");
4925 audio_extn_passthru_on_pause(out);
4926 }
4927
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304928 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004929 audio_extn_dts_notify_playback_state(out->usecase, 0,
4930 out->sample_rate, popcount(out->channel_mask),
4931 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004932 }
4933 pthread_mutex_unlock(&out->lock);
4934 }
4935 return status;
4936}
4937
4938static int out_resume(struct audio_stream_out* stream)
4939{
4940 struct stream_out *out = (struct stream_out *)stream;
4941 int status = -ENOSYS;
4942 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004943 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004944 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004945 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004946 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004947 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304948 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304949 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004950 }
4951 if (!status) {
4952 out->offload_state = OFFLOAD_STATE_PLAYING;
4953 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304954 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004955 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4956 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004957 }
4958 pthread_mutex_unlock(&out->lock);
4959 }
4960 return status;
4961}
4962
4963static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4964{
4965 struct stream_out *out = (struct stream_out *)stream;
4966 int status = -ENOSYS;
4967 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004968 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004969 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004970 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4971 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4972 else
4973 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4974 pthread_mutex_unlock(&out->lock);
4975 }
4976 return status;
4977}
4978
4979static int out_flush(struct audio_stream_out* stream)
4980{
4981 struct stream_out *out = (struct stream_out *)stream;
4982 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004983 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004984 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004985 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004986 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4987 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004988 } else {
4989 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4990 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004991 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004992 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004993 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004994 return 0;
4995 }
4996 return -ENOSYS;
4997}
4998
Haynes Mathew George16081042017-05-31 17:16:49 -07004999static int out_stop(const struct audio_stream_out* stream)
5000{
5001 struct stream_out *out = (struct stream_out *)stream;
5002 struct audio_device *adev = out->dev;
5003 int ret = -ENOSYS;
5004
5005 ALOGV("%s", __func__);
5006 pthread_mutex_lock(&adev->lock);
5007 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5008 out->playback_started && out->pcm != NULL) {
5009 pcm_stop(out->pcm);
5010 ret = stop_output_stream(out);
5011 out->playback_started = false;
5012 }
5013 pthread_mutex_unlock(&adev->lock);
5014 return ret;
5015}
5016
5017static int out_start(const struct audio_stream_out* stream)
5018{
5019 struct stream_out *out = (struct stream_out *)stream;
5020 struct audio_device *adev = out->dev;
5021 int ret = -ENOSYS;
5022
5023 ALOGV("%s", __func__);
5024 pthread_mutex_lock(&adev->lock);
5025 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5026 !out->playback_started && out->pcm != NULL) {
5027 ret = start_output_stream(out);
5028 if (ret == 0) {
5029 out->playback_started = true;
5030 }
5031 }
5032 pthread_mutex_unlock(&adev->lock);
5033 return ret;
5034}
5035
5036/*
5037 * Modify config->period_count based on min_size_frames
5038 */
5039static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5040{
5041 int periodCountRequested = (min_size_frames + config->period_size - 1)
5042 / config->period_size;
5043 int periodCount = MMAP_PERIOD_COUNT_MIN;
5044
5045 ALOGV("%s original config.period_size = %d config.period_count = %d",
5046 __func__, config->period_size, config->period_count);
5047
5048 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5049 periodCount *= 2;
5050 }
5051 config->period_count = periodCount;
5052
5053 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5054}
5055
5056static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5057 int32_t min_size_frames,
5058 struct audio_mmap_buffer_info *info)
5059{
5060 struct stream_out *out = (struct stream_out *)stream;
5061 struct audio_device *adev = out->dev;
5062 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005063 unsigned int offset1 = 0;
5064 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005065 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005066 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005067
5068 ALOGV("%s", __func__);
5069 pthread_mutex_lock(&adev->lock);
5070
5071 if (info == NULL || min_size_frames == 0) {
5072 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5073 ret = -EINVAL;
5074 goto exit;
5075 }
5076 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5077 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5078 ret = -ENOSYS;
5079 goto exit;
5080 }
5081 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5082 if (out->pcm_device_id < 0) {
5083 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5084 __func__, out->pcm_device_id, out->usecase);
5085 ret = -EINVAL;
5086 goto exit;
5087 }
5088
5089 adjust_mmap_period_count(&out->config, min_size_frames);
5090
5091 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5092 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5093 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5094 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
5095 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5096 step = "open";
5097 ret = -ENODEV;
5098 goto exit;
5099 }
5100 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5101 if (ret < 0) {
5102 step = "begin";
5103 goto exit;
5104 }
5105 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5106 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005107 ret = platform_get_mmap_data_fd(adev->platform,
5108 out->pcm_device_id, 0 /*playback*/,
5109 &info->shared_memory_fd,
5110 &mmap_size);
5111 if (ret < 0) {
5112 step = "get_mmap_fd";
5113 goto exit;
5114 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005115 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005116 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005117
5118 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5119 if (ret < 0) {
5120 step = "commit";
5121 goto exit;
5122 }
5123
5124 out->standby = false;
5125 ret = 0;
5126
5127 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5128 __func__, info->shared_memory_address, info->buffer_size_frames);
5129
5130exit:
5131 if (ret != 0) {
5132 if (out->pcm == NULL) {
5133 ALOGE("%s: %s - %d", __func__, step, ret);
5134 } else {
5135 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5136 pcm_close(out->pcm);
5137 out->pcm = NULL;
5138 }
5139 }
5140 pthread_mutex_unlock(&adev->lock);
5141 return ret;
5142}
5143
5144static int out_get_mmap_position(const struct audio_stream_out *stream,
5145 struct audio_mmap_position *position)
5146{
5147 struct stream_out *out = (struct stream_out *)stream;
5148 ALOGVV("%s", __func__);
5149 if (position == NULL) {
5150 return -EINVAL;
5151 }
5152 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005153 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005154 return -ENOSYS;
5155 }
5156 if (out->pcm == NULL) {
5157 return -ENOSYS;
5158 }
5159
5160 struct timespec ts = { 0, 0 };
5161 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5162 if (ret < 0) {
5163 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5164 return ret;
5165 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005166 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005167 return 0;
5168}
5169
5170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005171/** audio_stream_in implementation **/
5172static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5173{
5174 struct stream_in *in = (struct stream_in *)stream;
5175
5176 return in->config.rate;
5177}
5178
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005179static int in_set_sample_rate(struct audio_stream *stream __unused,
5180 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005181{
5182 return -ENOSYS;
5183}
5184
5185static size_t in_get_buffer_size(const struct audio_stream *stream)
5186{
5187 struct stream_in *in = (struct stream_in *)stream;
5188
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005189 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5190 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005191 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5192 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 -07005193 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5194 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305195 else if(audio_extn_cin_attached_usecase(in->usecase))
5196 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005197
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005198 return in->config.period_size * in->af_period_multiplier *
5199 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200}
5201
5202static uint32_t in_get_channels(const struct audio_stream *stream)
5203{
5204 struct stream_in *in = (struct stream_in *)stream;
5205
5206 return in->channel_mask;
5207}
5208
5209static audio_format_t in_get_format(const struct audio_stream *stream)
5210{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005211 struct stream_in *in = (struct stream_in *)stream;
5212
5213 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214}
5215
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005216static int in_set_format(struct audio_stream *stream __unused,
5217 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218{
5219 return -ENOSYS;
5220}
5221
5222static int in_standby(struct audio_stream *stream)
5223{
5224 struct stream_in *in = (struct stream_in *)stream;
5225 struct audio_device *adev = in->dev;
5226 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305227 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5228 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005229 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305230
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005231 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005232 if (!in->standby && in->is_st_session) {
5233 ALOGD("%s: sound trigger pcm stop lab", __func__);
5234 audio_extn_sound_trigger_stop_lab(in);
5235 in->standby = 1;
5236 }
5237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005238 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005239 if (adev->adm_deregister_stream)
5240 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5241
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005242 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005243 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005244 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005245 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005246 voice_extn_compress_voip_close_input_stream(stream);
5247 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005248 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5249 do_stop = in->capture_started;
5250 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005251 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305252 if (audio_extn_cin_attached_usecase(in->usecase))
5253 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005254 }
5255
5256 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005257 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005258 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005259 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005260 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005261 in->pcm = NULL;
5262 }
5263 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005264 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005265 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266 }
5267 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005268 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005269 return status;
5270}
5271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005272static int in_dump(const struct audio_stream *stream __unused,
5273 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005274{
5275 return 0;
5276}
5277
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305278static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5279{
5280 if (!stream || !parms)
5281 return;
5282
5283 struct stream_in *in = (struct stream_in *)stream;
5284 struct audio_device *adev = in->dev;
5285
5286 card_status_t status;
5287 int card;
5288 if (parse_snd_card_status(parms, &card, &status) < 0)
5289 return;
5290
5291 pthread_mutex_lock(&adev->lock);
5292 bool valid_cb = (card == adev->snd_card);
5293 pthread_mutex_unlock(&adev->lock);
5294
5295 if (!valid_cb)
5296 return;
5297
5298 lock_input_stream(in);
5299 if (in->card_status != status)
5300 in->card_status = status;
5301 pthread_mutex_unlock(&in->lock);
5302
5303 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5304 use_case_table[in->usecase],
5305 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5306
5307 // a better solution would be to report error back to AF and let
5308 // it put the stream to standby
5309 if (status == CARD_STATUS_OFFLINE)
5310 in_standby(&in->stream.common);
5311
5312 return;
5313}
5314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5316{
5317 struct stream_in *in = (struct stream_in *)stream;
5318 struct audio_device *adev = in->dev;
5319 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005321 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005322
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305323 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324 parms = str_parms_create_str(kvpairs);
5325
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305326 if (!parms)
5327 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005328 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005329 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005330
5331 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5332 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005333 val = atoi(value);
5334 /* no audio source uses val == 0 */
5335 if ((in->source != val) && (val != 0)) {
5336 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005337 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5338 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5339 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005340 (in->config.rate == 8000 || in->config.rate == 16000 ||
5341 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005342 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005343 err = voice_extn_compress_voip_open_input_stream(in);
5344 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005345 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005346 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005347 }
5348 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 }
5350 }
5351
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005352 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5353 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005354 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005355 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5356
5357 // Workaround: If routing to an non existing usb device, fail gracefully
5358 // The routing request will otherwise block during 10 second
5359 int card;
5360 if (audio_is_usb_in_device(val) &&
5361 (card = get_alive_usb_card(parms)) >= 0) {
5362
5363 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5364 ret = -ENOSYS;
5365 } else {
5366
5367 in->device = val;
5368 /* If recording is in progress, change the tx device to new device */
5369 if (!in->standby && !in->is_st_session) {
5370 ALOGV("update input routing change");
5371 // inform adm before actual routing to prevent glitches.
5372 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005373 adev->adm_on_routing_change(adev->adm_data,
5374 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005375 ret = select_devices(adev, in->usecase);
5376 }
5377 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379 }
5380 }
5381
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305382 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5383 if (err >= 0) {
5384 strlcpy(in->profile, value, sizeof(in->profile));
5385 ALOGV("updating stream profile with value '%s'", in->profile);
5386 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5387 &adev->streams_input_cfg_list,
5388 in->device, in->flags, in->format,
5389 in->sample_rate, in->bit_width,
5390 in->profile, &in->app_type_cfg);
5391 }
5392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005393 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005394 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395
5396 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305397error:
Eric Laurent994a6932013-07-17 11:51:42 -07005398 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005399 return ret;
5400}
5401
5402static char* in_get_parameters(const struct audio_stream *stream,
5403 const char *keys)
5404{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005405 struct stream_in *in = (struct stream_in *)stream;
5406 struct str_parms *query = str_parms_create_str(keys);
5407 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005408 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005409
5410 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005411 if (reply) {
5412 str_parms_destroy(reply);
5413 }
5414 if (query) {
5415 str_parms_destroy(query);
5416 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005417 ALOGE("in_get_parameters: failed to create query or reply");
5418 return NULL;
5419 }
5420
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005421 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005422
5423 voice_extn_in_get_parameters(in, query, reply);
5424
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005425 stream_get_parameter_channels(query, reply,
5426 &in->supported_channel_masks[0]);
5427 stream_get_parameter_formats(query, reply,
5428 &in->supported_formats[0]);
5429 stream_get_parameter_rates(query, reply,
5430 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005431 str = str_parms_to_str(reply);
5432 str_parms_destroy(query);
5433 str_parms_destroy(reply);
5434
5435 ALOGV("%s: exit: returns - %s", __func__, str);
5436 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005437}
5438
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005439static int in_set_gain(struct audio_stream_in *stream __unused,
5440 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441{
5442 return 0;
5443}
5444
5445static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5446 size_t bytes)
5447{
5448 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305449
5450 if (in == NULL) {
5451 ALOGE("%s: stream_in ptr is NULL", __func__);
5452 return -EINVAL;
5453 }
5454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305456 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305457 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005459 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305460
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005461 if (in->is_st_session) {
5462 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5463 /* Read from sound trigger HAL */
5464 audio_extn_sound_trigger_read(in, buffer, bytes);
5465 pthread_mutex_unlock(&in->lock);
5466 return bytes;
5467 }
5468
Haynes Mathew George16081042017-05-31 17:16:49 -07005469 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5470 ret = -ENOSYS;
5471 goto exit;
5472 }
5473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005474 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005475 pthread_mutex_lock(&adev->lock);
5476 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5477 ret = voice_extn_compress_voip_start_input_stream(in);
5478 else
5479 ret = start_input_stream(in);
5480 pthread_mutex_unlock(&adev->lock);
5481 if (ret != 0) {
5482 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483 }
5484 in->standby = 0;
5485 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005487 // what's the duration requested by the client?
5488 long ns = 0;
5489
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305490 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005491 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5492 in->config.rate;
5493
5494 request_in_focus(in, ns);
5495 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005496
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305497 if (audio_extn_cin_attached_usecase(in->usecase)) {
5498 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5499 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305500 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005501 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305502 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005503 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005504 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005505 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005506 } else if (audio_extn_ffv_get_stream() == in) {
5507 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305508 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005509 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305510 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5511 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5512 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5513 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305514 ret = -EINVAL;
5515 goto exit;
5516 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305517 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305518 ret = -errno;
5519 }
5520 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305521 /* bytes read is always set to bytes for non compress usecases */
5522 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 }
5524
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005525 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005527 /*
5528 * Instead of writing zeroes here, we could trust the hardware
5529 * to always provide zeroes when muted.
5530 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305531 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5532 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005533 memset(buffer, 0, bytes);
5534
5535exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005536 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305537 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005538 pthread_mutex_unlock(&in->lock);
5539
5540 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305541 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305542 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305543 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305544 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305545 in->standby = true;
5546 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305547 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5548 bytes_read = bytes;
5549 memset(buffer, 0, bytes);
5550 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005552 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305553 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305554 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305556 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005557}
5558
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005559static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005560{
5561 return 0;
5562}
5563
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005564static int add_remove_audio_effect(const struct audio_stream *stream,
5565 effect_handle_t effect,
5566 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005568 struct stream_in *in = (struct stream_in *)stream;
5569 int status = 0;
5570 effect_descriptor_t desc;
5571
5572 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005573 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5574
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005575 if (status != 0)
5576 return status;
5577
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005578 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005579 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005580 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5581 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005582 in->enable_aec != enable &&
5583 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5584 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005585 if (!in->standby) {
5586 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5587 select_devices(in->dev, in->usecase);
5588 }
5589
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005590 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005591 if (in->enable_ns != enable &&
5592 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5593 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005594 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005595 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5596 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005597 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5598 select_devices(in->dev, in->usecase);
5599 } else
5600 select_devices(in->dev, in->usecase);
5601 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005602 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005603 pthread_mutex_unlock(&in->dev->lock);
5604 pthread_mutex_unlock(&in->lock);
5605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005606 return 0;
5607}
5608
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005609static int in_add_audio_effect(const struct audio_stream *stream,
5610 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005611{
Eric Laurent994a6932013-07-17 11:51:42 -07005612 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005613 return add_remove_audio_effect(stream, effect, true);
5614}
5615
5616static int in_remove_audio_effect(const struct audio_stream *stream,
5617 effect_handle_t effect)
5618{
Eric Laurent994a6932013-07-17 11:51:42 -07005619 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005620 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005621}
5622
Haynes Mathew George16081042017-05-31 17:16:49 -07005623static int in_stop(const struct audio_stream_in* stream)
5624{
5625 struct stream_in *in = (struct stream_in *)stream;
5626 struct audio_device *adev = in->dev;
5627
5628 int ret = -ENOSYS;
5629 ALOGV("%s", __func__);
5630 pthread_mutex_lock(&adev->lock);
5631 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5632 in->capture_started && in->pcm != NULL) {
5633 pcm_stop(in->pcm);
5634 ret = stop_input_stream(in);
5635 in->capture_started = false;
5636 }
5637 pthread_mutex_unlock(&adev->lock);
5638 return ret;
5639}
5640
5641static int in_start(const struct audio_stream_in* stream)
5642{
5643 struct stream_in *in = (struct stream_in *)stream;
5644 struct audio_device *adev = in->dev;
5645 int ret = -ENOSYS;
5646
5647 ALOGV("%s in %p", __func__, in);
5648 pthread_mutex_lock(&adev->lock);
5649 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5650 !in->capture_started && in->pcm != NULL) {
5651 if (!in->capture_started) {
5652 ret = start_input_stream(in);
5653 if (ret == 0) {
5654 in->capture_started = true;
5655 }
5656 }
5657 }
5658 pthread_mutex_unlock(&adev->lock);
5659 return ret;
5660}
5661
5662static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5663 int32_t min_size_frames,
5664 struct audio_mmap_buffer_info *info)
5665{
5666 struct stream_in *in = (struct stream_in *)stream;
5667 struct audio_device *adev = in->dev;
5668 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005669 unsigned int offset1 = 0;
5670 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005671 const char *step = "";
5672
5673 pthread_mutex_lock(&adev->lock);
5674 ALOGV("%s in %p", __func__, in);
5675
5676 if (info == NULL || min_size_frames == 0) {
5677 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5678 ret = -EINVAL;
5679 goto exit;
5680 }
5681 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5682 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5683 ALOGV("%s in %p", __func__, in);
5684 ret = -ENOSYS;
5685 goto exit;
5686 }
5687 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5688 if (in->pcm_device_id < 0) {
5689 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5690 __func__, in->pcm_device_id, in->usecase);
5691 ret = -EINVAL;
5692 goto exit;
5693 }
5694
5695 adjust_mmap_period_count(&in->config, min_size_frames);
5696
5697 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5698 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5699 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5700 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5701 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5702 step = "open";
5703 ret = -ENODEV;
5704 goto exit;
5705 }
5706
5707 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5708 if (ret < 0) {
5709 step = "begin";
5710 goto exit;
5711 }
5712 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5713 info->burst_size_frames = in->config.period_size;
5714 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5715
5716 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5717 info->buffer_size_frames));
5718
5719 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5720 if (ret < 0) {
5721 step = "commit";
5722 goto exit;
5723 }
5724
5725 in->standby = false;
5726 ret = 0;
5727
5728 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5729 __func__, info->shared_memory_address, info->buffer_size_frames);
5730
5731exit:
5732 if (ret != 0) {
5733 if (in->pcm == NULL) {
5734 ALOGE("%s: %s - %d", __func__, step, ret);
5735 } else {
5736 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5737 pcm_close(in->pcm);
5738 in->pcm = NULL;
5739 }
5740 }
5741 pthread_mutex_unlock(&adev->lock);
5742 return ret;
5743}
5744
5745static int in_get_mmap_position(const struct audio_stream_in *stream,
5746 struct audio_mmap_position *position)
5747{
5748 struct stream_in *in = (struct stream_in *)stream;
5749 ALOGVV("%s", __func__);
5750 if (position == NULL) {
5751 return -EINVAL;
5752 }
5753 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5754 return -ENOSYS;
5755 }
5756 if (in->pcm == NULL) {
5757 return -ENOSYS;
5758 }
5759 struct timespec ts = { 0, 0 };
5760 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5761 if (ret < 0) {
5762 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5763 return ret;
5764 }
5765 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5766 return 0;
5767}
5768
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305769static int in_get_active_microphones(const struct audio_stream_in *stream,
5770 struct audio_microphone_characteristic_t *mic_array,
5771 size_t *mic_count) {
5772 struct stream_in *in = (struct stream_in *)stream;
5773 struct audio_device *adev = in->dev;
5774 ALOGVV("%s", __func__);
5775
5776 lock_input_stream(in);
5777 pthread_mutex_lock(&adev->lock);
5778 int ret = platform_get_active_microphones(adev->platform,
5779 audio_channel_count_from_in_mask(in->channel_mask),
5780 in->usecase, mic_array, mic_count);
5781 pthread_mutex_unlock(&adev->lock);
5782 pthread_mutex_unlock(&in->lock);
5783
5784 return ret;
5785}
5786
5787static int adev_get_microphones(const struct audio_hw_device *dev,
5788 struct audio_microphone_characteristic_t *mic_array,
5789 size_t *mic_count) {
5790 struct audio_device *adev = (struct audio_device *)dev;
5791 ALOGVV("%s", __func__);
5792
5793 pthread_mutex_lock(&adev->lock);
5794 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5795 pthread_mutex_unlock(&adev->lock);
5796
5797 return ret;
5798}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305799int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005800 audio_io_handle_t handle,
5801 audio_devices_t devices,
5802 audio_output_flags_t flags,
5803 struct audio_config *config,
5804 struct audio_stream_out **stream_out,
5805 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005806{
5807 struct audio_device *adev = (struct audio_device *)dev;
5808 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305809 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005810 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005811 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305812 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005813 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5814 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5815 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5816 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005817
kunleizdff872d2018-08-20 14:40:33 +08005818 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08005819 is_usb_dev = false;
5820 devices = AUDIO_DEVICE_OUT_SPEAKER;
5821 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5822 __func__, devices);
5823 }
5824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005827 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5828
Mingming Yin3a941d42016-02-17 18:08:05 -08005829 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5830 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305831 devices, flags, &out->stream);
5832
5833
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005834 if (!out) {
5835 return -ENOMEM;
5836 }
5837
Haynes Mathew George204045b2015-02-25 20:32:03 -08005838 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005839 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305840 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005841 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005842 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 if (devices == AUDIO_DEVICE_NONE)
5845 devices = AUDIO_DEVICE_OUT_SPEAKER;
5846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005847 out->flags = flags;
5848 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005849 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005850 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005851 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305852 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305853 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5854 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5855 else
5856 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005857 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005858 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005859 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305860 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305861 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305862 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005863 out->hal_output_suspend_supported = 0;
5864 out->dynamic_pm_qos_config_supported = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005865
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305866 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305867 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005868 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5869
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005870 if (audio_is_linear_pcm(out->format) &&
5871 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5872 pthread_mutex_lock(&adev->lock);
5873 if (is_hdmi) {
5874 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5875 ret = read_hdmi_sink_caps(out);
5876 } else if (is_usb_dev) {
5877 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5878 &config->format,
5879 &out->supported_formats[0],
5880 MAX_SUPPORTED_FORMATS,
5881 &config->channel_mask,
5882 &out->supported_channel_masks[0],
5883 MAX_SUPPORTED_CHANNEL_MASKS,
5884 &config->sample_rate,
5885 &out->supported_sample_rates[0],
5886 MAX_SUPPORTED_SAMPLE_RATES);
5887 ALOGV("plugged dev USB ret %d", ret);
5888 } else {
5889 ret = -1;
5890 }
5891 pthread_mutex_unlock(&adev->lock);
5892 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005893 if (ret == -ENOSYS) {
5894 /* ignore and go with default */
5895 ret = 0;
5896 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005897 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005898 goto error_open;
5899 }
5900 }
5901 }
5902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005903 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005904#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005905 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5906 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5907 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5908 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5909 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5910 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5911
5912 out->config = default_pcm_config_voip_copp;
5913 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5914 out->config.rate = out->sample_rate;
5915
5916#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305917 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005918 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005919 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005920 ret = voice_extn_compress_voip_open_output_stream(out);
5921 if (ret != 0) {
5922 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5923 __func__, ret);
5924 goto error_open;
5925 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005926#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005927 } else if (audio_is_linear_pcm(out->format) &&
5928 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5929 out->channel_mask = config->channel_mask;
5930 out->sample_rate = config->sample_rate;
5931 out->format = config->format;
5932 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5933 // does this change?
5934 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5935 out->config.rate = config->sample_rate;
5936 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5937 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5938 audio_bytes_per_sample(config->format));
5939 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005940 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305941 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305942 pthread_mutex_lock(&adev->lock);
5943 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5944 pthread_mutex_unlock(&adev->lock);
5945
5946 // reject offload during card offline to allow
5947 // fallback to s/w paths
5948 if (offline) {
5949 ret = -ENODEV;
5950 goto error_open;
5951 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005953 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5954 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5955 ALOGE("%s: Unsupported Offload information", __func__);
5956 ret = -EINVAL;
5957 goto error_open;
5958 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005959
Atul Khare3fa6e542017-08-09 00:56:17 +05305960 if (config->offload_info.format == 0)
5961 config->offload_info.format = config->format;
5962 if (config->offload_info.sample_rate == 0)
5963 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005964
Mingming Yin90310102013-11-13 16:57:00 -08005965 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305966 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005967 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005968 ret = -EINVAL;
5969 goto error_open;
5970 }
5971
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005972 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5973 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5974 (audio_extn_passthru_is_passthrough_stream(out)) &&
5975 !((config->sample_rate == 48000) ||
5976 (config->sample_rate == 96000) ||
5977 (config->sample_rate == 192000))) {
5978 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5979 __func__, config->sample_rate, config->offload_info.format);
5980 ret = -EINVAL;
5981 goto error_open;
5982 }
5983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005984 out->compr_config.codec = (struct snd_codec *)
5985 calloc(1, sizeof(struct snd_codec));
5986
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005987 if (!out->compr_config.codec) {
5988 ret = -ENOMEM;
5989 goto error_open;
5990 }
5991
Dhananjay Kumarac341582017-02-23 23:42:25 +05305992 out->stream.pause = out_pause;
5993 out->stream.resume = out_resume;
5994 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305995 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305996 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005997 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305998 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005999 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306000 } else {
6001 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6002 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006003 }
vivek mehta446c3962015-09-14 10:57:35 -07006004
6005 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006006 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6007 config->format == 0 && config->sample_rate == 0 &&
6008 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006009 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006010 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6011 } else {
6012 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6013 ret = -EEXIST;
6014 goto error_open;
6015 }
vivek mehta446c3962015-09-14 10:57:35 -07006016 }
6017
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018 if (config->offload_info.channel_mask)
6019 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006020 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006021 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006022 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006023 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306024 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006025 ret = -EINVAL;
6026 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006027 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006028
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006029 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006030 out->sample_rate = config->offload_info.sample_rate;
6031
Mingming Yin3ee55c62014-08-04 14:23:35 -07006032 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006033
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306034 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306035 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306036 audio_extn_dolby_send_ddp_endp_params(adev);
6037 audio_extn_dolby_set_dmid(adev);
6038 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006039
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006040 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006041 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 out->compr_config.codec->bit_rate =
6043 config->offload_info.bit_rate;
6044 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306045 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006046 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306047 /* Update bit width only for non passthrough usecases.
6048 * For passthrough usecases, the output will always be opened @16 bit
6049 */
6050 if (!audio_extn_passthru_is_passthrough_stream(out))
6051 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306052
6053 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6054 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6055 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6056
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006057 /*TODO: Do we need to change it for passthrough */
6058 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006059
Manish Dewangana6fc5442015-08-24 20:30:31 +05306060 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6061 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306062 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306063 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306064 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6065 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306066
6067 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6068 AUDIO_FORMAT_PCM) {
6069
6070 /*Based on platform support, configure appropriate alsa format for corresponding
6071 *hal input format.
6072 */
6073 out->compr_config.codec->format = hal_format_to_alsa(
6074 config->offload_info.format);
6075
Ashish Jain83a6cc22016-06-28 14:34:17 +05306076 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306077 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306078 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306079
Dhananjay Kumarac341582017-02-23 23:42:25 +05306080 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306081 *hal input format and alsa format might differ based on platform support.
6082 */
6083 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306084 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306085
6086 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6087
6088 /* Check if alsa session is configured with the same format as HAL input format,
6089 * if not then derive correct fragment size needed to accomodate the
6090 * conversion of HAL input format to alsa format.
6091 */
6092 audio_extn_utils_update_direct_pcm_fragment_size(out);
6093
6094 /*if hal input and output fragment size is different this indicates HAL input format is
6095 *not same as the alsa format
6096 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306097 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306098 /*Allocate a buffer to convert input data to the alsa configured format.
6099 *size of convert buffer is equal to the size required to hold one fragment size
6100 *worth of pcm data, this is because flinger does not write more than fragment_size
6101 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306102 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6103 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306104 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6105 ret = -ENOMEM;
6106 goto error_open;
6107 }
6108 }
6109 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6110 out->compr_config.fragment_size =
6111 audio_extn_passthru_get_buffer_size(&config->offload_info);
6112 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6113 } else {
6114 out->compr_config.fragment_size =
6115 platform_get_compress_offload_buffer_size(&config->offload_info);
6116 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6117 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006118
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306119 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6120 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6121 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006122 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306123 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006124
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306125 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6126 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6127 }
6128
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006129 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6130 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006131
Manish Dewangan69426c82017-01-30 17:35:36 +05306132 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6133 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6134 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6135 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6136 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6137 } else {
6138 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6139 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006140
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306141 memset(&out->channel_map_param, 0,
6142 sizeof(struct audio_out_channel_map_param));
6143
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006144 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306145 out->send_next_track_params = false;
6146 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006147 out->offload_state = OFFLOAD_STATE_IDLE;
6148 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006149 out->writeAt.tv_sec = 0;
6150 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006151
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006152 audio_extn_dts_create_state_notifier_node(out->usecase);
6153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006154 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6155 __func__, config->offload_info.version,
6156 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306157
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306158 /* Check if DSD audio format is supported in codec
6159 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306160 */
6161
6162 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306163 (!platform_check_codec_dsd_support(adev->platform) ||
6164 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306165 ret = -EINVAL;
6166 goto error_open;
6167 }
6168
Ashish Jain5106d362016-05-11 19:23:33 +05306169 /* Disable gapless if any of the following is true
6170 * passthrough playback
6171 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306172 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306173 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306174 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306175 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006176 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306177 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306178 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306179 check_and_set_gapless_mode(adev, false);
6180 } else
6181 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006182
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306183 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006184 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6185 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306186 if (config->format == AUDIO_FORMAT_DSD) {
6187 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6188 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6189 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006190
6191 create_offload_callback_thread(out);
6192
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006193 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006194 switch (config->sample_rate) {
6195 case 0:
6196 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6197 break;
6198 case 8000:
6199 case 16000:
6200 case 48000:
6201 out->sample_rate = config->sample_rate;
6202 break;
6203 default:
6204 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6205 config->sample_rate);
6206 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6207 ret = -EINVAL;
6208 goto error_open;
6209 }
6210 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6211 switch (config->channel_mask) {
6212 case AUDIO_CHANNEL_NONE:
6213 case AUDIO_CHANNEL_OUT_STEREO:
6214 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6215 break;
6216 default:
6217 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6218 config->channel_mask);
6219 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6220 ret = -EINVAL;
6221 goto error_open;
6222 }
6223 switch (config->format) {
6224 case AUDIO_FORMAT_DEFAULT:
6225 case AUDIO_FORMAT_PCM_16_BIT:
6226 out->format = AUDIO_FORMAT_PCM_16_BIT;
6227 break;
6228 default:
6229 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6230 config->format);
6231 config->format = AUDIO_FORMAT_PCM_16_BIT;
6232 ret = -EINVAL;
6233 goto error_open;
6234 }
6235
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306236 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006237 if (ret != 0) {
6238 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006239 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006240 goto error_open;
6241 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006242 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006243 if (config->sample_rate == 0)
6244 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6245 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6246 config->sample_rate != 8000) {
6247 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6248 ret = -EINVAL;
6249 goto error_open;
6250 }
6251 out->sample_rate = config->sample_rate;
6252 out->config.rate = config->sample_rate;
6253 if (config->format == AUDIO_FORMAT_DEFAULT)
6254 config->format = AUDIO_FORMAT_PCM_16_BIT;
6255 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6256 config->format = AUDIO_FORMAT_PCM_16_BIT;
6257 ret = -EINVAL;
6258 goto error_open;
6259 }
6260 out->format = config->format;
6261 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6262 out->config = pcm_config_afe_proxy_playback;
6263 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006264 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306265 unsigned int channels = 0;
6266 /*Update config params to default if not set by the caller*/
6267 if (config->sample_rate == 0)
6268 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6269 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6270 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6271 if (config->format == AUDIO_FORMAT_DEFAULT)
6272 config->format = AUDIO_FORMAT_PCM_16_BIT;
6273
6274 channels = audio_channel_count_from_out_mask(out->channel_mask);
6275
Varun Balaraje49253e2017-07-06 19:48:56 +05306276 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6277 out->usecase = get_interactive_usecase(adev);
6278 out->config = pcm_config_low_latency;
6279 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306280 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006281 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6282 out->flags);
6283 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006284 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6285 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6286 out->config = pcm_config_mmap_playback;
6287 out->stream.start = out_start;
6288 out->stream.stop = out_stop;
6289 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6290 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306291 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6292 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006293 out->hal_output_suspend_supported =
6294 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6295 out->dynamic_pm_qos_config_supported =
6296 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6297 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006298 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6299 } else {
6300 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6301 //the mixer path will be a string similar to "low-latency-playback resume"
6302 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6303 strlcat(out->pm_qos_mixer_path,
6304 " resume", MAX_MIXER_PATH_LEN);
6305 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6306 out->pm_qos_mixer_path);
6307 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306308 out->config = pcm_config_low_latency;
6309 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6310 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6311 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306312 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6313 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6314 if (out->config.period_size <= 0) {
6315 ALOGE("Invalid configuration period size is not valid");
6316 ret = -EINVAL;
6317 goto error_open;
6318 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306319 } else {
6320 /* primary path is the default path selected if no other outputs are available/suitable */
6321 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6322 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6323 }
6324 out->hal_ip_format = format = out->format;
6325 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6326 out->hal_op_format = pcm_format_to_hal(out->config.format);
6327 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6328 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006329 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306330 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306331 if (out->hal_ip_format != out->hal_op_format) {
6332 uint32_t buffer_size = out->config.period_size *
6333 format_to_bitwidth_table[out->hal_op_format] *
6334 out->config.channels;
6335 out->convert_buffer = calloc(1, buffer_size);
6336 if (out->convert_buffer == NULL){
6337 ALOGE("Allocation failed for convert buffer for size %d",
6338 out->compr_config.fragment_size);
6339 ret = -ENOMEM;
6340 goto error_open;
6341 }
6342 ALOGD("Convert buffer allocated of size %d", buffer_size);
6343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006344 }
6345
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006346 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6347 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306348
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006349 /* TODO remove this hardcoding and check why width is zero*/
6350 if (out->bit_width == 0)
6351 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306352 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006353 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006354 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306355 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306356 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006357 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6358 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6359 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006360 if(adev->primary_output == NULL)
6361 adev->primary_output = out;
6362 else {
6363 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006364 ret = -EEXIST;
6365 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006366 }
6367 }
6368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006369 /* Check if this usecase is already existing */
6370 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006371 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6372 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006373 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006374 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006375 ret = -EEXIST;
6376 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006377 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006379 pthread_mutex_unlock(&adev->lock);
6380
6381 out->stream.common.get_sample_rate = out_get_sample_rate;
6382 out->stream.common.set_sample_rate = out_set_sample_rate;
6383 out->stream.common.get_buffer_size = out_get_buffer_size;
6384 out->stream.common.get_channels = out_get_channels;
6385 out->stream.common.get_format = out_get_format;
6386 out->stream.common.set_format = out_set_format;
6387 out->stream.common.standby = out_standby;
6388 out->stream.common.dump = out_dump;
6389 out->stream.common.set_parameters = out_set_parameters;
6390 out->stream.common.get_parameters = out_get_parameters;
6391 out->stream.common.add_audio_effect = out_add_audio_effect;
6392 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6393 out->stream.get_latency = out_get_latency;
6394 out->stream.set_volume = out_set_volume;
6395 out->stream.write = out_write;
6396 out->stream.get_render_position = out_get_render_position;
6397 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006398 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006399
Haynes Mathew George16081042017-05-31 17:16:49 -07006400 if (out->realtime)
6401 out->af_period_multiplier = af_period_multiplier;
6402 else
6403 out->af_period_multiplier = 1;
6404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006405 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006406 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006407 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408
6409 config->format = out->stream.common.get_format(&out->stream.common);
6410 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6411 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306412 register_format(out->format, out->supported_formats);
6413 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6414 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306416 /*
6417 By locking output stream before registering, we allow the callback
6418 to update stream's state only after stream's initial state is set to
6419 adev state.
6420 */
6421 lock_output_stream(out);
6422 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6423 pthread_mutex_lock(&adev->lock);
6424 out->card_status = adev->card_status;
6425 pthread_mutex_unlock(&adev->lock);
6426 pthread_mutex_unlock(&out->lock);
6427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006428 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306429 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006430 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006431
6432 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6433 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6434 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006435 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306436 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006437 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006438 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306439 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006440 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6441 out->usecase, PCM_PLAYBACK);
6442 hdlr_stream_cfg.flags = out->flags;
6443 hdlr_stream_cfg.type = PCM_PLAYBACK;
6444 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6445 &hdlr_stream_cfg);
6446 if (ret) {
6447 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6448 out->adsp_hdlr_stream_handle = NULL;
6449 }
6450 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306451 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006452 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006453 if (ret < 0) {
6454 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6455 out->ip_hdlr_handle = NULL;
6456 }
6457 }
Eric Laurent994a6932013-07-17 11:51:42 -07006458 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006459 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006460
6461error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306462 if (out->convert_buffer)
6463 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006464 free(out);
6465 *stream_out = NULL;
6466 ALOGD("%s: exit: ret %d", __func__, ret);
6467 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006468}
6469
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306470void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006471 struct audio_stream_out *stream)
6472{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006473 struct stream_out *out = (struct stream_out *)stream;
6474 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006475 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006476
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006477 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306478
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306479 // must deregister from sndmonitor first to prevent races
6480 // between the callback and close_stream
6481 audio_extn_snd_mon_unregister_listener(out);
6482
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006483 /* close adsp hdrl session before standby */
6484 if (out->adsp_hdlr_stream_handle) {
6485 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6486 if (ret)
6487 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6488 out->adsp_hdlr_stream_handle = NULL;
6489 }
6490
Manish Dewangan21a850a2017-08-14 12:03:55 +05306491 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006492 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6493 out->ip_hdlr_handle = NULL;
6494 }
6495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006496 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306497 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006498 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306499 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306500 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006501 if(ret != 0)
6502 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6503 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006504 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006505 out_standby(&stream->common);
6506
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006507 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006508 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006509 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006510 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006511 if (out->compr_config.codec != NULL)
6512 free(out->compr_config.codec);
6513 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006514
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306515 out->a2dp_compress_mute = false;
6516
Varun Balaraje49253e2017-07-06 19:48:56 +05306517 if (is_interactive_usecase(out->usecase))
6518 free_interactive_usecase(adev, out->usecase);
6519
Ashish Jain83a6cc22016-06-28 14:34:17 +05306520 if (out->convert_buffer != NULL) {
6521 free(out->convert_buffer);
6522 out->convert_buffer = NULL;
6523 }
6524
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006525 if (adev->voice_tx_output == out)
6526 adev->voice_tx_output = NULL;
6527
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306528 if (adev->primary_output == out)
6529 adev->primary_output = NULL;
6530
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006531 pthread_cond_destroy(&out->cond);
6532 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006533 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006534 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006535}
6536
6537static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6538{
6539 struct audio_device *adev = (struct audio_device *)dev;
6540 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006541 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006542 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006543 int ret;
6544 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006545
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006546 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006547 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006548
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306549 if (!parms)
6550 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306551
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306552 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6553 if (ret >= 0) {
6554 /* When set to false, HAL should disable EC and NS */
6555 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6556 adev->bt_sco_on = true;
6557 else
6558 adev->bt_sco_on = false;
6559 }
6560
Naresh Tanniru4c630392014-05-12 01:05:52 +05306561 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006562 status = voice_set_parameters(adev, parms);
6563 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006564 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006565
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006566 status = platform_set_parameters(adev->platform, parms);
6567 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006568 goto done;
6569
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006570 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6571 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006572 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006573 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6574 adev->bluetooth_nrec = true;
6575 else
6576 adev->bluetooth_nrec = false;
6577 }
6578
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006579 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6580 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006581 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6582 adev->screen_off = false;
6583 else
6584 adev->screen_off = true;
6585 }
6586
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006587 ret = str_parms_get_int(parms, "rotation", &val);
6588 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006589 bool reverse_speakers = false;
6590 switch(val) {
6591 // FIXME: note that the code below assumes that the speakers are in the correct placement
6592 // relative to the user when the device is rotated 90deg from its default rotation. This
6593 // assumption is device-specific, not platform-specific like this code.
6594 case 270:
6595 reverse_speakers = true;
6596 break;
6597 case 0:
6598 case 90:
6599 case 180:
6600 break;
6601 default:
6602 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006603 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006604 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006605 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006606 // check and set swap
6607 // - check if orientation changed and speaker active
6608 // - set rotation and cache the rotation value
6609 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006610 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006611 }
6612
Mingming Yin514a8bc2014-07-29 15:22:21 -07006613 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6614 if (ret >= 0) {
6615 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6616 adev->bt_wb_speech_enabled = true;
6617 else
6618 adev->bt_wb_speech_enabled = false;
6619 }
6620
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006621 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6622 if (ret >= 0) {
6623 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306624 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006625 if (audio_is_output_device(val) &&
6626 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006627 ALOGV("cache new ext disp type and edid");
6628 ret = platform_get_ext_disp_type(adev->platform);
6629 if (ret < 0) {
6630 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306631 } else {
6632 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006633 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306634 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006635 /*
6636 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6637 * Per AudioPolicyManager, USB device is higher priority than WFD.
6638 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6639 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6640 * starting voice call on USB
6641 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006642 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306643 if (ret >= 0)
6644 audio_extn_usb_add_device(device, atoi(value));
6645
Zhou Song6f862822017-11-06 17:27:57 +08006646 if (!audio_extn_usb_is_tunnel_supported()) {
6647 ALOGV("detected USB connect .. disable proxy");
6648 adev->allow_afe_proxy_usage = false;
6649 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006650 }
6651 }
6652
6653 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6654 if (ret >= 0) {
6655 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306656 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006657 /*
6658 * The HDMI / Displayport disconnect handling has been moved to
6659 * audio extension to ensure that its parameters are not
6660 * invalidated prior to updating sysfs of the disconnect event
6661 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6662 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306663 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006664 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306665 if (ret >= 0)
6666 audio_extn_usb_remove_device(device, atoi(value));
6667
Zhou Song6f862822017-11-06 17:27:57 +08006668 if (!audio_extn_usb_is_tunnel_supported()) {
6669 ALOGV("detected USB disconnect .. enable proxy");
6670 adev->allow_afe_proxy_usage = true;
6671 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006672 }
6673 }
6674
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306675 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6676 if (ret >= 0) {
6677 struct audio_usecase *usecase;
6678 struct listnode *node;
6679 list_for_each(node, &adev->usecase_list) {
6680 usecase = node_to_item(node, struct audio_usecase, list);
6681 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006682 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306683 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006684
6685 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306686 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006687 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306688 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306689 //force device switch to re configure encoder
6690 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306691 audio_extn_a2dp_set_handoff_mode(false);
6692 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306693 break;
6694 }
6695 }
6696 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006697
6698 //handle vr audio setparam
6699 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6700 value, sizeof(value));
6701 if (ret >= 0) {
6702 ALOGI("Setting vr mode to be %s", value);
6703 if (!strncmp(value, "true", 4)) {
6704 adev->vr_audio_mode_enabled = true;
6705 ALOGI("Setting vr mode to true");
6706 } else if (!strncmp(value, "false", 5)) {
6707 adev->vr_audio_mode_enabled = false;
6708 ALOGI("Setting vr mode to false");
6709 } else {
6710 ALOGI("wrong vr mode set");
6711 }
6712 }
6713
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306714 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006715done:
6716 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006717 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306718error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006719 ALOGV("%s: exit with code(%d)", __func__, status);
6720 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721}
6722
6723static char* adev_get_parameters(const struct audio_hw_device *dev,
6724 const char *keys)
6725{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006726 struct audio_device *adev = (struct audio_device *)dev;
6727 struct str_parms *reply = str_parms_create();
6728 struct str_parms *query = str_parms_create_str(keys);
6729 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306730 char value[256] = {0};
6731 int ret = 0;
6732
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006733 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006734 if (reply) {
6735 str_parms_destroy(reply);
6736 }
6737 if (query) {
6738 str_parms_destroy(query);
6739 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006740 ALOGE("adev_get_parameters: failed to create query or reply");
6741 return NULL;
6742 }
6743
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006744 //handle vr audio getparam
6745
6746 ret = str_parms_get_str(query,
6747 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6748 value, sizeof(value));
6749
6750 if (ret >= 0) {
6751 bool vr_audio_enabled = false;
6752 pthread_mutex_lock(&adev->lock);
6753 vr_audio_enabled = adev->vr_audio_mode_enabled;
6754 pthread_mutex_unlock(&adev->lock);
6755
6756 ALOGI("getting vr mode to %d", vr_audio_enabled);
6757
6758 if (vr_audio_enabled) {
6759 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6760 "true");
6761 goto exit;
6762 } else {
6763 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6764 "false");
6765 goto exit;
6766 }
6767 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006768
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006769 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006770 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006771 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006772 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306773 pthread_mutex_unlock(&adev->lock);
6774
Naresh Tannirud7205b62014-06-20 02:54:48 +05306775exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006776 str = str_parms_to_str(reply);
6777 str_parms_destroy(query);
6778 str_parms_destroy(reply);
6779
6780 ALOGV("%s: exit: returns - %s", __func__, str);
6781 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006782}
6783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006784static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785{
6786 return 0;
6787}
6788
6789static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6790{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006791 int ret;
6792 struct audio_device *adev = (struct audio_device *)dev;
6793 pthread_mutex_lock(&adev->lock);
6794 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006795 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006796 pthread_mutex_unlock(&adev->lock);
6797 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798}
6799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006800static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6801 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006802{
6803 return -ENOSYS;
6804}
6805
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006806static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6807 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006808{
6809 return -ENOSYS;
6810}
6811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006812static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6813 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006814{
6815 return -ENOSYS;
6816}
6817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006818static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6819 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006820{
6821 return -ENOSYS;
6822}
6823
6824static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6825{
6826 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07006827 struct listnode *node;
6828 struct audio_usecase *usecase = NULL;
6829 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006830 pthread_mutex_lock(&adev->lock);
6831 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006832 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006833 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006834 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07006835 list_for_each(node, &adev->usecase_list) {
6836 usecase = node_to_item(node, struct audio_usecase, list);
6837 if (usecase->type == VOICE_CALL)
6838 break;
6839 }
6840 if (usecase &&
6841 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
6842 ret = audio_extn_usb_check_and_set_svc_int(usecase,
6843 true);
6844 if (ret != 0) {
6845 /* default service interval was successfully updated,
6846 reopen USB backend with new service interval */
6847 check_usecases_codec_backend(adev,
6848 usecase,
6849 usecase->out_snd_device);
6850 }
6851 }
6852
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006853 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006854 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006855 adev->current_call_output = NULL;
6856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006857 }
6858 pthread_mutex_unlock(&adev->lock);
6859 return 0;
6860}
6861
6862static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6863{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006864 int ret;
6865
6866 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006867 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006868 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6869 pthread_mutex_unlock(&adev->lock);
6870
6871 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872}
6873
6874static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6875{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006876 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 return 0;
6878}
6879
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006880static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006881 const struct audio_config *config)
6882{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006883 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006884
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006885 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6886 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006887}
6888
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006889static bool adev_input_allow_hifi_record(struct audio_device *adev,
6890 audio_devices_t devices,
6891 audio_input_flags_t flags,
6892 audio_source_t source) {
6893 const bool allowed = true;
6894
6895 if (!audio_is_usb_in_device(devices))
6896 return !allowed;
6897
6898 switch (flags) {
6899 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006900 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006901 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6902 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006903 default:
6904 return !allowed;
6905 }
6906
6907 switch (source) {
6908 case AUDIO_SOURCE_DEFAULT:
6909 case AUDIO_SOURCE_MIC:
6910 case AUDIO_SOURCE_UNPROCESSED:
6911 break;
6912 default:
6913 return !allowed;
6914 }
6915
6916 switch (adev->mode) {
6917 case 0:
6918 break;
6919 default:
6920 return !allowed;
6921 }
6922
6923 return allowed;
6924}
6925
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006926static int adev_update_voice_comm_input_stream(struct stream_in *in,
6927 struct audio_config *config)
6928{
6929 bool valid_rate = (config->sample_rate == 8000 ||
6930 config->sample_rate == 16000 ||
6931 config->sample_rate == 32000 ||
6932 config->sample_rate == 48000);
6933 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
6934
6935#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08006936 if (valid_rate && valid_ch &&
6937 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006938 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6939 in->config = default_pcm_config_voip_copp;
6940 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
6941 DEFAULT_VOIP_BUF_DURATION_MS,
6942 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6943 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08006944 ALOGW("%s No valid input in voip, use defaults"
6945 "sample rate %u, channel mask 0x%X",
6946 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006947 }
6948 in->config.rate = config->sample_rate;
6949 in->sample_rate = config->sample_rate;
6950#else
6951 //XXX needed for voice_extn_compress_voip_open_input_stream
6952 in->config.rate = config->sample_rate;
6953 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6954 voice_extn_compress_voip_is_active(in->dev)) &&
6955 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6956 valid_rate && valid_ch) {
6957 voice_extn_compress_voip_open_input_stream(in);
6958 // update rate entries to match config from AF
6959 in->config.rate = config->sample_rate;
6960 in->sample_rate = config->sample_rate;
6961 } else {
6962 ALOGW("%s compress voip not active, use defaults", __func__);
6963 }
6964#endif
6965 return 0;
6966}
6967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006968static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006969 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006970 audio_devices_t devices,
6971 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006972 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306973 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006974 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006975 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976{
6977 struct audio_device *adev = (struct audio_device *)dev;
6978 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006979 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006980 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006981 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306982 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006983 bool is_usb_dev = audio_is_usb_in_device(devices);
6984 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6985 devices,
6986 flags,
6987 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306988
kunleizdff872d2018-08-20 14:40:33 +08006989 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006990 is_usb_dev = false;
6991 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
6992 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
6993 __func__, devices);
6994 }
6995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006996 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006997
6998 if (!(is_usb_dev && may_use_hifi_record)) {
6999 if (config->sample_rate == 0)
7000 config->sample_rate = 48000;
7001 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7002 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
7003 if (config->format == AUDIO_FORMAT_DEFAULT)
7004 config->format = AUDIO_FORMAT_PCM_16_BIT;
7005
7006 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
7007
7008 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
7009 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05307010 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007011
7012 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007013
7014 if (!in) {
7015 ALOGE("failed to allocate input stream");
7016 return -ENOMEM;
7017 }
7018
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307019 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307020 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7021 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007022 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007023 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025 in->stream.common.get_sample_rate = in_get_sample_rate;
7026 in->stream.common.set_sample_rate = in_set_sample_rate;
7027 in->stream.common.get_buffer_size = in_get_buffer_size;
7028 in->stream.common.get_channels = in_get_channels;
7029 in->stream.common.get_format = in_get_format;
7030 in->stream.common.set_format = in_set_format;
7031 in->stream.common.standby = in_standby;
7032 in->stream.common.dump = in_dump;
7033 in->stream.common.set_parameters = in_set_parameters;
7034 in->stream.common.get_parameters = in_get_parameters;
7035 in->stream.common.add_audio_effect = in_add_audio_effect;
7036 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7037 in->stream.set_gain = in_set_gain;
7038 in->stream.read = in_read;
7039 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307040 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007041
7042 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007043 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007044 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007045 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007046 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007047 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007048 in->bit_width = 16;
7049 in->af_period_multiplier = 1;
7050
7051 /* Update config params with the requested sample rate and channels */
7052 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7053 (adev->mode != AUDIO_MODE_IN_CALL)) {
7054 ret = -EINVAL;
7055 goto err_open;
7056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007057
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007058 if (is_usb_dev && may_use_hifi_record) {
7059 /* HiFi record selects an appropriate format, channel, rate combo
7060 depending on sink capabilities*/
7061 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7062 &config->format,
7063 &in->supported_formats[0],
7064 MAX_SUPPORTED_FORMATS,
7065 &config->channel_mask,
7066 &in->supported_channel_masks[0],
7067 MAX_SUPPORTED_CHANNEL_MASKS,
7068 &config->sample_rate,
7069 &in->supported_sample_rates[0],
7070 MAX_SUPPORTED_SAMPLE_RATES);
7071 if (ret != 0) {
7072 ret = -EINVAL;
7073 goto err_open;
7074 }
7075 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007076 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307077 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307078 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7079 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7080 in->config.format = PCM_FORMAT_S32_LE;
7081 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307082 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7083 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7084 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7085 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7086 bool ret_error = false;
7087 in->bit_width = 24;
7088 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7089 from HAL is 24_packed and 8_24
7090 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7091 24_packed return error indicating supported format is 24_packed
7092 *> In case of any other source requesting 24 bit or float return error
7093 indicating format supported is 16 bit only.
7094
7095 on error flinger will retry with supported format passed
7096 */
7097 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7098 (source != AUDIO_SOURCE_CAMCORDER)) {
7099 config->format = AUDIO_FORMAT_PCM_16_BIT;
7100 if (config->sample_rate > 48000)
7101 config->sample_rate = 48000;
7102 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007103 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7104 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307105 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7106 ret_error = true;
7107 }
7108
7109 if (ret_error) {
7110 ret = -EINVAL;
7111 goto err_open;
7112 }
7113 }
7114
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007115 in->channel_mask = config->channel_mask;
7116 in->format = config->format;
7117
7118 in->usecase = USECASE_AUDIO_RECORD;
7119 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7120 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7121 is_low_latency = true;
7122#if LOW_LATENCY_CAPTURE_USE_CASE
7123 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7124#endif
7125 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7126 }
7127
7128 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7129 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7130 in->realtime = 0;
7131 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7132 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007133 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007134 in->stream.start = in_start;
7135 in->stream.stop = in_stop;
7136 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7137 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007138 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007139 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7140 } else if (in->realtime) {
7141 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007142 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007143 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007144 in->sample_rate = in->config.rate;
7145 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007146 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007147 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7148 in->config = pcm_config_audio_capture;
7149 frame_size = audio_stream_in_frame_size(&in->stream);
7150 buffer_size = get_input_buffer_size(config->sample_rate,
7151 config->format,
7152 channel_count,
7153 false /*is_low_latency*/);
7154 in->config.period_size = buffer_size / frame_size;
7155 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007156 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007157 switch (config->format) {
7158 case AUDIO_FORMAT_PCM_32_BIT:
7159 in->bit_width = 32;
7160 break;
7161 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7162 case AUDIO_FORMAT_PCM_8_24_BIT:
7163 in->bit_width = 24;
7164 break;
7165 default:
7166 in->bit_width = 16;
7167 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007168 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007169 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007170 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307171 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007172 if (config->sample_rate == 0)
7173 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7174 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7175 config->sample_rate != 8000) {
7176 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7177 ret = -EINVAL;
7178 goto err_open;
7179 }
7180 if (config->format == AUDIO_FORMAT_DEFAULT)
7181 config->format = AUDIO_FORMAT_PCM_16_BIT;
7182 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7183 config->format = AUDIO_FORMAT_PCM_16_BIT;
7184 ret = -EINVAL;
7185 goto err_open;
7186 }
7187
7188 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7189 in->config = pcm_config_afe_proxy_record;
7190 in->config.channels = channel_count;
7191 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307192 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007193 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307194 int ret_val;
7195 pthread_mutex_lock(&adev->lock);
7196 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7197 in, config, &channel_mask_updated);
7198 pthread_mutex_unlock(&adev->lock);
7199
7200 if (!ret_val) {
7201 if (channel_mask_updated == true) {
7202 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7203 __func__, config->channel_mask);
7204 ret = -EINVAL;
7205 goto err_open;
7206 }
7207 ALOGD("%s: created multi-channel session succesfully",__func__);
7208 } else if (audio_extn_compr_cap_enabled() &&
7209 audio_extn_compr_cap_format_supported(config->format) &&
7210 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7211 audio_extn_compr_cap_init(in);
7212 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307213 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307214 ret = audio_extn_cin_configure_input_stream(in);
7215 if (ret)
7216 goto err_open;
7217 } else {
7218 in->config = pcm_config_audio_capture;
7219 in->config.rate = config->sample_rate;
7220 in->config.format = pcm_format_from_audio_format(config->format);
7221 in->config.channels = channel_count;
7222 in->sample_rate = config->sample_rate;
7223 in->format = config->format;
7224 frame_size = audio_stream_in_frame_size(&in->stream);
7225 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007226 config->format,
7227 channel_count,
7228 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307229 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007230
Revathi Uddarajud2634032017-12-07 14:42:34 +05307231 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7232 /* optionally use VOIP usecase depending on config(s) */
7233 ret = adev_update_voice_comm_input_stream(in, config);
7234 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007235
Revathi Uddarajud2634032017-12-07 14:42:34 +05307236 if (ret) {
7237 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7238 goto err_open;
7239 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007240 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007241 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307242 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7243 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007244 devices, flags, in->format,
7245 in->sample_rate, in->bit_width,
7246 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307247 register_format(in->format, in->supported_formats);
7248 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7249 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307250
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007251 /* This stream could be for sound trigger lab,
7252 get sound trigger pcm if present */
7253 audio_extn_sound_trigger_check_and_get_session(in);
7254
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307255 lock_input_stream(in);
7256 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7257 pthread_mutex_lock(&adev->lock);
7258 in->card_status = adev->card_status;
7259 pthread_mutex_unlock(&adev->lock);
7260 pthread_mutex_unlock(&in->lock);
7261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007262 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007263 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007265
7266err_open:
7267 free(in);
7268 *stream_in = NULL;
7269 return ret;
7270}
7271
7272static void adev_close_input_stream(struct audio_hw_device *dev,
7273 struct audio_stream_in *stream)
7274{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007275 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007276 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007277 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307278
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307279 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007280
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307281 // must deregister from sndmonitor first to prevent races
7282 // between the callback and close_stream
7283 audio_extn_snd_mon_unregister_listener(stream);
7284
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307285 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007286 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307287
Pallavid7c7a272018-01-16 11:22:55 +05307288 if (in == NULL) {
7289 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7290 return;
7291 }
7292
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007293 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307294 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007295 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307296 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007297 if (ret != 0)
7298 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7299 __func__, ret);
7300 } else
7301 in_standby(&stream->common);
7302
Revathi Uddarajud2634032017-12-07 14:42:34 +05307303 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007304 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007305 audio_extn_ssr_deinit();
7306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007307
Garmond Leunge2433c32017-09-28 21:51:22 -07007308 if (audio_extn_ffv_get_stream() == in) {
7309 audio_extn_ffv_stream_deinit();
7310 }
7311
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307312 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007313 audio_extn_compr_cap_format_supported(in->config.format))
7314 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307315
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307316 if (audio_extn_cin_attached_usecase(in->usecase))
7317 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007318
Mingming Yinfd7607b2016-01-22 12:48:44 -08007319 if (in->is_st_session) {
7320 ALOGV("%s: sound trigger pcm stop lab", __func__);
7321 audio_extn_sound_trigger_stop_lab(in);
7322 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007323 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307324 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325 return;
7326}
7327
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307328int adev_create_audio_patch(struct audio_hw_device *dev,
7329 unsigned int num_sources,
7330 const struct audio_port_config *sources,
7331 unsigned int num_sinks,
7332 const struct audio_port_config *sinks,
7333 audio_patch_handle_t *handle)
7334{
7335
7336
7337 return audio_extn_hw_loopback_create_audio_patch(dev,
7338 num_sources,
7339 sources,
7340 num_sinks,
7341 sinks,
7342 handle);
7343
7344}
7345
7346int adev_release_audio_patch(struct audio_hw_device *dev,
7347 audio_patch_handle_t handle)
7348{
7349 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7350}
7351
7352int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7353{
7354 return audio_extn_hw_loopback_get_audio_port(dev, config);
7355}
7356
7357int adev_set_audio_port_config(struct audio_hw_device *dev,
7358 const struct audio_port_config *config)
7359{
7360 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7361}
7362
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007363static int adev_dump(const audio_hw_device_t *device __unused,
7364 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007365{
7366 return 0;
7367}
7368
7369static int adev_close(hw_device_t *device)
7370{
7371 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007372
7373 if (!adev)
7374 return 0;
7375
7376 pthread_mutex_lock(&adev_init_lock);
7377
7378 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307379 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007380 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007381 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307382 audio_extn_utils_release_streams_cfg_lists(
7383 &adev->streams_output_cfg_list,
7384 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307385 if (audio_extn_qaf_is_enabled())
7386 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007387 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007388 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007389 free(adev->snd_dev_ref_cnt);
7390 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007391 if (adev->adm_deinit)
7392 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307393 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007394 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307395 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307396 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007397 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307398 if (adev->device_cfg_params) {
7399 free(adev->device_cfg_params);
7400 adev->device_cfg_params = NULL;
7401 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007402 free(device);
7403 adev = NULL;
7404 }
7405 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007407 return 0;
7408}
7409
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007410/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7411 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7412 * just that it _might_ work.
7413 */
7414static int period_size_is_plausible_for_low_latency(int period_size)
7415{
7416 switch (period_size) {
7417 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007418 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007419 case 240:
7420 case 320:
7421 case 480:
7422 return 1;
7423 default:
7424 return 0;
7425 }
7426}
7427
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307428static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7429{
7430 bool is_snd_card_status = false;
7431 bool is_ext_device_status = false;
7432 char value[32];
7433 int card = -1;
7434 card_status_t status;
7435
7436 if (cookie != adev || !parms)
7437 return;
7438
7439 if (!parse_snd_card_status(parms, &card, &status)) {
7440 is_snd_card_status = true;
7441 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7442 is_ext_device_status = true;
7443 } else {
7444 // not a valid event
7445 return;
7446 }
7447
7448 pthread_mutex_lock(&adev->lock);
7449 if (card == adev->snd_card || is_ext_device_status) {
7450 if (is_snd_card_status && adev->card_status != status) {
7451 adev->card_status = status;
7452 platform_snd_card_update(adev->platform, status);
7453 audio_extn_fm_set_parameters(adev, parms);
7454 } else if (is_ext_device_status) {
7455 platform_set_parameters(adev->platform, parms);
7456 }
7457 }
7458 pthread_mutex_unlock(&adev->lock);
7459 return;
7460}
7461
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307462/* out and adev lock held */
7463static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7464{
7465 struct audio_usecase *uc_info;
7466 float left_p;
7467 float right_p;
7468 audio_devices_t devices;
7469
7470 uc_info = get_usecase_from_list(adev, out->usecase);
7471 if (uc_info == NULL) {
7472 ALOGE("%s: Could not find the usecase (%d) in the list",
7473 __func__, out->usecase);
7474 return -EINVAL;
7475 }
7476
7477 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7478 out->usecase, use_case_table[out->usecase]);
7479
7480 if (restore) {
7481 // restore A2DP device for active usecases and unmute if required
7482 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7483 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7484 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7485 select_devices(adev, uc_info->id);
7486 pthread_mutex_lock(&out->compr_mute_lock);
7487 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7488 (out->a2dp_compress_mute)) {
7489 out->a2dp_compress_mute = false;
7490 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7491 }
7492 pthread_mutex_unlock(&out->compr_mute_lock);
7493 }
7494 } else {
7495 // mute compress stream if suspended
7496 pthread_mutex_lock(&out->compr_mute_lock);
7497 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7498 (!out->a2dp_compress_mute)) {
7499 if (!out->standby) {
7500 ALOGD("%s: selecting speaker and muting stream", __func__);
7501 devices = out->devices;
7502 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7503 left_p = out->volume_l;
7504 right_p = out->volume_r;
7505 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7506 compress_pause(out->compr);
7507 out_set_compr_volume(&out->stream, (float)0, (float)0);
7508 out->a2dp_compress_mute = true;
7509 select_devices(adev, out->usecase);
7510 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7511 compress_resume(out->compr);
7512 out->devices = devices;
7513 out->volume_l = left_p;
7514 out->volume_r = right_p;
7515 }
7516 }
7517 pthread_mutex_unlock(&out->compr_mute_lock);
7518 }
7519 ALOGV("%s: exit", __func__);
7520 return 0;
7521}
7522
7523int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7524{
7525 int ret = 0;
7526
7527 lock_output_stream(out);
7528 pthread_mutex_lock(&adev->lock);
7529
7530 ret = check_a2dp_restore_l(adev, out, restore);
7531
7532 pthread_mutex_unlock(&adev->lock);
7533 pthread_mutex_unlock(&out->lock);
7534 return ret;
7535}
7536
Haynes Mathew George01156f92018-04-13 15:29:54 -07007537void adev_on_battery_status_changed(bool charging)
7538{
7539 pthread_mutex_lock(&adev->lock);
7540 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7541 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007542 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007543 pthread_mutex_unlock(&adev->lock);
7544}
7545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007546static int adev_open(const hw_module_t *module, const char *name,
7547 hw_device_t **device)
7548{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307549 int ret;
7550
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007551 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007552 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7553
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007554 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007555 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007556 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007557 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007558 ALOGD("%s: returning existing instance of adev", __func__);
7559 ALOGD("%s: exit", __func__);
7560 pthread_mutex_unlock(&adev_init_lock);
7561 return 0;
7562 }
7563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007564 adev = calloc(1, sizeof(struct audio_device));
7565
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007566 if (!adev) {
7567 pthread_mutex_unlock(&adev_init_lock);
7568 return -ENOMEM;
7569 }
7570
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007571 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7572
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307573#ifdef DYNAMIC_LOG_ENABLED
7574 register_for_dynamic_logging("hal");
7575#endif
7576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007577 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7578 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7579 adev->device.common.module = (struct hw_module_t *)module;
7580 adev->device.common.close = adev_close;
7581
7582 adev->device.init_check = adev_init_check;
7583 adev->device.set_voice_volume = adev_set_voice_volume;
7584 adev->device.set_master_volume = adev_set_master_volume;
7585 adev->device.get_master_volume = adev_get_master_volume;
7586 adev->device.set_master_mute = adev_set_master_mute;
7587 adev->device.get_master_mute = adev_get_master_mute;
7588 adev->device.set_mode = adev_set_mode;
7589 adev->device.set_mic_mute = adev_set_mic_mute;
7590 adev->device.get_mic_mute = adev_get_mic_mute;
7591 adev->device.set_parameters = adev_set_parameters;
7592 adev->device.get_parameters = adev_get_parameters;
7593 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7594 adev->device.open_output_stream = adev_open_output_stream;
7595 adev->device.close_output_stream = adev_close_output_stream;
7596 adev->device.open_input_stream = adev_open_input_stream;
7597 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307598 adev->device.create_audio_patch = adev_create_audio_patch;
7599 adev->device.release_audio_patch = adev_release_audio_patch;
7600 adev->device.get_audio_port = adev_get_audio_port;
7601 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007602 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307603 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007604
7605 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007606 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007607 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007608 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007609 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007610 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007611 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007612 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307613 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007614 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007615 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007616 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007617 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007618 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007619 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307620 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307621 adev->perf_lock_opts[0] = 0x101;
7622 adev->perf_lock_opts[1] = 0x20E;
7623 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007624 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007626 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007627 adev->platform = platform_init(adev);
7628 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007629 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007630 free(adev->snd_dev_ref_cnt);
7631 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007632 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007633 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7634 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007635 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007636 return -EINVAL;
7637 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007638
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307639 if (audio_extn_qaf_is_enabled()) {
7640 ret = audio_extn_qaf_init(adev);
7641 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007642 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307643 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007644 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307645 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7646 *device = NULL;
7647 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307648 return ret;
7649 }
7650
7651 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7652 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7653 }
7654
Eric Laurentc4aef752013-09-12 17:45:53 -07007655 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7656 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7657 if (adev->visualizer_lib == NULL) {
7658 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7659 } else {
7660 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7661 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007662 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007663 "visualizer_hal_start_output");
7664 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007665 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007666 "visualizer_hal_stop_output");
7667 }
7668 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307669 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007670 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007671 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307672 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007673 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007674
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007675 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7676 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7677 if (adev->offload_effects_lib == NULL) {
7678 ALOGE("%s: DLOPEN failed for %s", __func__,
7679 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7680 } else {
7681 ALOGV("%s: DLOPEN successful for %s", __func__,
7682 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7683 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307684 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007685 "offload_effects_bundle_hal_start_output");
7686 adev->offload_effects_stop_output =
7687 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7688 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007689 adev->offload_effects_set_hpx_state =
7690 (int (*)(bool))dlsym(adev->offload_effects_lib,
7691 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307692 adev->offload_effects_get_parameters =
7693 (void (*)(struct str_parms *, struct str_parms *))
7694 dlsym(adev->offload_effects_lib,
7695 "offload_effects_bundle_get_parameters");
7696 adev->offload_effects_set_parameters =
7697 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7698 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007699 }
7700 }
7701
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007702 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7703 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7704 if (adev->adm_lib == NULL) {
7705 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7706 } else {
7707 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7708 adev->adm_init = (adm_init_t)
7709 dlsym(adev->adm_lib, "adm_init");
7710 adev->adm_deinit = (adm_deinit_t)
7711 dlsym(adev->adm_lib, "adm_deinit");
7712 adev->adm_register_input_stream = (adm_register_input_stream_t)
7713 dlsym(adev->adm_lib, "adm_register_input_stream");
7714 adev->adm_register_output_stream = (adm_register_output_stream_t)
7715 dlsym(adev->adm_lib, "adm_register_output_stream");
7716 adev->adm_deregister_stream = (adm_deregister_stream_t)
7717 dlsym(adev->adm_lib, "adm_deregister_stream");
7718 adev->adm_request_focus = (adm_request_focus_t)
7719 dlsym(adev->adm_lib, "adm_request_focus");
7720 adev->adm_abandon_focus = (adm_abandon_focus_t)
7721 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007722 adev->adm_set_config = (adm_set_config_t)
7723 dlsym(adev->adm_lib, "adm_set_config");
7724 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7725 dlsym(adev->adm_lib, "adm_request_focus_v2");
7726 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7727 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7728 adev->adm_on_routing_change = (adm_on_routing_change_t)
7729 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007730 }
7731 }
7732
Mingming Yin514a8bc2014-07-29 15:22:21 -07007733 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007734 //initialize this to false for now,
7735 //this will be set to true through set param
7736 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007737
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007738 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007739 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007740 adev->dsp_bit_width_enforce_mode =
7741 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007742
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307743 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7744 &adev->streams_output_cfg_list,
7745 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007746
Kiran Kandi910e1862013-10-29 13:29:42 -07007747 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007748
7749 char value[PROPERTY_VALUE_MAX];
7750 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007751 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007752 trial = atoi(value);
7753 if (period_size_is_plausible_for_low_latency(trial)) {
7754 pcm_config_low_latency.period_size = trial;
7755 pcm_config_low_latency.start_threshold = trial / 4;
7756 pcm_config_low_latency.avail_min = trial / 4;
7757 configured_low_latency_capture_period_size = trial;
7758 }
7759 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007760 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007761 trial = atoi(value);
7762 if (period_size_is_plausible_for_low_latency(trial)) {
7763 configured_low_latency_capture_period_size = trial;
7764 }
7765 }
7766
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007767 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7768
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007769 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007770 af_period_multiplier = atoi(value);
7771 if (af_period_multiplier < 0)
7772 af_period_multiplier = 2;
7773 else if (af_period_multiplier > 4)
7774 af_period_multiplier = 4;
7775
7776 ALOGV("new period_multiplier = %d", af_period_multiplier);
7777 }
7778
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007779 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007780 pthread_mutex_unlock(&adev_init_lock);
7781
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007782 if (adev->adm_init)
7783 adev->adm_data = adev->adm_init();
7784
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307785 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307786 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007787 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307788
7789 audio_extn_snd_mon_init();
7790 pthread_mutex_lock(&adev->lock);
7791 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7792 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07007793 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
7794 /*
7795 * if the battery state callback happens before charging can be queried,
7796 * it will be guarded with the adev->lock held in the cb function and so
7797 * the callback value will reflect the latest state
7798 */
7799 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307800 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08007801 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
7802 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307803 /* Allocate memory for Device config params */
7804 adev->device_cfg_params = (struct audio_device_config_param*)
7805 calloc(platform_get_max_codec_backend(),
7806 sizeof(struct audio_device_config_param));
7807 if (adev->device_cfg_params == NULL)
7808 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307809
Eric Laurent994a6932013-07-17 11:51:42 -07007810 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007811 return 0;
7812}
7813
7814static struct hw_module_methods_t hal_module_methods = {
7815 .open = adev_open,
7816};
7817
7818struct audio_module HAL_MODULE_INFO_SYM = {
7819 .common = {
7820 .tag = HARDWARE_MODULE_TAG,
7821 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7822 .hal_api_version = HARDWARE_HAL_API_VERSION,
7823 .id = AUDIO_HARDWARE_MODULE_ID,
7824 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007825 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007826 .methods = &hal_module_methods,
7827 },
7828};