blob: 3e3f72fb278ac0c1610f4561e565a49c735f8298 [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 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001186 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001187 audio_extn_sound_trigger_update_device_status(snd_device,
1188 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301189 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001190 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193 return 0;
1194}
1195
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001196/*
1197 legend:
1198 uc - existing usecase
1199 new_uc - new usecase
1200 d1, d11, d2 - SND_DEVICE enums
1201 a1, a2 - corresponding ANDROID device enums
1202 B1, B2 - backend strings
1203
1204case 1
1205 uc->dev d1 (a1) B1
1206 new_uc->dev d1 (a1), d2 (a2) B1, B2
1207
1208 resolution: disable and enable uc->dev on d1
1209
1210case 2
1211 uc->dev d1 (a1) B1
1212 new_uc->dev d11 (a1) B1
1213
1214 resolution: need to switch uc since d1 and d11 are related
1215 (e.g. speaker and voice-speaker)
1216 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1217
1218case 3
1219 uc->dev d1 (a1) B1
1220 new_uc->dev d2 (a2) B2
1221
1222 resolution: no need to switch uc
1223
1224case 4
1225 uc->dev d1 (a1) B1
1226 new_uc->dev d2 (a2) B1
1227
1228 resolution: disable enable uc-dev on d2 since backends match
1229 we cannot enable two streams on two different devices if they
1230 share the same backend. e.g. if offload is on speaker device using
1231 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1232 using the same backend, offload must also be switched to voice-handset.
1233
1234case 5
1235 uc->dev d1 (a1) B1
1236 new_uc->dev d1 (a1), d2 (a2) B1
1237
1238 resolution: disable enable uc-dev on d2 since backends match
1239 we cannot enable two streams on two different devices if they
1240 share the same backend.
1241
1242case 6
1243 uc->dev d1 (a1) B1
1244 new_uc->dev d2 (a1) B2
1245
1246 resolution: no need to switch
1247
1248case 7
1249 uc->dev d1 (a1), d2 (a2) B1, B2
1250 new_uc->dev d1 (a1) B1
1251
1252 resolution: no need to switch
1253
Zhou Song4ba65882018-07-09 14:48:07 +08001254case 8
1255 uc->dev d1 (a1) B1
1256 new_uc->dev d11 (a1), d2 (a2) B1, B2
1257 resolution: compared to case 1, for this case, d1 and d11 are related
1258 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001259*/
1260static snd_device_t derive_playback_snd_device(void * platform,
1261 struct audio_usecase *uc,
1262 struct audio_usecase *new_uc,
1263 snd_device_t new_snd_device)
1264{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301265 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001266
1267 snd_device_t d1 = uc->out_snd_device;
1268 snd_device_t d2 = new_snd_device;
1269
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301270 switch (uc->type) {
1271 case TRANSCODE_LOOPBACK :
1272 a1 = uc->stream.inout->out_config.devices;
1273 a2 = new_uc->stream.inout->out_config.devices;
1274 break;
1275 default :
1276 a1 = uc->stream.out->devices;
1277 a2 = new_uc->stream.out->devices;
1278 break;
1279 }
1280
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001281 // Treat as a special case when a1 and a2 are not disjoint
1282 if ((a1 != a2) && (a1 & a2)) {
1283 snd_device_t d3[2];
1284 int num_devices = 0;
1285 int ret = platform_split_snd_device(platform,
1286 popcount(a1) > 1 ? d1 : d2,
1287 &num_devices,
1288 d3);
1289 if (ret < 0) {
1290 if (ret != -ENOSYS) {
1291 ALOGW("%s failed to split snd_device %d",
1292 __func__,
1293 popcount(a1) > 1 ? d1 : d2);
1294 }
1295 goto end;
1296 }
1297
1298 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1299 // But if it does happen, we need to give priority to d2 if
1300 // the combo devices active on the existing usecase share a backend.
1301 // This is because we cannot have a usecase active on a combo device
1302 // and a new usecase requests one device in this combo pair.
1303 if (platform_check_backends_match(d3[0], d3[1])) {
1304 return d2; // case 5
1305 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001306 // check if d1 is related to any of d3's
1307 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001308 return d1; // case 1
1309 else
1310 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001311 }
1312 } else {
1313 if (platform_check_backends_match(d1, d2)) {
1314 return d2; // case 2, 4
1315 } else {
1316 return d1; // case 6, 3
1317 }
1318 }
1319
1320end:
1321 return d2; // return whatever was calculated before.
1322}
1323
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001324static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301325 struct audio_usecase *uc_info,
1326 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327{
1328 struct listnode *node;
1329 struct audio_usecase *usecase;
1330 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301331 snd_device_t uc_derive_snd_device;
1332 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001333 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1334 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001335 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301336 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 /*
1338 * This function is to make sure that all the usecases that are active on
1339 * the hardware codec backend are always routed to any one device that is
1340 * handled by the hardware codec.
1341 * For example, if low-latency and deep-buffer usecases are currently active
1342 * on speaker and out_set_parameters(headset) is received on low-latency
1343 * output, then we have to make sure deep-buffer is also switched to headset,
1344 * because of the limitation that both the devices cannot be enabled
1345 * at the same time as they share the same backend.
1346 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001347 /*
1348 * This call is to check if we need to force routing for a particular stream
1349 * If there is a backend configuration change for the device when a
1350 * new stream starts, then ADM needs to be closed and re-opened with the new
1351 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001352 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001353 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001354 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1355 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301356 /* For a2dp device reconfigure all active sessions
1357 * with new AFE encoder format based on a2dp state
1358 */
1359 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1360 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1361 audio_extn_a2dp_is_force_device_switch()) {
1362 force_routing = true;
1363 force_restart_session = true;
1364 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301365 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1366
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001367 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001368 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001369 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001370 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1371 switch_device[i] = false;
1372
1373 list_for_each(node, &adev->usecase_list) {
1374 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001375
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301376 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1377 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301378 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301379 platform_get_snd_device_name(usecase->out_snd_device),
1380 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301381 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1382 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1383 usecase, uc_info, snd_device);
1384 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1385 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1386 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1387 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001388 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301389 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1390 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1391 ((force_restart_session) ||
1392 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301393 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1394 __func__, use_case_table[usecase->id],
1395 platform_get_snd_device_name(usecase->out_snd_device));
1396 disable_audio_route(adev, usecase);
1397 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301398 /* Enable existing usecase on derived playback device */
1399 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301400 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301401 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001402 }
1403 }
1404
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301405 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1406 num_uc_to_switch);
1407
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001409 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301411 /* Make sure the previous devices to be disabled first and then enable the
1412 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413 list_for_each(node, &adev->usecase_list) {
1414 usecase = node_to_item(node, struct audio_usecase, list);
1415 if (switch_device[usecase->id]) {
Aniket Kumar Lata25b344d2018-09-25 19:00:35 -07001416 /* Check if sound device to be switched can be split and if any
1417 of the split devices match with derived sound device */
1418 platform_split_snd_device(adev->platform, usecase->out_snd_device,
1419 &num_devices, split_snd_devices);
1420 if (num_devices > 1) {
1421 for (i = 0; i < num_devices; i++) {
1422 /* Disable devices that do not match with derived sound device */
1423 if (split_snd_devices[i] != derive_snd_device[usecase->id]) {
1424 disable_snd_device(adev, split_snd_devices[i]);
1425 }
1426 }
1427 } else {
1428 disable_snd_device(adev, usecase->out_snd_device);
1429 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001430 }
1431 }
1432
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001433 list_for_each(node, &adev->usecase_list) {
1434 usecase = node_to_item(node, struct audio_usecase, list);
1435 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301436 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001437 }
1438 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 /* Re-route all the usecases on the shared backend other than the
1441 specified usecase to new snd devices */
1442 list_for_each(node, &adev->usecase_list) {
1443 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301444 /* Update the out_snd_device only before enabling the audio route */
1445 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301446 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301447 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301448 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301449 use_case_table[usecase->id],
1450 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001451 /* Update voc calibration before enabling VoIP route */
1452 if (usecase->type == VOIP_CALL)
1453 status = platform_switch_voice_call_device_post(adev->platform,
1454 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001455 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301456 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001457 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1458 out_set_voip_volume(&usecase->stream.out->stream,
1459 usecase->stream.out->volume_l,
1460 usecase->stream.out->volume_r);
1461 }
Yidong Huang7939a3b2018-01-23 17:32:30 +08001462 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1463 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1464 if (parms)
1465 audio_extn_fm_set_parameters(adev, parms);
1466 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301467 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468 }
1469 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 }
1471}
1472
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301473static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001474 struct audio_usecase *uc_info,
1475 snd_device_t snd_device)
1476{
1477 struct listnode *node;
1478 struct audio_usecase *usecase;
1479 bool switch_device[AUDIO_USECASE_MAX];
1480 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301481 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001482 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001483
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301484 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1485 snd_device);
1486 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301487
1488 /*
1489 * Make sure out devices is checked against out codec backend device and
1490 * also in devices against in codec backend. Checking out device against in
1491 * codec backend or vice versa causes issues.
1492 */
1493 if (uc_info->type == PCM_CAPTURE)
1494 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001495 /*
1496 * This function is to make sure that all the active capture usecases
1497 * are always routed to the same input sound device.
1498 * For example, if audio-record and voice-call usecases are currently
1499 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1500 * is received for voice call then we have to make sure that audio-record
1501 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1502 * because of the limitation that two devices cannot be enabled
1503 * at the same time if they share the same backend.
1504 */
1505 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1506 switch_device[i] = false;
1507
1508 list_for_each(node, &adev->usecase_list) {
1509 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301510 /*
1511 * TODO: Enhance below condition to handle BT sco/USB multi recording
1512 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001513 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001514 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301515 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301516 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301517 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301518 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001519 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001520 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1521 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001522 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001523 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001524 switch_device[usecase->id] = true;
1525 num_uc_to_switch++;
1526 }
1527 }
1528
1529 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001530 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001531
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301532 /* Make sure the previous devices to be disabled first and then enable the
1533 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001534 list_for_each(node, &adev->usecase_list) {
1535 usecase = node_to_item(node, struct audio_usecase, list);
1536 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001537 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001538 }
1539 }
1540
1541 list_for_each(node, &adev->usecase_list) {
1542 usecase = node_to_item(node, struct audio_usecase, list);
1543 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001544 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001545 }
1546 }
1547
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001548 /* Re-route all the usecases on the shared backend other than the
1549 specified usecase to new snd devices */
1550 list_for_each(node, &adev->usecase_list) {
1551 usecase = node_to_item(node, struct audio_usecase, list);
1552 /* Update the in_snd_device only before enabling the audio route */
1553 if (switch_device[usecase->id] ) {
1554 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001555 if (usecase->type != VOICE_CALL) {
1556 /* Update voc calibration before enabling VoIP route */
1557 if (usecase->type == VOIP_CALL)
1558 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001559 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001560 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301561 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001562 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001563 }
1564 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001565 }
1566}
1567
Mingming Yin3a941d42016-02-17 18:08:05 -08001568static void reset_hdmi_sink_caps(struct stream_out *out) {
1569 int i = 0;
1570
1571 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1572 out->supported_channel_masks[i] = 0;
1573 }
1574 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1575 out->supported_formats[i] = 0;
1576 }
1577 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1578 out->supported_sample_rates[i] = 0;
1579 }
1580}
1581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001583static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584{
Mingming Yin3a941d42016-02-17 18:08:05 -08001585 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001586 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587
Mingming Yin3a941d42016-02-17 18:08:05 -08001588 reset_hdmi_sink_caps(out);
1589
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001590 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001591 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001592 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001593 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001594 }
1595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001598 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001599 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001600 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1601 case 6:
1602 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1603 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1604 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1605 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1606 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1607 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608 break;
1609 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001610 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001611 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 break;
1613 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001614
1615 // check channel format caps
1616 i = 0;
1617 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1618 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1619 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1620 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1621 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1622 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1623 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1624 }
1625
Ben Romberger1aaaf862017-04-06 17:49:46 -07001626 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1627 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1628 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1629 }
1630
Mingming Yin3a941d42016-02-17 18:08:05 -08001631 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1632 ALOGV(":%s HDMI supports DTS format", __func__);
1633 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1634 }
1635
1636 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1637 ALOGV(":%s HDMI supports DTS HD format", __func__);
1638 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1639 }
1640
Naresh Tanniru928f0862017-04-07 16:44:23 -07001641 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1642 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1643 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1644 }
1645
Mingming Yin3a941d42016-02-17 18:08:05 -08001646
1647 // check sample rate caps
1648 i = 0;
1649 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1650 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1651 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1652 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1653 }
1654 }
1655
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001656 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657}
1658
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001659static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1660 uint32_t *supported_sample_rates __unused,
1661 uint32_t max_rates __unused)
1662{
1663 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1664 supported_sample_rates,
1665 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301666 ssize_t i = 0;
1667
1668 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001669 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1670 supported_sample_rates[i]);
1671 }
1672 return count;
1673}
1674
1675static inline int read_usb_sup_channel_masks(bool is_playback,
1676 audio_channel_mask_t *supported_channel_masks,
1677 uint32_t max_masks)
1678{
1679 int channels = audio_extn_usb_get_max_channels(is_playback);
1680 int channel_count;
1681 uint32_t num_masks = 0;
1682 if (channels > MAX_HIFI_CHANNEL_COUNT)
1683 channels = MAX_HIFI_CHANNEL_COUNT;
1684
1685 if (is_playback) {
1686 // For playback we never report mono because the framework always outputs stereo
1687 channel_count = DEFAULT_CHANNEL_COUNT;
1688 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1689 // above 2 but we want indexed masks here. So we
1690 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1691 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1692 }
1693 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1694 supported_channel_masks[num_masks++] =
1695 audio_channel_mask_for_index_assignment_from_count(channel_count);
1696 }
1697 } else {
1698 // For capture we report all supported channel masks from 1 channel up.
1699 channel_count = MIN_CHANNEL_COUNT;
1700 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1701 // indexed mask
1702 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1703 supported_channel_masks[num_masks++] =
1704 audio_channel_in_mask_from_count(channel_count);
1705 }
1706 }
1707 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1708 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1709 return num_masks;
1710}
1711
1712static inline int read_usb_sup_formats(bool is_playback __unused,
1713 audio_format_t *supported_formats,
1714 uint32_t max_formats __unused)
1715{
1716 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1717 switch (bitwidth) {
1718 case 24:
1719 // XXX : usb.c returns 24 for s24 and s24_le?
1720 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1721 break;
1722 case 32:
1723 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1724 break;
1725 case 16:
1726 default :
1727 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1728 break;
1729 }
1730 ALOGV("%s: %s supported format %d", __func__,
1731 is_playback ? "P" : "C", bitwidth);
1732 return 1;
1733}
1734
1735static inline int read_usb_sup_params_and_compare(bool is_playback,
1736 audio_format_t *format,
1737 audio_format_t *supported_formats,
1738 uint32_t max_formats,
1739 audio_channel_mask_t *mask,
1740 audio_channel_mask_t *supported_channel_masks,
1741 uint32_t max_masks,
1742 uint32_t *rate,
1743 uint32_t *supported_sample_rates,
1744 uint32_t max_rates) {
1745 int ret = 0;
1746 int num_formats;
1747 int num_masks;
1748 int num_rates;
1749 int i;
1750
1751 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1752 max_formats);
1753 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1754 max_masks);
1755
1756 num_rates = read_usb_sup_sample_rates(is_playback,
1757 supported_sample_rates, max_rates);
1758
1759#define LUT(table, len, what, dflt) \
1760 for (i=0; i<len && (table[i] != what); i++); \
1761 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1762
1763 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1764 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1765 LUT(supported_sample_rates, num_rates, *rate, 0);
1766
1767#undef LUT
1768 return ret < 0 ? -EINVAL : 0; // HACK TBD
1769}
1770
Alexy Josephb1379942016-01-29 15:49:38 -08001771audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001772 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001773{
1774 struct audio_usecase *usecase;
1775 struct listnode *node;
1776
1777 list_for_each(node, &adev->usecase_list) {
1778 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001779 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001780 ALOGV("%s: usecase id %d", __func__, usecase->id);
1781 return usecase->id;
1782 }
1783 }
1784 return USECASE_INVALID;
1785}
1786
Alexy Josephb1379942016-01-29 15:49:38 -08001787struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001788 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789{
1790 struct audio_usecase *usecase;
1791 struct listnode *node;
1792
1793 list_for_each(node, &adev->usecase_list) {
1794 usecase = node_to_item(node, struct audio_usecase, list);
1795 if (usecase->id == uc_id)
1796 return usecase;
1797 }
1798 return NULL;
1799}
1800
Dhananjay Kumard4833242016-10-06 22:09:12 +05301801struct stream_in *get_next_active_input(const struct audio_device *adev)
1802{
1803 struct audio_usecase *usecase;
1804 struct listnode *node;
1805
1806 list_for_each_reverse(node, &adev->usecase_list) {
1807 usecase = node_to_item(node, struct audio_usecase, list);
1808 if (usecase->type == PCM_CAPTURE)
1809 return usecase->stream.in;
1810 }
1811 return NULL;
1812}
1813
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301814/*
1815 * is a true native playback active
1816 */
1817bool audio_is_true_native_stream_active(struct audio_device *adev)
1818{
1819 bool active = false;
1820 int i = 0;
1821 struct listnode *node;
1822
1823 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1824 ALOGV("%s:napb: not in true mode or non hdphones device",
1825 __func__);
1826 active = false;
1827 goto exit;
1828 }
1829
1830 list_for_each(node, &adev->usecase_list) {
1831 struct audio_usecase *uc;
1832 uc = node_to_item(node, struct audio_usecase, list);
1833 struct stream_out *curr_out =
1834 (struct stream_out*) uc->stream.out;
1835
1836 if (curr_out && PCM_PLAYBACK == uc->type) {
1837 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1838 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1839 uc->id, curr_out->sample_rate,
1840 curr_out->bit_width,
1841 platform_get_snd_device_name(uc->out_snd_device));
1842
1843 if (is_offload_usecase(uc->id) &&
1844 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1845 active = true;
1846 ALOGD("%s:napb:native stream detected", __func__);
1847 }
1848 }
1849 }
1850exit:
1851 return active;
1852}
1853
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001854uint32_t adev_get_dsp_bit_width_enforce_mode()
1855{
1856 if (adev == NULL) {
1857 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1858 return 0;
1859 }
1860 return adev->dsp_bit_width_enforce_mode;
1861}
1862
1863static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1864{
1865 char value[PROPERTY_VALUE_MAX];
1866 int trial;
1867 uint32_t dsp_bit_width_enforce_mode = 0;
1868
1869 if (!mixer) {
1870 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1871 __func__);
1872 return 0;
1873 }
1874
1875 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1876 value, NULL) > 0) {
1877 trial = atoi(value);
1878 switch (trial) {
1879 case 16:
1880 dsp_bit_width_enforce_mode = 16;
1881 break;
1882 case 24:
1883 dsp_bit_width_enforce_mode = 24;
1884 break;
1885 case 32:
1886 dsp_bit_width_enforce_mode = 32;
1887 break;
1888 default:
1889 dsp_bit_width_enforce_mode = 0;
1890 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1891 break;
1892 }
1893 }
1894
1895 return dsp_bit_width_enforce_mode;
1896}
1897
1898static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1899 uint32_t enforce_mode,
1900 bool enable)
1901{
1902 struct mixer_ctl *ctl = NULL;
1903 const char *mixer_ctl_name = "ASM Bit Width";
1904 uint32_t asm_bit_width_mode = 0;
1905
1906 if (enforce_mode == 0) {
1907 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1908 return;
1909 }
1910
1911 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1912 if (!ctl) {
1913 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1914 __func__, mixer_ctl_name);
1915 return;
1916 }
1917
1918 if (enable)
1919 asm_bit_width_mode = enforce_mode;
1920 else
1921 asm_bit_width_mode = 0;
1922
1923 ALOGV("%s DSP bit width feature status is %d width=%d",
1924 __func__, enable, asm_bit_width_mode);
1925 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1926 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1927 asm_bit_width_mode);
1928
1929 return;
1930}
1931
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301932/*
1933 * if native DSD playback active
1934 */
1935bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1936{
1937 bool active = false;
1938 struct listnode *node = NULL;
1939 struct audio_usecase *uc = NULL;
1940 struct stream_out *curr_out = NULL;
1941
1942 list_for_each(node, &adev->usecase_list) {
1943 uc = node_to_item(node, struct audio_usecase, list);
1944 curr_out = (struct stream_out*) uc->stream.out;
1945
1946 if (curr_out && PCM_PLAYBACK == uc->type &&
1947 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1948 active = true;
1949 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301950 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301951 }
1952 }
1953 return active;
1954}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301955
1956static bool force_device_switch(struct audio_usecase *usecase)
1957{
1958 bool ret = false;
1959 bool is_it_true_mode = false;
1960
Zhou Song30f2c3e2018-02-08 14:02:15 +08001961 if (usecase->type == PCM_CAPTURE ||
1962 usecase->type == TRANSCODE_LOOPBACK) {
1963 return false;
1964 }
1965
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001966 if(usecase->stream.out == NULL) {
1967 ALOGE("%s: stream.out is NULL", __func__);
1968 return false;
1969 }
1970
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301971 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001972 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1973 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1974 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301975 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1976 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1977 (!is_it_true_mode && adev->native_playback_enabled)){
1978 ret = true;
1979 ALOGD("napb: time to toggle native mode");
1980 }
1981 }
1982
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301983 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301984 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1985 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001986 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301987 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301988 ALOGD("Force a2dp device switch to update new encoder config");
1989 ret = true;
1990 }
1991
Manish Dewangan671a4202017-08-18 17:30:46 +05301992 if (usecase->stream.out->stream_config_changed) {
1993 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1994 return true;
1995 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301996 return ret;
1997}
1998
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301999bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2000{
2001 bool ret=false;
2002 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2003 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2004 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2005 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2006 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2007 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2008 ret = true;
2009
2010 return ret;
2011}
2012
2013bool is_a2dp_device(snd_device_t out_snd_device)
2014{
2015 bool ret=false;
2016 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2017 ret = true;
2018
2019 return ret;
2020}
2021
2022bool is_bt_soc_on(struct audio_device *adev)
2023{
2024 struct mixer_ctl *ctl;
2025 char *mixer_ctl_name = "BT SOC status";
2026 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2027 bool bt_soc_status = true;
2028 if (!ctl) {
2029 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2030 __func__, mixer_ctl_name);
2031 /*This is to ensure we dont break targets which dont have the kernel change*/
2032 return true;
2033 }
2034 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2035 ALOGD("BT SOC status: %d",bt_soc_status);
2036 return bt_soc_status;
2037}
2038
2039int out_standby_l(struct audio_stream *stream);
2040
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002041int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002043 snd_device_t out_snd_device = SND_DEVICE_NONE;
2044 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002045 struct audio_usecase *usecase = NULL;
2046 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002047 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002048 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302049 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002050 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002051 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002052 audio_devices_t audio_device;
2053 audio_channel_mask_t channel_mask;
2054 int sample_rate;
2055 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302057 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 usecase = get_usecase_from_list(adev, uc_id);
2060 if (usecase == NULL) {
2061 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2062 return -EINVAL;
2063 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002065 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002066 (usecase->type == VOIP_CALL) ||
2067 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302068 if(usecase->stream.out == NULL) {
2069 ALOGE("%s: stream.out is NULL", __func__);
2070 return -EINVAL;
2071 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002072 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002073 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002074 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302076 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2077 if (usecase->stream.inout == NULL) {
2078 ALOGE("%s: stream.inout is NULL", __func__);
2079 return -EINVAL;
2080 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302081 stream_out.devices = usecase->stream.inout->out_config.devices;
2082 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2083 stream_out.format = usecase->stream.inout->out_config.format;
2084 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2085 out_snd_device = platform_get_output_snd_device(adev->platform,
2086 &stream_out);
2087 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302088 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002089 } else {
2090 /*
2091 * If the voice call is active, use the sound devices of voice call usecase
2092 * so that it would not result any device switch. All the usecases will
2093 * be switched to new device when select_devices() is called for voice call
2094 * usecase. This is to avoid switching devices for voice call when
2095 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002096 * choose voice call device only if the use case device is
2097 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002098 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002099 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002100 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002101 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002102 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2103 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302104 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2105 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002106 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002107 in_snd_device = vc_usecase->in_snd_device;
2108 out_snd_device = vc_usecase->out_snd_device;
2109 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002110 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002111 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002112 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002113 if ((voip_usecase != NULL) &&
2114 (usecase->type == PCM_PLAYBACK) &&
2115 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002116 out_snd_device_backend_match = platform_check_backends_match(
2117 voip_usecase->out_snd_device,
2118 platform_get_output_snd_device(
2119 adev->platform,
2120 usecase->stream.out));
2121 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002122 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002123 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2124 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002125 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002126 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002127 in_snd_device = voip_usecase->in_snd_device;
2128 out_snd_device = voip_usecase->out_snd_device;
2129 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002130 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002131 hfp_ucid = audio_extn_hfp_get_usecase();
2132 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002133 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002134 in_snd_device = hfp_usecase->in_snd_device;
2135 out_snd_device = hfp_usecase->out_snd_device;
2136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002137 }
2138 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302139 if (usecase->stream.out == NULL) {
2140 ALOGE("%s: stream.out is NULL", __func__);
2141 return -EINVAL;
2142 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002143 usecase->devices = usecase->stream.out->devices;
2144 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002145 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002146 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002147 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002148 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2149 if (voip_usecase == NULL)
2150 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2151
2152 if ((usecase->stream.out != NULL &&
2153 voip_usecase != NULL &&
2154 usecase->stream.out->usecase == voip_usecase->id) &&
2155 adev->active_input &&
2156 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002157 select_devices(adev, adev->active_input->usecase);
2158 }
2159 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302161 if (usecase->stream.in == NULL) {
2162 ALOGE("%s: stream.in is NULL", __func__);
2163 return -EINVAL;
2164 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002165 usecase->devices = usecase->stream.in->device;
2166 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002167 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002168 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002169 if (adev->active_input &&
2170 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302171 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002172 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2173 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2174 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2175 out_device = voip_usecase->stream.out->devices;
2176 else if (adev->primary_output && !adev->primary_output->standby)
2177 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002178 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002179 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2180 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002181 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002182 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002183 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184 }
2185 }
2186
2187 if (out_snd_device == usecase->out_snd_device &&
2188 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302189
2190 if (!force_device_switch(usecase))
2191 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 }
2193
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302194 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2195 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2196 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2197 return 0;
2198 }
2199
sangwoobc677242013-08-08 16:53:43 +09002200 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002201 out_snd_device, platform_get_snd_device_name(out_snd_device),
2202 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 /*
2205 * Limitation: While in call, to do a device switch we need to disable
2206 * and enable both RX and TX devices though one of them is same as current
2207 * device.
2208 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002209 if ((usecase->type == VOICE_CALL) &&
2210 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2211 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002212 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002213 }
2214
2215 if (((usecase->type == VOICE_CALL) ||
2216 (usecase->type == VOIP_CALL)) &&
2217 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2218 /* Disable sidetone only if voice/voip call already exists */
2219 if (voice_is_call_state_active(adev) ||
2220 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002221 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002222
2223 /* Disable aanc only if voice call exists */
2224 if (voice_is_call_state_active(adev))
2225 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002226 }
2227
Zhou Songc66eb7e2017-08-08 18:29:07 +08002228 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302229 (!audio_extn_a2dp_is_ready())) {
2230 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002231 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302232 }
2233
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002234 /* Disable current sound devices */
2235 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002236 disable_audio_route(adev, usecase);
2237 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 }
2239
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002240 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002241 disable_audio_route(adev, usecase);
2242 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 }
2244
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002245 /* Applicable only on the targets that has external modem.
2246 * New device information should be sent to modem before enabling
2247 * the devices to reduce in-call device switch time.
2248 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002249 if ((usecase->type == VOICE_CALL) &&
2250 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2251 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002252 status = platform_switch_voice_call_enable_device_config(adev->platform,
2253 out_snd_device,
2254 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002255 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002256
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 /* Enable new sound devices */
2258 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002259 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302260 if (platform_check_codec_asrc_support(adev->platform))
2261 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002262 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 }
2264
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002265 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302266 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002267 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002268 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002269
Avinash Vaish71a8b972014-07-24 15:36:33 +05302270 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002271 status = platform_switch_voice_call_device_post(adev->platform,
2272 out_snd_device,
2273 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302274 enable_audio_route_for_voice_usecases(adev, usecase);
2275 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002276
sangwoo170731f2013-06-08 15:36:36 +09002277 usecase->in_snd_device = in_snd_device;
2278 usecase->out_snd_device = out_snd_device;
2279
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302280 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2281 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302282 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002283 if ((24 == usecase->stream.out->bit_width) &&
2284 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2285 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2286 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2287 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2288 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2289 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2290 /*
2291 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2292 * configured device sample rate, if not update the COPP rate to be equal to the
2293 * device sample rate, else open COPP at stream sample rate
2294 */
2295 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2296 usecase->stream.out->sample_rate,
2297 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302298 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2299 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002300 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2301 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2302 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2303 }
2304
Weiyin Jiang5d608082018-02-01 17:24:33 +08002305 /* Cache stream information to be notified to gef clients */
2306 audio_device = usecase->stream.out->devices;
2307 channel_mask = usecase->stream.out->channel_mask;
2308 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2309 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302310 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002311 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002312
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002313 /* If input stream is already running then effect needs to be
2314 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002315 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2316 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002317 check_and_enable_effect(adev);
2318
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002319 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002320 /* Enable aanc only if voice call exists */
2321 if (voice_is_call_state_active(adev))
2322 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2323
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002324 /* Enable sidetone only if other voice/voip call already exists */
2325 if (voice_is_call_state_active(adev) ||
2326 voice_extn_compress_voip_is_started(adev))
2327 voice_set_sidetone(adev, out_snd_device, true);
2328 }
2329
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002330 /* Applicable only on the targets that has external modem.
2331 * Enable device command should be sent to modem only after
2332 * enabling voice call mixer controls
2333 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002334 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002335 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2336 out_snd_device,
2337 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302338
2339 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2340
2341 if (usecase->type == VOIP_CALL) {
2342 if (adev->active_input != NULL &&
2343 !adev->active_input->standby) {
2344 if (is_bt_soc_on(adev) == false){
2345 ALOGD("BT SCO MIC disconnected while in connection");
2346 if (adev->active_input->pcm != NULL)
2347 pcm_stop(adev->active_input->pcm);
2348 }
2349 }
2350 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2351 && usecase->stream.out->started) {
2352 if (is_bt_soc_on(adev) == false) {
2353 ALOGD("BT SCO/A2DP disconnected while in connection");
2354 out_standby_l(&usecase->stream.out->stream.common);
2355 }
2356 }
2357 } else if ((usecase->stream.out != NULL) &&
2358 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2359 usecase->stream.out->started) {
2360 if (is_bt_soc_on(adev) == false) {
2361 ALOGD("BT SCO/A2dp disconnected while in connection");
2362 out_standby_l(&usecase->stream.out->stream.common);
2363 }
2364 }
2365 }
2366
Weiyin Jiang5d608082018-02-01 17:24:33 +08002367 /* Notify device change info to effect clients registered
2368 * NOTE: device lock has to be unlock temporarily here.
2369 * To the worst case, we notify stale info to clients.
2370 */
2371 if (usecase->type == PCM_PLAYBACK) {
2372 pthread_mutex_unlock(&adev->lock);
2373 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2374 pthread_mutex_lock(&adev->lock);
2375 }
2376
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302377 ALOGD("%s: done",__func__);
2378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 return status;
2380}
2381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382static int stop_input_stream(struct stream_in *in)
2383{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302384 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302386
2387 if (in == NULL) {
2388 ALOGE("%s: stream_in ptr is NULL", __func__);
2389 return -EINVAL;
2390 }
2391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 struct audio_device *adev = in->dev;
2393
Eric Laurent994a6932013-07-17 11:51:42 -07002394 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002395 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396 uc_info = get_usecase_from_list(adev, in->usecase);
2397 if (uc_info == NULL) {
2398 ALOGE("%s: Could not find the usecase (%d) in the list",
2399 __func__, in->usecase);
2400 return -EINVAL;
2401 }
2402
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002403 /* Close in-call recording streams */
2404 voice_check_and_stop_incall_rec_usecase(adev, in);
2405
Eric Laurent150dbfe2013-02-27 14:31:02 -08002406 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002407 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002408
2409 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002410 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002412 list_remove(&uc_info->list);
2413 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002415 adev->active_input = get_next_active_input(adev);
2416
Eric Laurent994a6932013-07-17 11:51:42 -07002417 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418 return ret;
2419}
2420
2421int start_input_stream(struct stream_in *in)
2422{
2423 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002424 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302426
2427 if (in == NULL) {
2428 ALOGE("%s: stream_in ptr is NULL", __func__);
2429 return -EINVAL;
2430 }
2431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002433 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002434 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435
Mingming Yin2664a5b2015-09-03 10:53:11 -07002436 if (get_usecase_from_list(adev, usecase) == NULL)
2437 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302438 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2439 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002440
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302441 if (CARD_STATUS_OFFLINE == in->card_status||
2442 CARD_STATUS_OFFLINE == adev->card_status) {
2443 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302444 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302445 goto error_config;
2446 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302447
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302448 if (audio_is_bluetooth_sco_device(in->device)) {
2449 if (!adev->bt_sco_on) {
2450 ALOGE("%s: SCO profile is not ready, return error", __func__);
2451 ret = -EIO;
2452 goto error_config;
2453 }
2454 }
2455
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002456 /* Check if source matches incall recording usecase criteria */
2457 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2458 if (ret)
2459 goto error_config;
2460 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002461 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2462
2463 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2464 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2465 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002466 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002467 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002468
Eric Laurentb23d5282013-05-14 15:27:20 -07002469 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 if (in->pcm_device_id < 0) {
2471 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2472 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002473 ret = -EINVAL;
2474 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002476
2477 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002479
2480 if (!uc_info) {
2481 ret = -ENOMEM;
2482 goto error_config;
2483 }
2484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 uc_info->id = in->usecase;
2486 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002487 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002488 uc_info->devices = in->device;
2489 uc_info->in_snd_device = SND_DEVICE_NONE;
2490 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002492 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302493 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2494 adev->perf_lock_opts,
2495 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002496 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497
Haynes Mathew George16081042017-05-31 17:16:49 -07002498 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302499 ret = audio_extn_cin_start_input_stream(in);
2500 if (ret)
2501 goto error_open;
2502 else
2503 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002504 }
2505
Haynes Mathew George16081042017-05-31 17:16:49 -07002506 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002507 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002508 ALOGE("%s: pcm stream not ready", __func__);
2509 goto error_open;
2510 }
2511 ret = pcm_start(in->pcm);
2512 if (ret < 0) {
2513 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2514 goto error_open;
2515 }
2516 } else {
2517 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2518 unsigned int pcm_open_retry_count = 0;
2519
2520 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2521 flags |= PCM_MMAP | PCM_NOIRQ;
2522 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2523 } else if (in->realtime) {
2524 flags |= PCM_MMAP | PCM_NOIRQ;
2525 }
2526
Garmond Leunge2433c32017-09-28 21:51:22 -07002527 if (audio_extn_ffv_get_stream() == in) {
2528 ALOGD("%s: ffv stream, update pcm config", __func__);
2529 audio_extn_ffv_update_pcm_config(&config);
2530 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002531 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2532 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2533
2534 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002535 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002536 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002537 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002538 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002539 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2540 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2541 if (in->pcm != NULL) {
2542 pcm_close(in->pcm);
2543 in->pcm = NULL;
2544 }
2545 if (pcm_open_retry_count-- == 0) {
2546 ret = -EIO;
2547 goto error_open;
2548 }
2549 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2550 continue;
2551 }
2552 break;
2553 }
2554
2555 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002556 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002557 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002558 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002559 if (ret < 0) {
2560 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2561 pcm_close(in->pcm);
2562 in->pcm = NULL;
2563 goto error_open;
2564 }
2565 register_in_stream(in);
2566 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002567 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002568 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002569 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002570 if (ret < 0) {
2571 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002572 pcm_close(in->pcm);
2573 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002574 goto error_open;
2575 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002576 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002577 }
2578
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002579 check_and_enable_effect(adev);
2580
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302581done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302582 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002583 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002584
Eric Laurentc8400632013-02-14 19:04:54 -08002585 return ret;
2586
2587error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302588 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002590error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302591 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302592 /*
2593 * sleep 50ms to allow sufficient time for kernel
2594 * drivers to recover incases like SSR.
2595 */
2596 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002597 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002598
2599 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600}
2601
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002602void lock_input_stream(struct stream_in *in)
2603{
2604 pthread_mutex_lock(&in->pre_lock);
2605 pthread_mutex_lock(&in->lock);
2606 pthread_mutex_unlock(&in->pre_lock);
2607}
2608
2609void lock_output_stream(struct stream_out *out)
2610{
2611 pthread_mutex_lock(&out->pre_lock);
2612 pthread_mutex_lock(&out->lock);
2613 pthread_mutex_unlock(&out->pre_lock);
2614}
2615
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616/* must be called with out->lock locked */
2617static int send_offload_cmd_l(struct stream_out* out, int command)
2618{
2619 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2620
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002621 if (!cmd) {
2622 ALOGE("failed to allocate mem for command 0x%x", command);
2623 return -ENOMEM;
2624 }
2625
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002626 ALOGVV("%s %d", __func__, command);
2627
2628 cmd->cmd = command;
2629 list_add_tail(&out->offload_cmd_list, &cmd->node);
2630 pthread_cond_signal(&out->offload_cond);
2631 return 0;
2632}
2633
2634/* must be called iwth out->lock locked */
2635static void stop_compressed_output_l(struct stream_out *out)
2636{
2637 out->offload_state = OFFLOAD_STATE_IDLE;
2638 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002639 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002640 if (out->compr != NULL) {
2641 compress_stop(out->compr);
2642 while (out->offload_thread_blocked) {
2643 pthread_cond_wait(&out->cond, &out->lock);
2644 }
2645 }
2646}
2647
Varun Balaraje49253e2017-07-06 19:48:56 +05302648bool is_interactive_usecase(audio_usecase_t uc_id)
2649{
2650 unsigned int i;
2651 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2652 if (uc_id == interactive_usecases[i])
2653 return true;
2654 }
2655 return false;
2656}
2657
2658static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2659{
2660 audio_usecase_t ret_uc = USECASE_INVALID;
2661 unsigned int intract_uc_index;
2662 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2663
2664 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2665 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2666 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2667 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2668 ret_uc = interactive_usecases[intract_uc_index];
2669 break;
2670 }
2671 }
2672
2673 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2674 return ret_uc;
2675}
2676
2677static void free_interactive_usecase(struct audio_device *adev,
2678 audio_usecase_t uc_id)
2679{
2680 unsigned int interact_uc_index;
2681 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2682
2683 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2684 if (interactive_usecases[interact_uc_index] == uc_id) {
2685 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2686 break;
2687 }
2688 }
2689 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2690}
2691
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002692bool is_offload_usecase(audio_usecase_t uc_id)
2693{
2694 unsigned int i;
2695 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2696 if (uc_id == offload_usecases[i])
2697 return true;
2698 }
2699 return false;
2700}
2701
Dhananjay Kumarac341582017-02-23 23:42:25 +05302702static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002703{
vivek mehta446c3962015-09-14 10:57:35 -07002704 audio_usecase_t ret_uc = USECASE_INVALID;
2705 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002706 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002707 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302708 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002709 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2710 else
2711 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002712
vivek mehta446c3962015-09-14 10:57:35 -07002713 pthread_mutex_lock(&adev->lock);
2714 if (get_usecase_from_list(adev, ret_uc) != NULL)
2715 ret_uc = USECASE_INVALID;
2716 pthread_mutex_unlock(&adev->lock);
2717
2718 return ret_uc;
2719 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002720
2721 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002722 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2723 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2724 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2725 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002726 break;
2727 }
2728 }
vivek mehta446c3962015-09-14 10:57:35 -07002729
2730 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2731 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002732}
2733
2734static void free_offload_usecase(struct audio_device *adev,
2735 audio_usecase_t uc_id)
2736{
vivek mehta446c3962015-09-14 10:57:35 -07002737 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002738 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002739
2740 if (!adev->multi_offload_enable)
2741 return;
2742
2743 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2744 if (offload_usecases[offload_uc_index] == uc_id) {
2745 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002746 break;
2747 }
2748 }
2749 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2750}
2751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752static void *offload_thread_loop(void *context)
2753{
2754 struct stream_out *out = (struct stream_out *) context;
2755 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002756 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002757
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2759 set_sched_policy(0, SP_FOREGROUND);
2760 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2761
2762 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002763 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002764 for (;;) {
2765 struct offload_cmd *cmd = NULL;
2766 stream_callback_event_t event;
2767 bool send_callback = false;
2768
2769 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2770 __func__, list_empty(&out->offload_cmd_list),
2771 out->offload_state);
2772 if (list_empty(&out->offload_cmd_list)) {
2773 ALOGV("%s SLEEPING", __func__);
2774 pthread_cond_wait(&out->offload_cond, &out->lock);
2775 ALOGV("%s RUNNING", __func__);
2776 continue;
2777 }
2778
2779 item = list_head(&out->offload_cmd_list);
2780 cmd = node_to_item(item, struct offload_cmd, node);
2781 list_remove(item);
2782
2783 ALOGVV("%s STATE %d CMD %d out->compr %p",
2784 __func__, out->offload_state, cmd->cmd, out->compr);
2785
2786 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2787 free(cmd);
2788 break;
2789 }
2790
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002791 // allow OFFLOAD_CMD_ERROR reporting during standby
2792 // this is needed to handle failures during compress_open
2793 // Note however that on a pause timeout, the stream is closed
2794 // and no offload usecase will be active. Therefore this
2795 // special case is needed for compress_open failures alone
2796 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2797 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002799 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 pthread_cond_signal(&out->cond);
2801 continue;
2802 }
2803 out->offload_thread_blocked = true;
2804 pthread_mutex_unlock(&out->lock);
2805 send_callback = false;
2806 switch(cmd->cmd) {
2807 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002808 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002810 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002811 send_callback = true;
2812 event = STREAM_CBK_EVENT_WRITE_READY;
2813 break;
2814 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002815 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302816 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002817 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302818 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002819 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302820 if (ret < 0)
2821 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302822 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302823 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002824 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002825 else
2826 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002827 if (-ENETRESET != ret && !(-EINTR == ret &&
2828 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302829 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302830 pthread_mutex_lock(&out->lock);
2831 out->send_new_metadata = 1;
2832 out->send_next_track_params = true;
2833 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302834 event = STREAM_CBK_EVENT_DRAIN_READY;
2835 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2836 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302837 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 break;
2839 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002840 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002841 ret = compress_drain(out->compr);
2842 ALOGD("copl(%p):out of compress_drain", out);
2843 // EINTR check avoids drain interruption due to SSR
2844 if (-ENETRESET != ret && !(-EINTR == ret &&
2845 CARD_STATUS_OFFLINE == out->card_status)) {
2846 send_callback = true;
2847 event = STREAM_CBK_EVENT_DRAIN_READY;
2848 } else
2849 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302851 case OFFLOAD_CMD_ERROR:
2852 ALOGD("copl(%p): sending error callback to AF", out);
2853 send_callback = true;
2854 event = STREAM_CBK_EVENT_ERROR;
2855 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 default:
2857 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2858 break;
2859 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002860 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 out->offload_thread_blocked = false;
2862 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002863 if (send_callback && out->client_callback) {
2864 ALOGVV("%s: sending client_callback event %d", __func__, event);
2865 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002866 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002867 free(cmd);
2868 }
2869
2870 pthread_cond_signal(&out->cond);
2871 while (!list_empty(&out->offload_cmd_list)) {
2872 item = list_head(&out->offload_cmd_list);
2873 list_remove(item);
2874 free(node_to_item(item, struct offload_cmd, node));
2875 }
2876 pthread_mutex_unlock(&out->lock);
2877
2878 return NULL;
2879}
2880
2881static int create_offload_callback_thread(struct stream_out *out)
2882{
2883 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2884 list_init(&out->offload_cmd_list);
2885 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2886 offload_thread_loop, out);
2887 return 0;
2888}
2889
2890static int destroy_offload_callback_thread(struct stream_out *out)
2891{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002892 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 stop_compressed_output_l(out);
2894 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2895
2896 pthread_mutex_unlock(&out->lock);
2897 pthread_join(out->offload_thread, (void **) NULL);
2898 pthread_cond_destroy(&out->offload_cond);
2899
2900 return 0;
2901}
2902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903static int stop_output_stream(struct stream_out *out)
2904{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302905 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 struct audio_usecase *uc_info;
2907 struct audio_device *adev = out->dev;
2908
Eric Laurent994a6932013-07-17 11:51:42 -07002909 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002910 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 uc_info = get_usecase_from_list(adev, out->usecase);
2912 if (uc_info == NULL) {
2913 ALOGE("%s: Could not find the usecase (%d) in the list",
2914 __func__, out->usecase);
2915 return -EINVAL;
2916 }
2917
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002918 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302919 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002920 if (adev->visualizer_stop_output != NULL)
2921 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002922
2923 audio_extn_dts_remove_state_notifier_node(out->usecase);
2924
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002925 if (adev->offload_effects_stop_output != NULL)
2926 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2927 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002928
Arun Mirpurief53ce52018-09-11 18:00:09 -07002929 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2930 voice_set_device_mute_flag(adev, false);
2931
Eric Laurent150dbfe2013-02-27 14:31:02 -08002932 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002933 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002934
2935 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002936 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002938 if (is_offload_usecase(out->usecase)) {
2939 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2940 adev->dsp_bit_width_enforce_mode,
2941 false);
2942 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07002943 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2944 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
2945 false);
2946
2947 if (ret != 0)
2948 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
2949 /* default service interval was successfully updated,
2950 reopen USB backend with new service interval */
2951 ret = 0;
2952 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002953
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002954 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302955 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002956 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302957 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002958 ALOGV("Disable passthrough , reset mixer to pcm");
2959 /* NO_PASSTHROUGH */
2960 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002961 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002962 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2963 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002964
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302965 /* Must be called after removing the usecase from list */
2966 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302967 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302968
Manish Dewangan21a850a2017-08-14 12:03:55 +05302969 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002970 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2971 if (ret < 0)
2972 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2973 }
2974
Garmond Leung5fd0b552018-04-17 11:56:12 -07002975 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002976 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 return ret;
2978}
2979
2980int start_output_stream(struct stream_out *out)
2981{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 struct audio_usecase *uc_info;
2984 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002985 char mixer_ctl_name[128];
2986 struct mixer_ctl *ctl = NULL;
2987 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302988 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989
Haynes Mathew George380745d2017-10-04 15:27:45 -07002990 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002991 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2992 ret = -EINVAL;
2993 goto error_config;
2994 }
2995
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302996 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2997 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2998 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302999
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303000 if (CARD_STATUS_OFFLINE == out->card_status ||
3001 CARD_STATUS_OFFLINE == adev->card_status) {
3002 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303003 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303004 goto error_config;
3005 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303006
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303007 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
3008 if (!audio_extn_a2dp_is_ready()) {
3009 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303010 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303011 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303012 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3013 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3014 ret = -EAGAIN;
3015 goto error_config;
3016 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303017 }
3018 }
3019 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303020 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3021 if (!adev->bt_sco_on) {
3022 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3023 //combo usecase just by pass a2dp
3024 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3025 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3026 } else {
3027 ALOGE("%s: SCO profile is not ready, return error", __func__);
3028 ret = -EAGAIN;
3029 goto error_config;
3030 }
3031 }
3032 }
3033
Eric Laurentb23d5282013-05-14 15:27:20 -07003034 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 if (out->pcm_device_id < 0) {
3036 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3037 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003038 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003039 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 }
3041
3042 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003043
3044 if (!uc_info) {
3045 ret = -ENOMEM;
3046 goto error_config;
3047 }
3048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 uc_info->id = out->usecase;
3050 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003051 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003052 uc_info->devices = out->devices;
3053 uc_info->in_snd_device = SND_DEVICE_NONE;
3054 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003055
3056 /* This must be called before adding this usecase to the list */
3057 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3058 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3059 /* USB backend is not reopened immediately.
3060 This is eventually done as part of select_devices */
3061 }
3062
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003063 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303065 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3066 adev->perf_lock_opts,
3067 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303068
3069 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303070 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303071 if (audio_extn_passthru_is_enabled() &&
3072 audio_extn_passthru_is_passthrough_stream(out)) {
3073 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303074 }
3075 }
3076
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303077 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3078 (!audio_extn_a2dp_is_ready())) {
3079 if (!a2dp_combo) {
3080 check_a2dp_restore_l(adev, out, false);
3081 } else {
3082 audio_devices_t dev = out->devices;
3083 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3084 select_devices(adev, out->usecase);
3085 out->devices = dev;
3086 }
3087 } else {
3088 select_devices(adev, out->usecase);
3089 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003090
Arun Mirpurief53ce52018-09-11 18:00:09 -07003091 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3092 voice_set_device_mute_flag(adev, true);
3093
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003094 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3095 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003096
3097 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3098 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3099 ALOGE("%s: pcm stream not ready", __func__);
3100 goto error_open;
3101 }
3102 ret = pcm_start(out->pcm);
3103 if (ret < 0) {
3104 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3105 goto error_open;
3106 }
3107 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003108 unsigned int flags = PCM_OUT;
3109 unsigned int pcm_open_retry_count = 0;
3110 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3111 flags |= PCM_MMAP | PCM_NOIRQ;
3112 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003113 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003114 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003115 } else
3116 flags |= PCM_MONOTONIC;
3117
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003118 if ((adev->vr_audio_mode_enabled) &&
3119 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3120 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3121 "PCM_Dev %d Topology", out->pcm_device_id);
3122 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3123 if (!ctl) {
3124 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3125 __func__, mixer_ctl_name);
3126 } else {
3127 //if success use ULLPP
3128 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3129 __func__, mixer_ctl_name, out->pcm_device_id);
3130 //There is a still a possibility that some sessions
3131 // that request for FAST|RAW when 3D audio is active
3132 //can go through ULLPP. Ideally we expects apps to
3133 //listen to audio focus and stop concurrent playback
3134 //Also, we will look for mode flag (voice_in_communication)
3135 //before enabling the realtime flag.
3136 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3137 }
3138 }
3139
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003140 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003141 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003142 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3143 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003144 ATRACE_END();
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003145 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3146 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3147 if (out->pcm != NULL) {
3148 pcm_close(out->pcm);
3149 out->pcm = NULL;
3150 }
3151 if (pcm_open_retry_count-- == 0) {
3152 ret = -EIO;
3153 goto error_open;
3154 }
3155 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3156 continue;
3157 }
3158 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003160
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003161 ALOGV("%s: pcm_prepare", __func__);
3162 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003163 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003164 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003165 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003166 if (ret < 0) {
3167 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3168 pcm_close(out->pcm);
3169 out->pcm = NULL;
3170 goto error_open;
3171 }
3172 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303173 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303174 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003175 // apply volume for voip playback after path is set up
3176 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3177 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003179 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303180 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003181 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3182 adev->dsp_bit_width_enforce_mode,
3183 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003185 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003186 out->compr = compress_open(adev->snd_card,
3187 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003188 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003189 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003191 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 compress_close(out->compr);
3193 out->compr = NULL;
3194 ret = -EIO;
3195 goto error_open;
3196 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303197 /* compress_open sends params of the track, so reset the flag here */
3198 out->is_compr_metadata_avail = false;
3199
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003200 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003202
Fred Oh3f43e742015-03-04 18:42:34 -08003203 /* Since small bufs uses blocking writes, a write will be blocked
3204 for the default max poll time (20s) in the event of an SSR.
3205 Reduce the poll time to observe and deal with SSR faster.
3206 */
Ashish Jain5106d362016-05-11 19:23:33 +05303207 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003208 compress_set_max_poll_wait(out->compr, 1000);
3209 }
3210
Manish Dewangan69426c82017-01-30 17:35:36 +05303211 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303212 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303213
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003214 audio_extn_dts_create_state_notifier_node(out->usecase);
3215 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3216 popcount(out->channel_mask),
3217 out->playback_started);
3218
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003219#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303220 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003221 audio_extn_dolby_send_ddp_endp_params(adev);
3222#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303223 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3224 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003225 if (adev->visualizer_start_output != NULL)
3226 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3227 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303228 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003229 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003232
3233 if (ret == 0) {
3234 register_out_stream(out);
3235 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003236 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3237 ALOGE("%s: pcm stream not ready", __func__);
3238 goto error_open;
3239 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003240 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003241 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003242 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003243 if (ret < 0)
3244 goto error_open;
3245 }
3246 }
3247
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303248 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003249 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003250
Manish Dewangan21a850a2017-08-14 12:03:55 +05303251 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003252 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003253 if (ret < 0)
3254 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3255 }
3256
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003257 // consider a scenario where on pause lower layers are tear down.
3258 // so on resume, swap mixer control need to be sent only when
3259 // backend is active, hence rather than sending from enable device
3260 // sending it from start of streamtream
3261
3262 platform_set_swap_channels(adev, true);
3263
Haynes Mathew George380745d2017-10-04 15:27:45 -07003264 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003265 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003266error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303267 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003269error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303270 /*
3271 * sleep 50ms to allow sufficient time for kernel
3272 * drivers to recover incases like SSR.
3273 */
3274 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003275 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003276 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277}
3278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279static int check_input_parameters(uint32_t sample_rate,
3280 audio_format_t format,
3281 int channel_count)
3282{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003283 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303285 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3286 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3287 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003288 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003289 !audio_extn_compr_cap_format_supported(format))
3290 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003291
3292 switch (channel_count) {
3293 case 1:
3294 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303295 case 3:
3296 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003297 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003298 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003299 break;
3300 default:
3301 ret = -EINVAL;
3302 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303
3304 switch (sample_rate) {
3305 case 8000:
3306 case 11025:
3307 case 12000:
3308 case 16000:
3309 case 22050:
3310 case 24000:
3311 case 32000:
3312 case 44100:
3313 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003314 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303315 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003316 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303317 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 break;
3319 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003320 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 }
3322
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324}
3325
Naresh Tanniru04f71882018-06-26 17:46:22 +05303326
3327/** Add a value in a list if not already present.
3328 * @return true if value was successfully inserted or already present,
3329 * false if the list is full and does not contain the value.
3330 */
3331static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3332 for (size_t i = 0; i < list_length; i++) {
3333 if (list[i] == value) return true; // value is already present
3334 if (list[i] == 0) { // no values in this slot
3335 list[i] = value;
3336 return true; // value inserted
3337 }
3338 }
3339 return false; // could not insert value
3340}
3341
3342/** Add channel_mask in supported_channel_masks if not already present.
3343 * @return true if channel_mask was successfully inserted or already present,
3344 * false if supported_channel_masks is full and does not contain channel_mask.
3345 */
3346static void register_channel_mask(audio_channel_mask_t channel_mask,
3347 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3348 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3349 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3350}
3351
3352/** Add format in supported_formats if not already present.
3353 * @return true if format was successfully inserted or already present,
3354 * false if supported_formats is full and does not contain format.
3355 */
3356static void register_format(audio_format_t format,
3357 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3358 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3359 "%s: stream can not declare supporting its format %x", __func__, format);
3360}
3361/** Add sample_rate in supported_sample_rates if not already present.
3362 * @return true if sample_rate was successfully inserted or already present,
3363 * false if supported_sample_rates is full and does not contain sample_rate.
3364 */
3365static void register_sample_rate(uint32_t sample_rate,
3366 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3367 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3368 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3369}
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371static size_t get_input_buffer_size(uint32_t sample_rate,
3372 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003373 int channel_count,
3374 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375{
3376 size_t size = 0;
3377
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003378 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3379 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003381 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003382 if (is_low_latency)
3383 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303384
3385 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003387 /* make sure the size is multiple of 32 bytes
3388 * At 48 kHz mono 16-bit PCM:
3389 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3390 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3391 */
3392 size += 0x1f;
3393 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003394
3395 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396}
3397
Ashish Jain058165c2016-09-28 23:18:48 +05303398static size_t get_output_period_size(uint32_t sample_rate,
3399 audio_format_t format,
3400 int channel_count,
3401 int duration /*in millisecs*/)
3402{
3403 size_t size = 0;
3404 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3405
3406 if ((duration == 0) || (sample_rate == 0) ||
3407 (bytes_per_sample == 0) || (channel_count == 0)) {
3408 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3409 bytes_per_sample, channel_count);
3410 return -EINVAL;
3411 }
3412
3413 size = (sample_rate *
3414 duration *
3415 bytes_per_sample *
3416 channel_count) / 1000;
3417 /*
3418 * To have same PCM samples for all channels, the buffer size requires to
3419 * be multiple of (number of channels * bytes per sample)
3420 * For writes to succeed, the buffer must be written at address which is multiple of 32
3421 */
3422 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3423
3424 return (size/(channel_count * bytes_per_sample));
3425}
3426
Zhou Song48453a02018-01-10 17:50:59 +08003427static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303428{
3429 uint64_t actual_frames_rendered = 0;
3430 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3431
3432 /* This adjustment accounts for buffering after app processor.
3433 * It is based on estimated DSP latency per use case, rather than exact.
3434 */
3435 int64_t platform_latency = platform_render_latency(out->usecase) *
3436 out->sample_rate / 1000000LL;
3437
Zhou Song48453a02018-01-10 17:50:59 +08003438 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303439 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3440 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3441 * hence only estimate.
3442 */
3443 int64_t signed_frames = out->written - kernel_buffer_size;
3444
3445 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3446
Zhou Song48453a02018-01-10 17:50:59 +08003447 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303448 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003449 if (timestamp != NULL )
3450 *timestamp = out->writeAt;
3451 } else if (timestamp != NULL) {
3452 clock_gettime(CLOCK_MONOTONIC, timestamp);
3453 }
3454 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303455
3456 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3457 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3458 (long long int)out->written, (int)kernel_buffer_size,
3459 audio_bytes_per_sample(out->compr_config.codec->format),
3460 popcount(out->channel_mask));
3461
3462 return actual_frames_rendered;
3463}
3464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3466{
3467 struct stream_out *out = (struct stream_out *)stream;
3468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003469 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470}
3471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003472static int out_set_sample_rate(struct audio_stream *stream __unused,
3473 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474{
3475 return -ENOSYS;
3476}
3477
3478static size_t out_get_buffer_size(const struct audio_stream *stream)
3479{
3480 struct stream_out *out = (struct stream_out *)stream;
3481
Varun Balaraje49253e2017-07-06 19:48:56 +05303482 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303483 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303484 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303485 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3486 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3487 else
3488 return out->compr_config.fragment_size;
3489 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003490 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003491 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3492 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 +05303493 else if (is_offload_usecase(out->usecase) &&
3494 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303495 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003497 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003498 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499}
3500
3501static uint32_t out_get_channels(const struct audio_stream *stream)
3502{
3503 struct stream_out *out = (struct stream_out *)stream;
3504
3505 return out->channel_mask;
3506}
3507
3508static audio_format_t out_get_format(const struct audio_stream *stream)
3509{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 struct stream_out *out = (struct stream_out *)stream;
3511
3512 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513}
3514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003515static int out_set_format(struct audio_stream *stream __unused,
3516 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517{
3518 return -ENOSYS;
3519}
3520
3521static int out_standby(struct audio_stream *stream)
3522{
3523 struct stream_out *out = (struct stream_out *)stream;
3524 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003525 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303527 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3528 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003530 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003532 if (adev->adm_deregister_stream)
3533 adev->adm_deregister_stream(adev->adm_data, out->handle);
3534
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003535 if (is_offload_usecase(out->usecase))
3536 stop_compressed_output_l(out);
3537
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003538 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003540 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3541 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303542 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003543 pthread_mutex_unlock(&adev->lock);
3544 pthread_mutex_unlock(&out->lock);
3545 ALOGD("VOIP output entered standby");
3546 return 0;
3547 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003548 if (out->pcm) {
3549 pcm_close(out->pcm);
3550 out->pcm = NULL;
3551 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003552 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3553 do_stop = out->playback_started;
3554 out->playback_started = false;
3555 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003557 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303558 out->send_next_track_params = false;
3559 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003560 out->gapless_mdata.encoder_delay = 0;
3561 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003562 if (out->compr != NULL) {
3563 compress_close(out->compr);
3564 out->compr = NULL;
3565 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003566 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003567 if (do_stop) {
3568 stop_output_stream(out);
3569 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003570 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 }
3572 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303573 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 return 0;
3575}
3576
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303577static int out_on_error(struct audio_stream *stream)
3578{
3579 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003580 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303581
3582 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003583 // always send CMD_ERROR for offload streams, this
3584 // is needed e.g. when SSR happens within compress_open
3585 // since the stream is active, offload_callback_thread is also active.
3586 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3587 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003588 }
3589 pthread_mutex_unlock(&out->lock);
3590
3591 status = out_standby(&out->stream.common);
3592
3593 lock_output_stream(out);
3594 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003595 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303596 }
3597 pthread_mutex_unlock(&out->lock);
3598
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003599 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303600}
3601
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303602/*
3603 *standby implementation without locks, assumes that the callee already
3604 *has taken adev and out lock.
3605 */
3606int out_standby_l(struct audio_stream *stream)
3607{
3608 struct stream_out *out = (struct stream_out *)stream;
3609 struct audio_device *adev = out->dev;
3610
3611 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3612 stream, out->usecase, use_case_table[out->usecase]);
3613
3614 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003615 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303616 if (adev->adm_deregister_stream)
3617 adev->adm_deregister_stream(adev->adm_data, out->handle);
3618
3619 if (is_offload_usecase(out->usecase))
3620 stop_compressed_output_l(out);
3621
3622 out->standby = true;
3623 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3624 voice_extn_compress_voip_close_output_stream(stream);
3625 out->started = 0;
3626 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003627 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303628 return 0;
3629 } else if (!is_offload_usecase(out->usecase)) {
3630 if (out->pcm) {
3631 pcm_close(out->pcm);
3632 out->pcm = NULL;
3633 }
3634 } else {
3635 ALOGD("copl(%p):standby", out);
3636 out->send_next_track_params = false;
3637 out->is_compr_metadata_avail = false;
3638 out->gapless_mdata.encoder_delay = 0;
3639 out->gapless_mdata.encoder_padding = 0;
3640 if (out->compr != NULL) {
3641 compress_close(out->compr);
3642 out->compr = NULL;
3643 }
3644 }
3645 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003646 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303647 }
3648 ALOGD("%s: exit", __func__);
3649 return 0;
3650}
3651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003652static int out_dump(const struct audio_stream *stream __unused,
3653 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654{
3655 return 0;
3656}
3657
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003658static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3659{
3660 int ret = 0;
3661 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003662
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003663 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003664 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003665 return -EINVAL;
3666 }
3667
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303668 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003669
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003670 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3671 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303672 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003673 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003674 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3675 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303676 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003677 }
3678
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003679 ALOGV("%s new encoder delay %u and padding %u", __func__,
3680 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3681
3682 return 0;
3683}
3684
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003685static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3686{
3687 return out == adev->primary_output || out == adev->voice_tx_output;
3688}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003689
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303690// note: this call is safe only if the stream_cb is
3691// removed first in close_output_stream (as is done now).
3692static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3693{
3694 if (!stream || !parms)
3695 return;
3696
3697 struct stream_out *out = (struct stream_out *)stream;
3698 struct audio_device *adev = out->dev;
3699
3700 card_status_t status;
3701 int card;
3702 if (parse_snd_card_status(parms, &card, &status) < 0)
3703 return;
3704
3705 pthread_mutex_lock(&adev->lock);
3706 bool valid_cb = (card == adev->snd_card);
3707 pthread_mutex_unlock(&adev->lock);
3708
3709 if (!valid_cb)
3710 return;
3711
3712 lock_output_stream(out);
3713 if (out->card_status != status)
3714 out->card_status = status;
3715 pthread_mutex_unlock(&out->lock);
3716
3717 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3718 use_case_table[out->usecase],
3719 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3720
3721 if (status == CARD_STATUS_OFFLINE)
3722 out_on_error(stream);
3723
3724 return;
3725}
3726
Kevin Rocardfce19002017-08-07 19:21:36 -07003727static int get_alive_usb_card(struct str_parms* parms) {
3728 int card;
3729 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3730 !audio_extn_usb_alive(card)) {
3731 return card;
3732 }
3733 return -ENODEV;
3734}
3735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3737{
3738 struct stream_out *out = (struct stream_out *)stream;
3739 struct audio_device *adev = out->dev;
3740 struct str_parms *parms;
3741 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003742 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303743 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003744 bool reconfig = false;
3745 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746
sangwoobc677242013-08-08 16:53:43 +09003747 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003748 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303750 if (!parms)
3751 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003752 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3753 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003755 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003756 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003758 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003759 * When HDMI cable is unplugged the music playback is paused and
3760 * the policy manager sends routing=0. But the audioflinger continues
3761 * to write data until standby time (3sec). As the HDMI core is
3762 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003763 * Avoid this by routing audio to speaker until standby.
3764 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003765 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3766 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303767 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003768 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3769 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003770 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303771 /*
3772 * When A2DP is disconnected the
3773 * music playback is paused and the policy manager sends routing=0
3774 * But the audioflingercontinues to write data until standby time
3775 * (3sec). As BT is turned off, the write gets blocked.
3776 * Avoid this by routing audio to speaker until standby.
3777 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003778 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003779 (val == AUDIO_DEVICE_NONE) &&
3780 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303781 val = AUDIO_DEVICE_OUT_SPEAKER;
3782 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05303783 /*
3784 * When USB headset is disconnected the music platback paused
3785 * and the policy manager send routing=0. But if the USB is connected
3786 * back before the standby time, AFE is not closed and opened
3787 * when USB is connected back. So routing to speker will guarantee
3788 * AFE reconfiguration and AFE will be opend once USB is connected again
3789 */
3790 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
3791 (val == AUDIO_DEVICE_NONE) &&
3792 !audio_extn_usb_connected(parms)) {
3793 val = AUDIO_DEVICE_OUT_SPEAKER;
3794 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303795 /* To avoid a2dp to sco overlapping / BT device improper state
3796 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303797 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303798 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3799 if (!audio_extn_a2dp_is_ready()) {
3800 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3801 //combo usecase just by pass a2dp
3802 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303803 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303804 } else {
3805 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3806 /* update device to a2dp and don't route as BT returned error
3807 * However it is still possible a2dp routing called because
3808 * of current active device disconnection (like wired headset)
3809 */
3810 out->devices = val;
3811 pthread_mutex_unlock(&out->lock);
3812 pthread_mutex_unlock(&adev->lock);
3813 goto error;
3814 }
3815 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303816 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003817
3818 audio_devices_t new_dev = val;
3819
3820 // Workaround: If routing to an non existing usb device, fail gracefully
3821 // The routing request will otherwise block during 10 second
3822 int card;
3823 if (audio_is_usb_out_device(new_dev) &&
3824 (card = get_alive_usb_card(parms)) >= 0) {
3825
3826 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3827 pthread_mutex_unlock(&adev->lock);
3828 pthread_mutex_unlock(&out->lock);
3829 ret = -ENOSYS;
3830 goto routing_fail;
3831 }
3832
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003833 /*
3834 * select_devices() call below switches all the usecases on the same
3835 * backend to the new device. Refer to check_usecases_codec_backend() in
3836 * the select_devices(). But how do we undo this?
3837 *
3838 * For example, music playback is active on headset (deep-buffer usecase)
3839 * and if we go to ringtones and select a ringtone, low-latency usecase
3840 * will be started on headset+speaker. As we can't enable headset+speaker
3841 * and headset devices at the same time, select_devices() switches the music
3842 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3843 * So when the ringtone playback is completed, how do we undo the same?
3844 *
3845 * We are relying on the out_set_parameters() call on deep-buffer output,
3846 * once the ringtone playback is ended.
3847 * NOTE: We should not check if the current devices are same as new devices.
3848 * Because select_devices() must be called to switch back the music
3849 * playback to headset.
3850 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003851 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003852 audio_devices_t new_dev = val;
3853 bool same_dev = out->devices == new_dev;
3854 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003855
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003856 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003857 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003858 if (adev->mode == AUDIO_MODE_IN_CALL) {
3859 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003860 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3861 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
3862 audio_extn_usb_set_service_interval(true /*playback*/,
3863 service_interval,
3864 &reconfig);
3865 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
3866 }
3867 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003868 }
3869 } else {
3870 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003871 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003872 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003873 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003874
3875 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003876 if (!same_dev) {
3877 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303878 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3879 adev->perf_lock_opts,
3880 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003881 if (adev->adm_on_routing_change)
3882 adev->adm_on_routing_change(adev->adm_data,
3883 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003884 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303885 if (!bypass_a2dp) {
3886 select_devices(adev, out->usecase);
3887 } else {
3888 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3889 select_devices(adev, out->usecase);
3890 out->devices = new_dev;
3891 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003892
3893 if (!same_dev) {
3894 // on device switch force swap, lower functions will make sure
3895 // to check if swap is allowed or not.
3896 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303897 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003898 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303899 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3900 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003901 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303902 pthread_mutex_lock(&out->compr_mute_lock);
3903 out->a2dp_compress_mute = false;
3904 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3905 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003906 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3907 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303908 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003909 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003910 }
3911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003913 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003915 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003916
3917 if (out == adev->primary_output) {
3918 pthread_mutex_lock(&adev->lock);
3919 audio_extn_set_parameters(adev, parms);
3920 pthread_mutex_unlock(&adev->lock);
3921 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003922 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003923 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003924 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003925
3926 audio_extn_dts_create_state_notifier_node(out->usecase);
3927 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3928 popcount(out->channel_mask),
3929 out->playback_started);
3930
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003931 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003932 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003933
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303934 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3935 if (err >= 0) {
3936 strlcpy(out->profile, value, sizeof(out->profile));
3937 ALOGV("updating stream profile with value '%s'", out->profile);
3938 lock_output_stream(out);
3939 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3940 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003941 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303942 out->sample_rate, out->bit_width,
3943 out->channel_mask, out->profile,
3944 &out->app_type_cfg);
3945 pthread_mutex_unlock(&out->lock);
3946 }
3947
Alexy Joseph98988832017-01-13 14:56:59 -08003948 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003949 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3950 // and vendor.audio.hal.output.suspend.supported is set to true
3951 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003952 //check suspend parameter only for low latency and if the property
3953 //is enabled
3954 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3955 ALOGI("%s: got suspend_playback %s", __func__, value);
3956 lock_output_stream(out);
3957 if (!strncmp(value, "false", 5)) {
3958 //suspend_playback=false is supposed to set QOS value back to 75%
3959 //the mixer control sent with value Enable will achieve that
3960 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3961 } else if (!strncmp (value, "true", 4)) {
3962 //suspend_playback=true is supposed to remove QOS value
3963 //resetting the mixer control will set the default value
3964 //for the mixer control which is Disable and this removes the QOS vote
3965 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3966 } else {
3967 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3968 " got %s", __func__, value);
3969 ret = -1;
3970 }
3971
3972 if (ret != 0) {
3973 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3974 __func__, out->pm_qos_mixer_path, ret);
3975 }
3976
3977 pthread_mutex_unlock(&out->lock);
3978 }
3979 }
3980 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303982error:
Eric Laurent994a6932013-07-17 11:51:42 -07003983 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 return ret;
3985}
3986
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003987static bool stream_get_parameter_channels(struct str_parms *query,
3988 struct str_parms *reply,
3989 audio_channel_mask_t *supported_channel_masks) {
3990 int ret = -1;
3991 char value[512];
3992 bool first = true;
3993 size_t i, j;
3994
3995 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3996 ret = 0;
3997 value[0] = '\0';
3998 i = 0;
3999 while (supported_channel_masks[i] != 0) {
4000 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4001 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4002 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304003 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004004
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304005 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004006 first = false;
4007 break;
4008 }
4009 }
4010 i++;
4011 }
4012 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4013 }
4014 return ret == 0;
4015}
4016
4017static bool stream_get_parameter_formats(struct str_parms *query,
4018 struct str_parms *reply,
4019 audio_format_t *supported_formats) {
4020 int ret = -1;
4021 char value[256];
4022 size_t i, j;
4023 bool first = true;
4024
4025 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4026 ret = 0;
4027 value[0] = '\0';
4028 i = 0;
4029 while (supported_formats[i] != 0) {
4030 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4031 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4032 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304033 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004034 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304035 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004036 first = false;
4037 break;
4038 }
4039 }
4040 i++;
4041 }
4042 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4043 }
4044 return ret == 0;
4045}
4046
4047static bool stream_get_parameter_rates(struct str_parms *query,
4048 struct str_parms *reply,
4049 uint32_t *supported_sample_rates) {
4050
4051 int i;
4052 char value[256];
4053 int ret = -1;
4054 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4055 ret = 0;
4056 value[0] = '\0';
4057 i=0;
4058 int cursor = 0;
4059 while (supported_sample_rates[i]) {
4060 int avail = sizeof(value) - cursor;
4061 ret = snprintf(value + cursor, avail, "%s%d",
4062 cursor > 0 ? "|" : "",
4063 supported_sample_rates[i]);
4064 if (ret < 0 || ret >= avail) {
4065 // if cursor is at the last element of the array
4066 // overwrite with \0 is duplicate work as
4067 // snprintf already put a \0 in place.
4068 // else
4069 // we had space to write the '|' at value[cursor]
4070 // (which will be overwritten) or no space to fill
4071 // the first element (=> cursor == 0)
4072 value[cursor] = '\0';
4073 break;
4074 }
4075 cursor += ret;
4076 ++i;
4077 }
4078 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4079 value);
4080 }
4081 return ret >= 0;
4082}
4083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4085{
4086 struct stream_out *out = (struct stream_out *)stream;
4087 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004088 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 char value[256];
4090 struct str_parms *reply = str_parms_create();
4091 size_t i, j;
4092 int ret;
4093 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004094
4095 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004096 if (reply) {
4097 str_parms_destroy(reply);
4098 }
4099 if (query) {
4100 str_parms_destroy(query);
4101 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004102 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4103 return NULL;
4104 }
4105
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004106 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4108 if (ret >= 0) {
4109 value[0] = '\0';
4110 i = 0;
4111 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004112 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4113 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004115 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004116 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004117 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 first = false;
4119 break;
4120 }
4121 }
4122 i++;
4123 }
4124 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4125 str = str_parms_to_str(reply);
4126 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004127 voice_extn_out_get_parameters(out, query, reply);
4128 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004130
Alexy Joseph62142aa2015-11-16 15:10:34 -08004131
4132 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4133 if (ret >= 0) {
4134 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304135 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4136 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004137 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304138 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004139 } else {
4140 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304141 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004142 }
4143 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004144 if (str)
4145 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004146 str = str_parms_to_str(reply);
4147 }
4148
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004149 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4150 if (ret >= 0) {
4151 value[0] = '\0';
4152 i = 0;
4153 first = true;
4154 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004155 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4156 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004157 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004158 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004159 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004160 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004161 first = false;
4162 break;
4163 }
4164 }
4165 i++;
4166 }
4167 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004168 if (str)
4169 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004170 str = str_parms_to_str(reply);
4171 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004172
4173 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4174 if (ret >= 0) {
4175 value[0] = '\0';
4176 i = 0;
4177 first = true;
4178 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004179 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4180 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004181 if (!first) {
4182 strlcat(value, "|", sizeof(value));
4183 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004184 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004185 first = false;
4186 break;
4187 }
4188 }
4189 i++;
4190 }
4191 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4192 if (str)
4193 free(str);
4194 str = str_parms_to_str(reply);
4195 }
4196
Alexy Joseph98988832017-01-13 14:56:59 -08004197 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4198 //only low latency track supports suspend_resume
4199 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004200 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004201 if (str)
4202 free(str);
4203 str = str_parms_to_str(reply);
4204 }
4205
4206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 str_parms_destroy(query);
4208 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004209 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 return str;
4211}
4212
4213static uint32_t out_get_latency(const struct audio_stream_out *stream)
4214{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004215 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004217 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218
Alexy Josephaa54c872014-12-03 02:46:47 -08004219 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304220 lock_output_stream(out);
4221 latency = audio_extn_utils_compress_get_dsp_latency(out);
4222 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004223 } else if ((out->realtime) ||
4224 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004225 // since the buffer won't be filled up faster than realtime,
4226 // return a smaller number
4227 if (out->config.rate)
4228 period_ms = (out->af_period_multiplier * out->config.period_size *
4229 1000) / (out->config.rate);
4230 else
4231 period_ms = 0;
4232 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004233 } else {
4234 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004235 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004236 }
4237
yidongh0515e042017-07-06 15:00:34 +08004238 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004239 latency += audio_extn_a2dp_get_encoder_latency();
4240
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304241 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004242 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243}
4244
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304245static float AmpToDb(float amplification)
4246{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304247 float db = DSD_VOLUME_MIN_DB;
4248 if (amplification > 0) {
4249 db = 20 * log10(amplification);
4250 if(db < DSD_VOLUME_MIN_DB)
4251 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304252 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304253 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304254}
4255
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304256static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4257 float right)
4258{
4259 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304260 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304261 char mixer_ctl_name[128];
4262 struct audio_device *adev = out->dev;
4263 struct mixer_ctl *ctl;
4264 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4265 PCM_PLAYBACK);
4266
4267 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4268 "Compress Playback %d Volume", pcm_device_id);
4269 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4270 if (!ctl) {
4271 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4272 __func__, mixer_ctl_name);
4273 return -EINVAL;
4274 }
4275 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4276 __func__, mixer_ctl_name, left, right);
4277 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4278 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4279 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4280
4281 return 0;
4282}
4283
Zhou Song2b8f28f2017-09-11 10:51:38 +08004284static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4285 float right)
4286{
4287 struct stream_out *out = (struct stream_out *)stream;
4288 char mixer_ctl_name[] = "App Type Gain";
4289 struct audio_device *adev = out->dev;
4290 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304291 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004292
4293 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4294 if (!ctl) {
4295 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4296 __func__, mixer_ctl_name);
4297 return -EINVAL;
4298 }
4299
4300 set_values[0] = 0; //0: Rx Session 1:Tx Session
4301 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304302 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4303 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004304
4305 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4306 return 0;
4307}
4308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309static int out_set_volume(struct audio_stream_out *stream, float left,
4310 float right)
4311{
Eric Laurenta9024de2013-04-04 09:19:12 -07004312 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004313 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304314 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004315
Eric Laurenta9024de2013-04-04 09:19:12 -07004316 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4317 /* only take left channel into account: the API is for stereo anyway */
4318 out->muted = (left == 0.0f);
4319 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004320 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304321 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004322 /*
4323 * Set mute or umute on HDMI passthrough stream.
4324 * Only take left channel into account.
4325 * Mute is 0 and unmute 1
4326 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304327 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304328 } else if (out->format == AUDIO_FORMAT_DSD){
4329 char mixer_ctl_name[128] = "DSD Volume";
4330 struct audio_device *adev = out->dev;
4331 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4332
4333 if (!ctl) {
4334 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4335 __func__, mixer_ctl_name);
4336 return -EINVAL;
4337 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304338 volume[0] = (long)(AmpToDb(left));
4339 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304340 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4341 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004342 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304343 pthread_mutex_lock(&out->compr_mute_lock);
4344 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4345 if (!out->a2dp_compress_mute)
4346 ret = out_set_compr_volume(stream, left, right);
4347 out->volume_l = left;
4348 out->volume_r = right;
4349 pthread_mutex_unlock(&out->compr_mute_lock);
4350 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004351 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004352 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004353 if (!out->standby)
4354 ret = out_set_voip_volume(stream, left, right);
4355 out->volume_l = left;
4356 out->volume_r = right;
4357 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004358 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 return -ENOSYS;
4361}
4362
Zhou Songc9672822017-08-16 16:01:39 +08004363static void update_frames_written(struct stream_out *out, size_t bytes)
4364{
4365 size_t bpf = 0;
4366
4367 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4368 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4369 bpf = 1;
4370 else if (!is_offload_usecase(out->usecase))
4371 bpf = audio_bytes_per_sample(out->format) *
4372 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004373
4374 pthread_mutex_lock(&out->position_query_lock);
4375 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004376 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004377 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4378 }
4379 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004380}
4381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4383 size_t bytes)
4384{
4385 struct stream_out *out = (struct stream_out *)stream;
4386 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004387 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304388 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004389 const size_t frame_size = audio_stream_out_frame_size(stream);
4390 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391
Haynes Mathew George380745d2017-10-04 15:27:45 -07004392 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004393 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304394
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304395 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004396
Dhananjay Kumarac341582017-02-23 23:42:25 +05304397 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304398 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304399 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4400 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004401 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304402 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304403 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304404 ALOGD(" %s: sound card is not active/SSR state", __func__);
4405 ret= -EIO;
4406 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304407 }
4408 }
4409
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304410 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304411 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304412 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304413 goto exit;
4414 }
4415
Haynes Mathew George16081042017-05-31 17:16:49 -07004416 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4417 ret = -EINVAL;
4418 goto exit;
4419 }
4420
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304421 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4422 !out->is_iec61937_info_available) {
4423
4424 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4425 out->is_iec61937_info_available = true;
4426 } else if (audio_extn_passthru_is_enabled()) {
4427 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304428 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304429
4430 if((out->format == AUDIO_FORMAT_DTS) ||
4431 (out->format == AUDIO_FORMAT_DTS_HD)) {
4432 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4433 buffer, bytes);
4434 if (ret) {
4435 if (ret != -ENOSYS) {
4436 out->is_iec61937_info_available = false;
4437 ALOGD("iec61937 transmission info not yet updated retry");
4438 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304439 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304440 /* if stream has started and after that there is
4441 * stream config change (iec transmission config)
4442 * then trigger select_device to update backend configuration.
4443 */
4444 out->stream_config_changed = true;
4445 pthread_mutex_lock(&adev->lock);
4446 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304447 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4448 ret = -EINVAL;
4449 goto exit;
4450 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304451 pthread_mutex_unlock(&adev->lock);
4452 out->stream_config_changed = false;
4453 out->is_iec61937_info_available = true;
4454 }
4455 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304456
Garmond Leung317cbf12017-09-13 16:20:50 -07004457 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304458 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4459 (out->is_iec61937_info_available == true)) {
4460 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4461 ret = -EINVAL;
4462 goto exit;
4463 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304464 }
4465 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304466
4467 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4468 (audio_extn_a2dp_is_suspended())) {
4469 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4470 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304471 ret = -EIO;
4472 goto exit;
4473 }
4474 }
4475 }
4476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004478 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004479 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004480 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4481 ret = voice_extn_compress_voip_start_output_stream(out);
4482 else
4483 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004484 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004485 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004486 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004487 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 goto exit;
4489 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304490 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004491 if (last_known_cal_step != -1) {
4492 ALOGD("%s: retry previous failed cal level set", __func__);
4493 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304494 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004495 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304496
4497 if ((out->is_iec61937_info_available == true) &&
4498 (audio_extn_passthru_is_passthrough_stream(out))&&
4499 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4500 ret = -EINVAL;
4501 goto exit;
4502 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504
Ashish Jain81eb2a82015-05-13 10:52:34 +05304505 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004506 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304507 adev->is_channel_status_set = true;
4508 }
4509
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004510 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004511 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004512 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004513 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004514 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4515 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304516 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4517 ALOGD("copl(%p):send next track params in gapless", out);
4518 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4519 out->send_next_track_params = false;
4520 out->is_compr_metadata_avail = false;
4521 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004522 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304523 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304524 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004525
Ashish Jain83a6cc22016-06-28 14:34:17 +05304526 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304527 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304528 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304529 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004530 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304531 return -EINVAL;
4532 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304533 audio_format_t dst_format = out->hal_op_format;
4534 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304535
4536 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4537 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4538
Ashish Jain83a6cc22016-06-28 14:34:17 +05304539 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304540 dst_format,
4541 buffer,
4542 src_format,
4543 frames);
4544
Ashish Jain83a6cc22016-06-28 14:34:17 +05304545 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304546 bytes_to_write);
4547
4548 /*Convert written bytes in audio flinger format*/
4549 if (ret > 0)
4550 ret = ((ret * format_to_bitwidth_table[out->format]) /
4551 format_to_bitwidth_table[dst_format]);
4552 }
4553 } else
4554 ret = compress_write(out->compr, buffer, bytes);
4555
Zhou Songc9672822017-08-16 16:01:39 +08004556 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4557 update_frames_written(out, bytes);
4558
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304559 if (ret < 0)
4560 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08004561 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304562 /*msg to cb thread only if non blocking write is enabled*/
4563 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304564 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004565 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304566 } else if (-ENETRESET == ret) {
4567 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304568 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304569 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304570 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004571 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304572 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004573 }
Ashish Jain5106d362016-05-11 19:23:33 +05304574
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304575 /* Call compr start only when non-zero bytes of data is there to be rendered */
4576 if (!out->playback_started && ret > 0) {
4577 int status = compress_start(out->compr);
4578 if (status < 0) {
4579 ret = status;
4580 ALOGE("%s: compr start failed with err %d", __func__, errno);
4581 goto exit;
4582 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004583 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004584 out->playback_started = 1;
4585 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004586
4587 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4588 popcount(out->channel_mask),
4589 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004590 }
4591 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004592 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004593 return ret;
4594 } else {
4595 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004596 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004597 if (out->muted)
4598 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004599 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
4600 __func__, frames, frame_size, bytes_to_write);
4601
4602 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
4603 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4604 int16_t *src = (int16_t *)buffer;
4605 int16_t *dst = (int16_t *)buffer;
4606
4607 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
4608 out->format != AUDIO_FORMAT_PCM_16_BIT,
4609 "out_write called for incall music use case with wrong properties");
4610
4611 /*
4612 * FIXME: this can be removed once audio flinger mixer supports
4613 * mono output
4614 */
4615
4616 /*
4617 * Code below goes over each frame in the buffer and adds both
4618 * L and R samples and then divides by 2 to convert to mono
4619 */
4620 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
4621 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
4622 }
4623 bytes_to_write /= 2;
4624 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004625
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304626 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004627
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004628 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004629
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004630 if (out->config.rate)
4631 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4632 out->config.rate;
4633
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004634 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004635 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4636
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004637 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004638 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004639 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304640 out->convert_buffer != NULL) {
4641
4642 memcpy_by_audio_format(out->convert_buffer,
4643 out->hal_op_format,
4644 buffer,
4645 out->hal_ip_format,
4646 out->config.period_size * out->config.channels);
4647
4648 ret = pcm_write(out->pcm, out->convert_buffer,
4649 (out->config.period_size *
4650 out->config.channels *
4651 format_to_bitwidth_table[out->hal_op_format]));
4652 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304653 /*
4654 * To avoid underrun in DSP when the application is not pumping
4655 * data at required rate, check for the no. of bytes and ignore
4656 * pcm_write if it is less than actual buffer size.
4657 * It is a work around to a change in compress VOIP driver.
4658 */
4659 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4660 bytes < (out->config.period_size * out->config.channels *
4661 audio_bytes_per_sample(out->format))) {
4662 size_t voip_buf_size =
4663 out->config.period_size * out->config.channels *
4664 audio_bytes_per_sample(out->format);
4665 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4666 __func__, bytes, voip_buf_size);
4667 usleep(((uint64_t)voip_buf_size - bytes) *
4668 1000000 / audio_stream_out_frame_size(stream) /
4669 out_get_sample_rate(&out->stream.common));
4670 ret = 0;
4671 } else
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004672 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304673 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004674
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004675 release_out_focus(out);
4676
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304677 if (ret < 0)
4678 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004679 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304680 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682 }
4683
4684exit:
Zhou Songc9672822017-08-16 16:01:39 +08004685 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304686 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304687 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 pthread_mutex_unlock(&out->lock);
4690
4691 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004692 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004693 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304694 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304695 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304696 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304697 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304698 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304699 out->standby = true;
4700 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304701 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304702 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4703 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4704 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004705
4706 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304707 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004708 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004709 return ret;
4710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004712 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713 return bytes;
4714}
4715
4716static int out_get_render_position(const struct audio_stream_out *stream,
4717 uint32_t *dsp_frames)
4718{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004719 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004720
4721 if (dsp_frames == NULL)
4722 return -EINVAL;
4723
4724 *dsp_frames = 0;
4725 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004726 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304727
4728 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4729 * this operation and adev_close_output_stream(where out gets reset).
4730 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304731 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004732 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304733 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004734 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304735 return 0;
4736 }
4737
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004738 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304739 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304740 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004741 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304742 if (ret < 0)
4743 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004744 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304745 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004746 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304747 if (-ENETRESET == ret) {
4748 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304749 out->card_status = CARD_STATUS_OFFLINE;
4750 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304751 } else if(ret < 0) {
4752 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304753 ret = -EINVAL;
4754 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304755 /*
4756 * Handle corner case where compress session is closed during SSR
4757 * and timestamp is queried
4758 */
4759 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304760 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304761 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304762 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004763 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304764 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304765 pthread_mutex_unlock(&out->lock);
4766 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004767 } else if (audio_is_linear_pcm(out->format)) {
4768 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004769 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004770 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004771 } else
4772 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773}
4774
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004775static int out_add_audio_effect(const struct audio_stream *stream __unused,
4776 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004777{
4778 return 0;
4779}
4780
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004781static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4782 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783{
4784 return 0;
4785}
4786
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004787static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4788 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304790 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791}
4792
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004793static int out_get_presentation_position(const struct audio_stream_out *stream,
4794 uint64_t *frames, struct timespec *timestamp)
4795{
4796 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304797 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004798 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004799
Ashish Jain5106d362016-05-11 19:23:33 +05304800 /* below piece of code is not guarded against any lock because audioFliner serializes
4801 * this operation and adev_close_output_stream( where out gets reset).
4802 */
4803 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304804 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004805 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304806 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4807 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4808 return 0;
4809 }
4810
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004811 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004812
Ashish Jain5106d362016-05-11 19:23:33 +05304813 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4814 ret = compress_get_tstamp(out->compr, &dsp_frames,
4815 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004816 // Adjustment accounts for A2dp encoder latency with offload usecases
4817 // Note: Encoder latency is returned in ms.
4818 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4819 unsigned long offset =
4820 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4821 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4822 }
Ashish Jain5106d362016-05-11 19:23:33 +05304823 ALOGVV("%s rendered frames %ld sample_rate %d",
4824 __func__, dsp_frames, out->sample_rate);
4825 *frames = dsp_frames;
4826 if (ret < 0)
4827 ret = -errno;
4828 if (-ENETRESET == ret) {
4829 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304830 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304831 ret = -EINVAL;
4832 } else
4833 ret = 0;
4834 /* this is the best we can do */
4835 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004836 } else {
4837 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004838 unsigned int avail;
4839 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4840 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4841 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4842 // This adjustment accounts for buffering after app processor.
4843 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004844 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004845 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004846
Weiyin Jiangd4633762018-03-16 12:05:03 +08004847 // Adjustment accounts for A2dp encoder latency with non offload usecases
4848 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4849 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4850 signed_frames -=
4851 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4852 }
4853
4854 // It would be unusual for this value to be negative, but check just in case ...
4855 if (signed_frames >= 0) {
4856 *frames = signed_frames;
4857 ret = 0;
4858 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004859 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304860 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304861 *frames = out->written;
4862 clock_gettime(CLOCK_MONOTONIC, timestamp);
4863 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004864 }
4865 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004866 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004867 return ret;
4868}
4869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004870static int out_set_callback(struct audio_stream_out *stream,
4871 stream_callback_t callback, void *cookie)
4872{
4873 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004874 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004875
4876 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004877 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004878 out->client_callback = callback;
4879 out->client_cookie = cookie;
4880 if (out->adsp_hdlr_stream_handle) {
4881 ret = audio_extn_adsp_hdlr_stream_set_callback(
4882 out->adsp_hdlr_stream_handle,
4883 callback,
4884 cookie);
4885 if (ret)
4886 ALOGW("%s:adsp hdlr callback registration failed %d",
4887 __func__, ret);
4888 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004889 pthread_mutex_unlock(&out->lock);
4890 return 0;
4891}
4892
4893static int out_pause(struct audio_stream_out* stream)
4894{
4895 struct stream_out *out = (struct stream_out *)stream;
4896 int status = -ENOSYS;
4897 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004898 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004899 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004900 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004901 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304902 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304903 status = compress_pause(out->compr);
4904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004905 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004906
Mingming Yin21854652016-04-13 11:54:02 -07004907 if (audio_extn_passthru_is_active()) {
4908 ALOGV("offload use case, pause passthru");
4909 audio_extn_passthru_on_pause(out);
4910 }
4911
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304912 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004913 audio_extn_dts_notify_playback_state(out->usecase, 0,
4914 out->sample_rate, popcount(out->channel_mask),
4915 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004916 }
4917 pthread_mutex_unlock(&out->lock);
4918 }
4919 return status;
4920}
4921
4922static int out_resume(struct audio_stream_out* stream)
4923{
4924 struct stream_out *out = (struct stream_out *)stream;
4925 int status = -ENOSYS;
4926 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004927 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004928 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004929 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004930 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004931 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304932 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304933 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004934 }
4935 if (!status) {
4936 out->offload_state = OFFLOAD_STATE_PLAYING;
4937 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304938 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004939 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4940 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004941 }
4942 pthread_mutex_unlock(&out->lock);
4943 }
4944 return status;
4945}
4946
4947static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4948{
4949 struct stream_out *out = (struct stream_out *)stream;
4950 int status = -ENOSYS;
4951 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004952 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004953 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004954 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4955 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4956 else
4957 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4958 pthread_mutex_unlock(&out->lock);
4959 }
4960 return status;
4961}
4962
4963static int out_flush(struct audio_stream_out* stream)
4964{
4965 struct stream_out *out = (struct stream_out *)stream;
4966 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004967 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004968 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004969 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004970 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4971 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004972 } else {
4973 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4974 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004975 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004976 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004977 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004978 return 0;
4979 }
4980 return -ENOSYS;
4981}
4982
Haynes Mathew George16081042017-05-31 17:16:49 -07004983static int out_stop(const struct audio_stream_out* stream)
4984{
4985 struct stream_out *out = (struct stream_out *)stream;
4986 struct audio_device *adev = out->dev;
4987 int ret = -ENOSYS;
4988
4989 ALOGV("%s", __func__);
4990 pthread_mutex_lock(&adev->lock);
4991 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4992 out->playback_started && out->pcm != NULL) {
4993 pcm_stop(out->pcm);
4994 ret = stop_output_stream(out);
4995 out->playback_started = false;
4996 }
4997 pthread_mutex_unlock(&adev->lock);
4998 return ret;
4999}
5000
5001static int out_start(const struct audio_stream_out* stream)
5002{
5003 struct stream_out *out = (struct stream_out *)stream;
5004 struct audio_device *adev = out->dev;
5005 int ret = -ENOSYS;
5006
5007 ALOGV("%s", __func__);
5008 pthread_mutex_lock(&adev->lock);
5009 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5010 !out->playback_started && out->pcm != NULL) {
5011 ret = start_output_stream(out);
5012 if (ret == 0) {
5013 out->playback_started = true;
5014 }
5015 }
5016 pthread_mutex_unlock(&adev->lock);
5017 return ret;
5018}
5019
5020/*
5021 * Modify config->period_count based on min_size_frames
5022 */
5023static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5024{
5025 int periodCountRequested = (min_size_frames + config->period_size - 1)
5026 / config->period_size;
5027 int periodCount = MMAP_PERIOD_COUNT_MIN;
5028
5029 ALOGV("%s original config.period_size = %d config.period_count = %d",
5030 __func__, config->period_size, config->period_count);
5031
5032 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5033 periodCount *= 2;
5034 }
5035 config->period_count = periodCount;
5036
5037 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5038}
5039
5040static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5041 int32_t min_size_frames,
5042 struct audio_mmap_buffer_info *info)
5043{
5044 struct stream_out *out = (struct stream_out *)stream;
5045 struct audio_device *adev = out->dev;
5046 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005047 unsigned int offset1 = 0;
5048 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005049 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005050 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005051
5052 ALOGV("%s", __func__);
5053 pthread_mutex_lock(&adev->lock);
5054
5055 if (info == NULL || min_size_frames == 0) {
5056 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5057 ret = -EINVAL;
5058 goto exit;
5059 }
5060 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5061 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5062 ret = -ENOSYS;
5063 goto exit;
5064 }
5065 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5066 if (out->pcm_device_id < 0) {
5067 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5068 __func__, out->pcm_device_id, out->usecase);
5069 ret = -EINVAL;
5070 goto exit;
5071 }
5072
5073 adjust_mmap_period_count(&out->config, min_size_frames);
5074
5075 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5076 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5077 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5078 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
5079 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5080 step = "open";
5081 ret = -ENODEV;
5082 goto exit;
5083 }
5084 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5085 if (ret < 0) {
5086 step = "begin";
5087 goto exit;
5088 }
5089 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
5090 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005091 ret = platform_get_mmap_data_fd(adev->platform,
5092 out->pcm_device_id, 0 /*playback*/,
5093 &info->shared_memory_fd,
5094 &mmap_size);
5095 if (ret < 0) {
5096 step = "get_mmap_fd";
5097 goto exit;
5098 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005099 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005100 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005101
5102 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5103 if (ret < 0) {
5104 step = "commit";
5105 goto exit;
5106 }
5107
5108 out->standby = false;
5109 ret = 0;
5110
5111 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5112 __func__, info->shared_memory_address, info->buffer_size_frames);
5113
5114exit:
5115 if (ret != 0) {
5116 if (out->pcm == NULL) {
5117 ALOGE("%s: %s - %d", __func__, step, ret);
5118 } else {
5119 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5120 pcm_close(out->pcm);
5121 out->pcm = NULL;
5122 }
5123 }
5124 pthread_mutex_unlock(&adev->lock);
5125 return ret;
5126}
5127
5128static int out_get_mmap_position(const struct audio_stream_out *stream,
5129 struct audio_mmap_position *position)
5130{
5131 struct stream_out *out = (struct stream_out *)stream;
5132 ALOGVV("%s", __func__);
5133 if (position == NULL) {
5134 return -EINVAL;
5135 }
5136 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005137 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005138 return -ENOSYS;
5139 }
5140 if (out->pcm == NULL) {
5141 return -ENOSYS;
5142 }
5143
5144 struct timespec ts = { 0, 0 };
5145 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5146 if (ret < 0) {
5147 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5148 return ret;
5149 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005150 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005151 return 0;
5152}
5153
5154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155/** audio_stream_in implementation **/
5156static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5157{
5158 struct stream_in *in = (struct stream_in *)stream;
5159
5160 return in->config.rate;
5161}
5162
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005163static int in_set_sample_rate(struct audio_stream *stream __unused,
5164 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165{
5166 return -ENOSYS;
5167}
5168
5169static size_t in_get_buffer_size(const struct audio_stream *stream)
5170{
5171 struct stream_in *in = (struct stream_in *)stream;
5172
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005173 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5174 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005175 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5176 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 -07005177 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5178 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305179 else if(audio_extn_cin_attached_usecase(in->usecase))
5180 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005181
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005182 return in->config.period_size * in->af_period_multiplier *
5183 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005184}
5185
5186static uint32_t in_get_channels(const struct audio_stream *stream)
5187{
5188 struct stream_in *in = (struct stream_in *)stream;
5189
5190 return in->channel_mask;
5191}
5192
5193static audio_format_t in_get_format(const struct audio_stream *stream)
5194{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005195 struct stream_in *in = (struct stream_in *)stream;
5196
5197 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198}
5199
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005200static int in_set_format(struct audio_stream *stream __unused,
5201 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202{
5203 return -ENOSYS;
5204}
5205
5206static int in_standby(struct audio_stream *stream)
5207{
5208 struct stream_in *in = (struct stream_in *)stream;
5209 struct audio_device *adev = in->dev;
5210 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305211 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5212 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005213 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305214
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005215 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005216 if (!in->standby && in->is_st_session) {
5217 ALOGD("%s: sound trigger pcm stop lab", __func__);
5218 audio_extn_sound_trigger_stop_lab(in);
5219 in->standby = 1;
5220 }
5221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005223 if (adev->adm_deregister_stream)
5224 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5225
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005226 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005228 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005229 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005230 voice_extn_compress_voip_close_input_stream(stream);
5231 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005232 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5233 do_stop = in->capture_started;
5234 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005235 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305236 if (audio_extn_cin_attached_usecase(in->usecase))
5237 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005238 }
5239
5240 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005241 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005242 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005243 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005244 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005245 in->pcm = NULL;
5246 }
5247 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005248 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005249 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250 }
5251 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005252 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253 return status;
5254}
5255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005256static int in_dump(const struct audio_stream *stream __unused,
5257 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258{
5259 return 0;
5260}
5261
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305262static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5263{
5264 if (!stream || !parms)
5265 return;
5266
5267 struct stream_in *in = (struct stream_in *)stream;
5268 struct audio_device *adev = in->dev;
5269
5270 card_status_t status;
5271 int card;
5272 if (parse_snd_card_status(parms, &card, &status) < 0)
5273 return;
5274
5275 pthread_mutex_lock(&adev->lock);
5276 bool valid_cb = (card == adev->snd_card);
5277 pthread_mutex_unlock(&adev->lock);
5278
5279 if (!valid_cb)
5280 return;
5281
5282 lock_input_stream(in);
5283 if (in->card_status != status)
5284 in->card_status = status;
5285 pthread_mutex_unlock(&in->lock);
5286
5287 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5288 use_case_table[in->usecase],
5289 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5290
5291 // a better solution would be to report error back to AF and let
5292 // it put the stream to standby
5293 if (status == CARD_STATUS_OFFLINE)
5294 in_standby(&in->stream.common);
5295
5296 return;
5297}
5298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5300{
5301 struct stream_in *in = (struct stream_in *)stream;
5302 struct audio_device *adev = in->dev;
5303 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005305 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305307 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005308 parms = str_parms_create_str(kvpairs);
5309
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305310 if (!parms)
5311 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005312 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005313 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005314
5315 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5316 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005317 val = atoi(value);
5318 /* no audio source uses val == 0 */
5319 if ((in->source != val) && (val != 0)) {
5320 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005321 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5322 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5323 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005324 (in->config.rate == 8000 || in->config.rate == 16000 ||
5325 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005326 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005327 err = voice_extn_compress_voip_open_input_stream(in);
5328 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005329 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005330 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005331 }
5332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005333 }
5334 }
5335
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005336 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5337 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005339 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5340
5341 // Workaround: If routing to an non existing usb device, fail gracefully
5342 // The routing request will otherwise block during 10 second
5343 int card;
5344 if (audio_is_usb_in_device(val) &&
5345 (card = get_alive_usb_card(parms)) >= 0) {
5346
5347 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5348 ret = -ENOSYS;
5349 } else {
5350
5351 in->device = val;
5352 /* If recording is in progress, change the tx device to new device */
5353 if (!in->standby && !in->is_st_session) {
5354 ALOGV("update input routing change");
5355 // inform adm before actual routing to prevent glitches.
5356 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005357 adev->adm_on_routing_change(adev->adm_data,
5358 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005359 ret = select_devices(adev, in->usecase);
5360 }
5361 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005362 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363 }
5364 }
5365
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305366 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5367 if (err >= 0) {
5368 strlcpy(in->profile, value, sizeof(in->profile));
5369 ALOGV("updating stream profile with value '%s'", in->profile);
5370 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5371 &adev->streams_input_cfg_list,
5372 in->device, in->flags, in->format,
5373 in->sample_rate, in->bit_width,
5374 in->profile, &in->app_type_cfg);
5375 }
5376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005377 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005378 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379
5380 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305381error:
Eric Laurent994a6932013-07-17 11:51:42 -07005382 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005383 return ret;
5384}
5385
5386static char* in_get_parameters(const struct audio_stream *stream,
5387 const char *keys)
5388{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005389 struct stream_in *in = (struct stream_in *)stream;
5390 struct str_parms *query = str_parms_create_str(keys);
5391 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005392 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005393
5394 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005395 if (reply) {
5396 str_parms_destroy(reply);
5397 }
5398 if (query) {
5399 str_parms_destroy(query);
5400 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005401 ALOGE("in_get_parameters: failed to create query or reply");
5402 return NULL;
5403 }
5404
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005405 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005406
5407 voice_extn_in_get_parameters(in, query, reply);
5408
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005409 stream_get_parameter_channels(query, reply,
5410 &in->supported_channel_masks[0]);
5411 stream_get_parameter_formats(query, reply,
5412 &in->supported_formats[0]);
5413 stream_get_parameter_rates(query, reply,
5414 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005415 str = str_parms_to_str(reply);
5416 str_parms_destroy(query);
5417 str_parms_destroy(reply);
5418
5419 ALOGV("%s: exit: returns - %s", __func__, str);
5420 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005421}
5422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005423static int in_set_gain(struct audio_stream_in *stream __unused,
5424 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005425{
5426 return 0;
5427}
5428
5429static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5430 size_t bytes)
5431{
5432 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305433
5434 if (in == NULL) {
5435 ALOGE("%s: stream_in ptr is NULL", __func__);
5436 return -EINVAL;
5437 }
5438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305440 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305441 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005443 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305444
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005445 if (in->is_st_session) {
5446 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5447 /* Read from sound trigger HAL */
5448 audio_extn_sound_trigger_read(in, buffer, bytes);
5449 pthread_mutex_unlock(&in->lock);
5450 return bytes;
5451 }
5452
Haynes Mathew George16081042017-05-31 17:16:49 -07005453 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5454 ret = -ENOSYS;
5455 goto exit;
5456 }
5457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005459 pthread_mutex_lock(&adev->lock);
5460 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5461 ret = voice_extn_compress_voip_start_input_stream(in);
5462 else
5463 ret = start_input_stream(in);
5464 pthread_mutex_unlock(&adev->lock);
5465 if (ret != 0) {
5466 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467 }
5468 in->standby = 0;
5469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005470
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005471 // what's the duration requested by the client?
5472 long ns = 0;
5473
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305474 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005475 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5476 in->config.rate;
5477
5478 request_in_focus(in, ns);
5479 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005480
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305481 if (audio_extn_cin_attached_usecase(in->usecase)) {
5482 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5483 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305484 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005485 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305486 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005487 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005488 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005489 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005490 } else if (audio_extn_ffv_get_stream() == in) {
5491 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305492 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005493 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305494 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5495 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5496 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5497 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305498 ret = -EINVAL;
5499 goto exit;
5500 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305501 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305502 ret = -errno;
5503 }
5504 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305505 /* bytes read is always set to bytes for non compress usecases */
5506 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 }
5508
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005509 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511 /*
5512 * Instead of writing zeroes here, we could trust the hardware
5513 * to always provide zeroes when muted.
5514 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305515 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5516 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005517 memset(buffer, 0, bytes);
5518
5519exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005520 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305521 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005522 pthread_mutex_unlock(&in->lock);
5523
5524 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305525 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305526 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305527 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305528 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305529 in->standby = true;
5530 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305531 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5532 bytes_read = bytes;
5533 memset(buffer, 0, bytes);
5534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005535 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005536 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305537 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305538 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305540 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005541}
5542
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005543static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005544{
5545 return 0;
5546}
5547
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005548static int add_remove_audio_effect(const struct audio_stream *stream,
5549 effect_handle_t effect,
5550 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005552 struct stream_in *in = (struct stream_in *)stream;
5553 int status = 0;
5554 effect_descriptor_t desc;
5555
5556 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005557 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5558
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005559 if (status != 0)
5560 return status;
5561
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005562 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005563 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08005564 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5565 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005566 in->enable_aec != enable &&
5567 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5568 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005569 if (!in->standby) {
5570 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5571 select_devices(in->dev, in->usecase);
5572 }
5573
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005574 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005575 if (in->enable_ns != enable &&
5576 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5577 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005578 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08005579 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
5580 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005581 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5582 select_devices(in->dev, in->usecase);
5583 } else
5584 select_devices(in->dev, in->usecase);
5585 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005586 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005587 pthread_mutex_unlock(&in->dev->lock);
5588 pthread_mutex_unlock(&in->lock);
5589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590 return 0;
5591}
5592
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005593static int in_add_audio_effect(const struct audio_stream *stream,
5594 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005595{
Eric Laurent994a6932013-07-17 11:51:42 -07005596 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005597 return add_remove_audio_effect(stream, effect, true);
5598}
5599
5600static int in_remove_audio_effect(const struct audio_stream *stream,
5601 effect_handle_t effect)
5602{
Eric Laurent994a6932013-07-17 11:51:42 -07005603 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005604 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605}
5606
Haynes Mathew George16081042017-05-31 17:16:49 -07005607static int in_stop(const struct audio_stream_in* stream)
5608{
5609 struct stream_in *in = (struct stream_in *)stream;
5610 struct audio_device *adev = in->dev;
5611
5612 int ret = -ENOSYS;
5613 ALOGV("%s", __func__);
5614 pthread_mutex_lock(&adev->lock);
5615 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5616 in->capture_started && in->pcm != NULL) {
5617 pcm_stop(in->pcm);
5618 ret = stop_input_stream(in);
5619 in->capture_started = false;
5620 }
5621 pthread_mutex_unlock(&adev->lock);
5622 return ret;
5623}
5624
5625static int in_start(const struct audio_stream_in* stream)
5626{
5627 struct stream_in *in = (struct stream_in *)stream;
5628 struct audio_device *adev = in->dev;
5629 int ret = -ENOSYS;
5630
5631 ALOGV("%s in %p", __func__, in);
5632 pthread_mutex_lock(&adev->lock);
5633 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5634 !in->capture_started && in->pcm != NULL) {
5635 if (!in->capture_started) {
5636 ret = start_input_stream(in);
5637 if (ret == 0) {
5638 in->capture_started = true;
5639 }
5640 }
5641 }
5642 pthread_mutex_unlock(&adev->lock);
5643 return ret;
5644}
5645
5646static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5647 int32_t min_size_frames,
5648 struct audio_mmap_buffer_info *info)
5649{
5650 struct stream_in *in = (struct stream_in *)stream;
5651 struct audio_device *adev = in->dev;
5652 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005653 unsigned int offset1 = 0;
5654 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005655 const char *step = "";
5656
5657 pthread_mutex_lock(&adev->lock);
5658 ALOGV("%s in %p", __func__, in);
5659
5660 if (info == NULL || min_size_frames == 0) {
5661 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5662 ret = -EINVAL;
5663 goto exit;
5664 }
5665 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5666 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5667 ALOGV("%s in %p", __func__, in);
5668 ret = -ENOSYS;
5669 goto exit;
5670 }
5671 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5672 if (in->pcm_device_id < 0) {
5673 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5674 __func__, in->pcm_device_id, in->usecase);
5675 ret = -EINVAL;
5676 goto exit;
5677 }
5678
5679 adjust_mmap_period_count(&in->config, min_size_frames);
5680
5681 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5682 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5683 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5684 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5685 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5686 step = "open";
5687 ret = -ENODEV;
5688 goto exit;
5689 }
5690
5691 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5692 if (ret < 0) {
5693 step = "begin";
5694 goto exit;
5695 }
5696 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5697 info->burst_size_frames = in->config.period_size;
5698 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5699
5700 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5701 info->buffer_size_frames));
5702
5703 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5704 if (ret < 0) {
5705 step = "commit";
5706 goto exit;
5707 }
5708
5709 in->standby = false;
5710 ret = 0;
5711
5712 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5713 __func__, info->shared_memory_address, info->buffer_size_frames);
5714
5715exit:
5716 if (ret != 0) {
5717 if (in->pcm == NULL) {
5718 ALOGE("%s: %s - %d", __func__, step, ret);
5719 } else {
5720 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5721 pcm_close(in->pcm);
5722 in->pcm = NULL;
5723 }
5724 }
5725 pthread_mutex_unlock(&adev->lock);
5726 return ret;
5727}
5728
5729static int in_get_mmap_position(const struct audio_stream_in *stream,
5730 struct audio_mmap_position *position)
5731{
5732 struct stream_in *in = (struct stream_in *)stream;
5733 ALOGVV("%s", __func__);
5734 if (position == NULL) {
5735 return -EINVAL;
5736 }
5737 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5738 return -ENOSYS;
5739 }
5740 if (in->pcm == NULL) {
5741 return -ENOSYS;
5742 }
5743 struct timespec ts = { 0, 0 };
5744 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5745 if (ret < 0) {
5746 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5747 return ret;
5748 }
5749 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5750 return 0;
5751}
5752
Naresh Tannirudcb47c52018-06-25 16:23:32 +05305753static int in_get_active_microphones(const struct audio_stream_in *stream,
5754 struct audio_microphone_characteristic_t *mic_array,
5755 size_t *mic_count) {
5756 struct stream_in *in = (struct stream_in *)stream;
5757 struct audio_device *adev = in->dev;
5758 ALOGVV("%s", __func__);
5759
5760 lock_input_stream(in);
5761 pthread_mutex_lock(&adev->lock);
5762 int ret = platform_get_active_microphones(adev->platform,
5763 audio_channel_count_from_in_mask(in->channel_mask),
5764 in->usecase, mic_array, mic_count);
5765 pthread_mutex_unlock(&adev->lock);
5766 pthread_mutex_unlock(&in->lock);
5767
5768 return ret;
5769}
5770
5771static int adev_get_microphones(const struct audio_hw_device *dev,
5772 struct audio_microphone_characteristic_t *mic_array,
5773 size_t *mic_count) {
5774 struct audio_device *adev = (struct audio_device *)dev;
5775 ALOGVV("%s", __func__);
5776
5777 pthread_mutex_lock(&adev->lock);
5778 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
5779 pthread_mutex_unlock(&adev->lock);
5780
5781 return ret;
5782}
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305783int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005784 audio_io_handle_t handle,
5785 audio_devices_t devices,
5786 audio_output_flags_t flags,
5787 struct audio_config *config,
5788 struct audio_stream_out **stream_out,
5789 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005790{
5791 struct audio_device *adev = (struct audio_device *)dev;
5792 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305793 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005794 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005795 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305796 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005797 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5798 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5799 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5800 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005801
kunleizdff872d2018-08-20 14:40:33 +08005802 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08005803 is_usb_dev = false;
5804 devices = AUDIO_DEVICE_OUT_SPEAKER;
5805 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
5806 __func__, devices);
5807 }
5808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005809 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005811 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5812
Mingming Yin3a941d42016-02-17 18:08:05 -08005813 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5814 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305815 devices, flags, &out->stream);
5816
5817
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005818 if (!out) {
5819 return -ENOMEM;
5820 }
5821
Haynes Mathew George204045b2015-02-25 20:32:03 -08005822 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005823 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305824 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005825 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005826 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005828 if (devices == AUDIO_DEVICE_NONE)
5829 devices = AUDIO_DEVICE_OUT_SPEAKER;
5830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005831 out->flags = flags;
5832 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005833 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005834 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005835 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305836 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305837 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5838 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5839 else
5840 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005841 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005842 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005843 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305844 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305845 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305846 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005847 out->hal_output_suspend_supported = 0;
5848 out->dynamic_pm_qos_config_supported = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305850 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305851 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005852 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5853
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005854 if (audio_is_linear_pcm(out->format) &&
5855 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5856 pthread_mutex_lock(&adev->lock);
5857 if (is_hdmi) {
5858 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5859 ret = read_hdmi_sink_caps(out);
5860 } else if (is_usb_dev) {
5861 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5862 &config->format,
5863 &out->supported_formats[0],
5864 MAX_SUPPORTED_FORMATS,
5865 &config->channel_mask,
5866 &out->supported_channel_masks[0],
5867 MAX_SUPPORTED_CHANNEL_MASKS,
5868 &config->sample_rate,
5869 &out->supported_sample_rates[0],
5870 MAX_SUPPORTED_SAMPLE_RATES);
5871 ALOGV("plugged dev USB ret %d", ret);
5872 } else {
5873 ret = -1;
5874 }
5875 pthread_mutex_unlock(&adev->lock);
5876 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005877 if (ret == -ENOSYS) {
5878 /* ignore and go with default */
5879 ret = 0;
5880 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005881 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005882 goto error_open;
5883 }
5884 }
5885 }
5886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005888#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005889 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5890 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5891 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5892 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5893 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5894 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5895
5896 out->config = default_pcm_config_voip_copp;
5897 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5898 out->config.rate = out->sample_rate;
5899
5900#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305901 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005902 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005903 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005904 ret = voice_extn_compress_voip_open_output_stream(out);
5905 if (ret != 0) {
5906 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5907 __func__, ret);
5908 goto error_open;
5909 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005910#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005911 } else if (audio_is_linear_pcm(out->format) &&
5912 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5913 out->channel_mask = config->channel_mask;
5914 out->sample_rate = config->sample_rate;
5915 out->format = config->format;
5916 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5917 // does this change?
5918 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5919 out->config.rate = config->sample_rate;
5920 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5921 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5922 audio_bytes_per_sample(config->format));
5923 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005924 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305925 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305926 pthread_mutex_lock(&adev->lock);
5927 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5928 pthread_mutex_unlock(&adev->lock);
5929
5930 // reject offload during card offline to allow
5931 // fallback to s/w paths
5932 if (offline) {
5933 ret = -ENODEV;
5934 goto error_open;
5935 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005937 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5938 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5939 ALOGE("%s: Unsupported Offload information", __func__);
5940 ret = -EINVAL;
5941 goto error_open;
5942 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005943
Atul Khare3fa6e542017-08-09 00:56:17 +05305944 if (config->offload_info.format == 0)
5945 config->offload_info.format = config->format;
5946 if (config->offload_info.sample_rate == 0)
5947 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005948
Mingming Yin90310102013-11-13 16:57:00 -08005949 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305950 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005951 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005952 ret = -EINVAL;
5953 goto error_open;
5954 }
5955
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005956 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5957 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5958 (audio_extn_passthru_is_passthrough_stream(out)) &&
5959 !((config->sample_rate == 48000) ||
5960 (config->sample_rate == 96000) ||
5961 (config->sample_rate == 192000))) {
5962 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5963 __func__, config->sample_rate, config->offload_info.format);
5964 ret = -EINVAL;
5965 goto error_open;
5966 }
5967
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005968 out->compr_config.codec = (struct snd_codec *)
5969 calloc(1, sizeof(struct snd_codec));
5970
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005971 if (!out->compr_config.codec) {
5972 ret = -ENOMEM;
5973 goto error_open;
5974 }
5975
Dhananjay Kumarac341582017-02-23 23:42:25 +05305976 out->stream.pause = out_pause;
5977 out->stream.resume = out_resume;
5978 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305979 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305980 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005981 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305982 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005983 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305984 } else {
5985 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5986 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005987 }
vivek mehta446c3962015-09-14 10:57:35 -07005988
5989 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005990 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5991 config->format == 0 && config->sample_rate == 0 &&
5992 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005993 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005994 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5995 } else {
5996 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5997 ret = -EEXIST;
5998 goto error_open;
5999 }
vivek mehta446c3962015-09-14 10:57:35 -07006000 }
6001
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006002 if (config->offload_info.channel_mask)
6003 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006004 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006005 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006006 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006007 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306008 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006009 ret = -EINVAL;
6010 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006011 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006012
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006013 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006014 out->sample_rate = config->offload_info.sample_rate;
6015
Mingming Yin3ee55c62014-08-04 14:23:35 -07006016 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006017
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306018 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306019 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306020 audio_extn_dolby_send_ddp_endp_params(adev);
6021 audio_extn_dolby_set_dmid(adev);
6022 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006023
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006024 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006025 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006026 out->compr_config.codec->bit_rate =
6027 config->offload_info.bit_rate;
6028 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306029 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006030 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306031 /* Update bit width only for non passthrough usecases.
6032 * For passthrough usecases, the output will always be opened @16 bit
6033 */
6034 if (!audio_extn_passthru_is_passthrough_stream(out))
6035 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306036
6037 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
6038 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
6039 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
6040
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006041 /*TODO: Do we need to change it for passthrough */
6042 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006043
Manish Dewangana6fc5442015-08-24 20:30:31 +05306044 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
6045 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306046 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05306047 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05306048 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
6049 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306050
6051 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
6052 AUDIO_FORMAT_PCM) {
6053
6054 /*Based on platform support, configure appropriate alsa format for corresponding
6055 *hal input format.
6056 */
6057 out->compr_config.codec->format = hal_format_to_alsa(
6058 config->offload_info.format);
6059
Ashish Jain83a6cc22016-06-28 14:34:17 +05306060 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05306061 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306062 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306063
Dhananjay Kumarac341582017-02-23 23:42:25 +05306064 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05306065 *hal input format and alsa format might differ based on platform support.
6066 */
6067 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05306068 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306069
6070 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
6071
6072 /* Check if alsa session is configured with the same format as HAL input format,
6073 * if not then derive correct fragment size needed to accomodate the
6074 * conversion of HAL input format to alsa format.
6075 */
6076 audio_extn_utils_update_direct_pcm_fragment_size(out);
6077
6078 /*if hal input and output fragment size is different this indicates HAL input format is
6079 *not same as the alsa format
6080 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306081 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306082 /*Allocate a buffer to convert input data to the alsa configured format.
6083 *size of convert buffer is equal to the size required to hold one fragment size
6084 *worth of pcm data, this is because flinger does not write more than fragment_size
6085 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05306086 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
6087 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05306088 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
6089 ret = -ENOMEM;
6090 goto error_open;
6091 }
6092 }
6093 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
6094 out->compr_config.fragment_size =
6095 audio_extn_passthru_get_buffer_size(&config->offload_info);
6096 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6097 } else {
6098 out->compr_config.fragment_size =
6099 platform_get_compress_offload_buffer_size(&config->offload_info);
6100 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
6101 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07006102
Naresh Tanniruee3499a2017-01-05 14:05:35 +05306103 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6104 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
6105 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07006106 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05306107 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006108
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05306109 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
6110 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
6111 }
6112
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006113 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
6114 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006115
Manish Dewangan69426c82017-01-30 17:35:36 +05306116 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
6117 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
6118 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
6119 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
6120 out->render_mode = RENDER_MODE_AUDIO_MASTER;
6121 } else {
6122 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
6123 }
Alexy Josephaa54c872014-12-03 02:46:47 -08006124
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05306125 memset(&out->channel_map_param, 0,
6126 sizeof(struct audio_out_channel_map_param));
6127
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006128 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306129 out->send_next_track_params = false;
6130 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006131 out->offload_state = OFFLOAD_STATE_IDLE;
6132 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08006133 out->writeAt.tv_sec = 0;
6134 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006135
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006136 audio_extn_dts_create_state_notifier_node(out->usecase);
6137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006138 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
6139 __func__, config->offload_info.version,
6140 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05306141
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306142 /* Check if DSD audio format is supported in codec
6143 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306144 */
6145
6146 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306147 (!platform_check_codec_dsd_support(adev->platform) ||
6148 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306149 ret = -EINVAL;
6150 goto error_open;
6151 }
6152
Ashish Jain5106d362016-05-11 19:23:33 +05306153 /* Disable gapless if any of the following is true
6154 * passthrough playback
6155 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05306156 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05306157 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306158 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306159 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07006160 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05306161 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306162 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05306163 check_and_set_gapless_mode(adev, false);
6164 } else
6165 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07006166
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306167 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07006168 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6169 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05306170 if (config->format == AUDIO_FORMAT_DSD) {
6171 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
6172 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
6173 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07006174
6175 create_offload_callback_thread(out);
6176
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006177 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006178 switch (config->sample_rate) {
6179 case 0:
6180 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6181 break;
6182 case 8000:
6183 case 16000:
6184 case 48000:
6185 out->sample_rate = config->sample_rate;
6186 break;
6187 default:
6188 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
6189 config->sample_rate);
6190 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6191 ret = -EINVAL;
6192 goto error_open;
6193 }
6194 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
6195 switch (config->channel_mask) {
6196 case AUDIO_CHANNEL_NONE:
6197 case AUDIO_CHANNEL_OUT_STEREO:
6198 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6199 break;
6200 default:
6201 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
6202 config->channel_mask);
6203 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6204 ret = -EINVAL;
6205 goto error_open;
6206 }
6207 switch (config->format) {
6208 case AUDIO_FORMAT_DEFAULT:
6209 case AUDIO_FORMAT_PCM_16_BIT:
6210 out->format = AUDIO_FORMAT_PCM_16_BIT;
6211 break;
6212 default:
6213 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
6214 config->format);
6215 config->format = AUDIO_FORMAT_PCM_16_BIT;
6216 ret = -EINVAL;
6217 goto error_open;
6218 }
6219
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306220 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006221 if (ret != 0) {
6222 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006223 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07006224 goto error_open;
6225 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006226 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006227 if (config->sample_rate == 0)
6228 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6229 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6230 config->sample_rate != 8000) {
6231 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6232 ret = -EINVAL;
6233 goto error_open;
6234 }
6235 out->sample_rate = config->sample_rate;
6236 out->config.rate = config->sample_rate;
6237 if (config->format == AUDIO_FORMAT_DEFAULT)
6238 config->format = AUDIO_FORMAT_PCM_16_BIT;
6239 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6240 config->format = AUDIO_FORMAT_PCM_16_BIT;
6241 ret = -EINVAL;
6242 goto error_open;
6243 }
6244 out->format = config->format;
6245 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
6246 out->config = pcm_config_afe_proxy_playback;
6247 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006248 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05306249 unsigned int channels = 0;
6250 /*Update config params to default if not set by the caller*/
6251 if (config->sample_rate == 0)
6252 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6253 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6254 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6255 if (config->format == AUDIO_FORMAT_DEFAULT)
6256 config->format = AUDIO_FORMAT_PCM_16_BIT;
6257
6258 channels = audio_channel_count_from_out_mask(out->channel_mask);
6259
Varun Balaraje49253e2017-07-06 19:48:56 +05306260 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6261 out->usecase = get_interactive_usecase(adev);
6262 out->config = pcm_config_low_latency;
6263 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306264 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006265 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6266 out->flags);
6267 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006268 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6269 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6270 out->config = pcm_config_mmap_playback;
6271 out->stream.start = out_start;
6272 out->stream.stop = out_stop;
6273 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6274 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306275 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6276 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006277 out->hal_output_suspend_supported =
6278 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6279 out->dynamic_pm_qos_config_supported =
6280 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6281 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006282 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6283 } else {
6284 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6285 //the mixer path will be a string similar to "low-latency-playback resume"
6286 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6287 strlcat(out->pm_qos_mixer_path,
6288 " resume", MAX_MIXER_PATH_LEN);
6289 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6290 out->pm_qos_mixer_path);
6291 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306292 out->config = pcm_config_low_latency;
6293 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6294 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6295 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306296 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6297 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6298 if (out->config.period_size <= 0) {
6299 ALOGE("Invalid configuration period size is not valid");
6300 ret = -EINVAL;
6301 goto error_open;
6302 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306303 } else {
6304 /* primary path is the default path selected if no other outputs are available/suitable */
6305 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6306 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6307 }
6308 out->hal_ip_format = format = out->format;
6309 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6310 out->hal_op_format = pcm_format_to_hal(out->config.format);
6311 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6312 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006313 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306314 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306315 if (out->hal_ip_format != out->hal_op_format) {
6316 uint32_t buffer_size = out->config.period_size *
6317 format_to_bitwidth_table[out->hal_op_format] *
6318 out->config.channels;
6319 out->convert_buffer = calloc(1, buffer_size);
6320 if (out->convert_buffer == NULL){
6321 ALOGE("Allocation failed for convert buffer for size %d",
6322 out->compr_config.fragment_size);
6323 ret = -ENOMEM;
6324 goto error_open;
6325 }
6326 ALOGD("Convert buffer allocated of size %d", buffer_size);
6327 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006328 }
6329
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006330 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6331 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306332
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006333 /* TODO remove this hardcoding and check why width is zero*/
6334 if (out->bit_width == 0)
6335 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306336 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006337 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006338 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306339 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306340 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006341 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6342 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6343 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006344 if(adev->primary_output == NULL)
6345 adev->primary_output = out;
6346 else {
6347 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006348 ret = -EEXIST;
6349 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006350 }
6351 }
6352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006353 /* Check if this usecase is already existing */
6354 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006355 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6356 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006357 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006358 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006359 ret = -EEXIST;
6360 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006361 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006363 pthread_mutex_unlock(&adev->lock);
6364
6365 out->stream.common.get_sample_rate = out_get_sample_rate;
6366 out->stream.common.set_sample_rate = out_set_sample_rate;
6367 out->stream.common.get_buffer_size = out_get_buffer_size;
6368 out->stream.common.get_channels = out_get_channels;
6369 out->stream.common.get_format = out_get_format;
6370 out->stream.common.set_format = out_set_format;
6371 out->stream.common.standby = out_standby;
6372 out->stream.common.dump = out_dump;
6373 out->stream.common.set_parameters = out_set_parameters;
6374 out->stream.common.get_parameters = out_get_parameters;
6375 out->stream.common.add_audio_effect = out_add_audio_effect;
6376 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6377 out->stream.get_latency = out_get_latency;
6378 out->stream.set_volume = out_set_volume;
6379 out->stream.write = out_write;
6380 out->stream.get_render_position = out_get_render_position;
6381 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006382 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006383
Haynes Mathew George16081042017-05-31 17:16:49 -07006384 if (out->realtime)
6385 out->af_period_multiplier = af_period_multiplier;
6386 else
6387 out->af_period_multiplier = 1;
6388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006389 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006390 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006391 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392
6393 config->format = out->stream.common.get_format(&out->stream.common);
6394 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6395 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05306396 register_format(out->format, out->supported_formats);
6397 register_channel_mask(out->channel_mask, out->supported_channel_masks);
6398 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006399
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306400 /*
6401 By locking output stream before registering, we allow the callback
6402 to update stream's state only after stream's initial state is set to
6403 adev state.
6404 */
6405 lock_output_stream(out);
6406 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6407 pthread_mutex_lock(&adev->lock);
6408 out->card_status = adev->card_status;
6409 pthread_mutex_unlock(&adev->lock);
6410 pthread_mutex_unlock(&out->lock);
6411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006412 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306413 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006414 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006415
6416 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6417 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6418 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006419 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306420 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006421 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006422 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306423 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006424 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6425 out->usecase, PCM_PLAYBACK);
6426 hdlr_stream_cfg.flags = out->flags;
6427 hdlr_stream_cfg.type = PCM_PLAYBACK;
6428 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6429 &hdlr_stream_cfg);
6430 if (ret) {
6431 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6432 out->adsp_hdlr_stream_handle = NULL;
6433 }
6434 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306435 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006436 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006437 if (ret < 0) {
6438 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6439 out->ip_hdlr_handle = NULL;
6440 }
6441 }
Eric Laurent994a6932013-07-17 11:51:42 -07006442 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006443 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006444
6445error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306446 if (out->convert_buffer)
6447 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006448 free(out);
6449 *stream_out = NULL;
6450 ALOGD("%s: exit: ret %d", __func__, ret);
6451 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452}
6453
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306454void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006455 struct audio_stream_out *stream)
6456{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006457 struct stream_out *out = (struct stream_out *)stream;
6458 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006459 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006460
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006461 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306462
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306463 // must deregister from sndmonitor first to prevent races
6464 // between the callback and close_stream
6465 audio_extn_snd_mon_unregister_listener(out);
6466
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006467 /* close adsp hdrl session before standby */
6468 if (out->adsp_hdlr_stream_handle) {
6469 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6470 if (ret)
6471 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6472 out->adsp_hdlr_stream_handle = NULL;
6473 }
6474
Manish Dewangan21a850a2017-08-14 12:03:55 +05306475 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006476 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6477 out->ip_hdlr_handle = NULL;
6478 }
6479
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006480 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306481 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006482 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306483 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306484 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006485 if(ret != 0)
6486 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6487 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006488 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006489 out_standby(&stream->common);
6490
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006491 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006492 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006493 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006494 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006495 if (out->compr_config.codec != NULL)
6496 free(out->compr_config.codec);
6497 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006498
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306499 out->a2dp_compress_mute = false;
6500
Varun Balaraje49253e2017-07-06 19:48:56 +05306501 if (is_interactive_usecase(out->usecase))
6502 free_interactive_usecase(adev, out->usecase);
6503
Ashish Jain83a6cc22016-06-28 14:34:17 +05306504 if (out->convert_buffer != NULL) {
6505 free(out->convert_buffer);
6506 out->convert_buffer = NULL;
6507 }
6508
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006509 if (adev->voice_tx_output == out)
6510 adev->voice_tx_output = NULL;
6511
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306512 if (adev->primary_output == out)
6513 adev->primary_output = NULL;
6514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006515 pthread_cond_destroy(&out->cond);
6516 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006517 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006518 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006519}
6520
6521static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6522{
6523 struct audio_device *adev = (struct audio_device *)dev;
6524 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006525 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006526 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006527 int ret;
6528 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006529
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006530 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006531 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006532
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306533 if (!parms)
6534 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306535
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306536 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6537 if (ret >= 0) {
6538 /* When set to false, HAL should disable EC and NS */
6539 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6540 adev->bt_sco_on = true;
6541 else
6542 adev->bt_sco_on = false;
6543 }
6544
Naresh Tanniru4c630392014-05-12 01:05:52 +05306545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006546 status = voice_set_parameters(adev, parms);
6547 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006548 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006549
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006550 status = platform_set_parameters(adev->platform, parms);
6551 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006552 goto done;
6553
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006554 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6555 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006556 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006557 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6558 adev->bluetooth_nrec = true;
6559 else
6560 adev->bluetooth_nrec = false;
6561 }
6562
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006563 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6564 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006565 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6566 adev->screen_off = false;
6567 else
6568 adev->screen_off = true;
6569 }
6570
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006571 ret = str_parms_get_int(parms, "rotation", &val);
6572 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006573 bool reverse_speakers = false;
6574 switch(val) {
6575 // FIXME: note that the code below assumes that the speakers are in the correct placement
6576 // relative to the user when the device is rotated 90deg from its default rotation. This
6577 // assumption is device-specific, not platform-specific like this code.
6578 case 270:
6579 reverse_speakers = true;
6580 break;
6581 case 0:
6582 case 90:
6583 case 180:
6584 break;
6585 default:
6586 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006587 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006588 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006589 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006590 // check and set swap
6591 // - check if orientation changed and speaker active
6592 // - set rotation and cache the rotation value
6593 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006594 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006595 }
6596
Mingming Yin514a8bc2014-07-29 15:22:21 -07006597 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6598 if (ret >= 0) {
6599 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6600 adev->bt_wb_speech_enabled = true;
6601 else
6602 adev->bt_wb_speech_enabled = false;
6603 }
6604
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006605 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6606 if (ret >= 0) {
6607 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306608 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006609 if (audio_is_output_device(val) &&
6610 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006611 ALOGV("cache new ext disp type and edid");
6612 ret = platform_get_ext_disp_type(adev->platform);
6613 if (ret < 0) {
6614 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05306615 } else {
6616 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006617 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306618 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006619 /*
6620 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6621 * Per AudioPolicyManager, USB device is higher priority than WFD.
6622 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6623 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6624 * starting voice call on USB
6625 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006626 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306627 if (ret >= 0)
6628 audio_extn_usb_add_device(device, atoi(value));
6629
Zhou Song6f862822017-11-06 17:27:57 +08006630 if (!audio_extn_usb_is_tunnel_supported()) {
6631 ALOGV("detected USB connect .. disable proxy");
6632 adev->allow_afe_proxy_usage = false;
6633 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006634 }
6635 }
6636
6637 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6638 if (ret >= 0) {
6639 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306640 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006641 /*
6642 * The HDMI / Displayport disconnect handling has been moved to
6643 * audio extension to ensure that its parameters are not
6644 * invalidated prior to updating sysfs of the disconnect event
6645 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6646 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306647 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006648 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306649 if (ret >= 0)
6650 audio_extn_usb_remove_device(device, atoi(value));
6651
Zhou Song6f862822017-11-06 17:27:57 +08006652 if (!audio_extn_usb_is_tunnel_supported()) {
6653 ALOGV("detected USB disconnect .. enable proxy");
6654 adev->allow_afe_proxy_usage = true;
6655 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006656 }
6657 }
6658
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306659 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6660 if (ret >= 0) {
6661 struct audio_usecase *usecase;
6662 struct listnode *node;
6663 list_for_each(node, &adev->usecase_list) {
6664 usecase = node_to_item(node, struct audio_usecase, list);
6665 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006666 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306667 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006668
6669 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306670 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006671 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306672 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306673 //force device switch to re configure encoder
6674 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306675 audio_extn_a2dp_set_handoff_mode(false);
6676 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306677 break;
6678 }
6679 }
6680 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006681
6682 //handle vr audio setparam
6683 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6684 value, sizeof(value));
6685 if (ret >= 0) {
6686 ALOGI("Setting vr mode to be %s", value);
6687 if (!strncmp(value, "true", 4)) {
6688 adev->vr_audio_mode_enabled = true;
6689 ALOGI("Setting vr mode to true");
6690 } else if (!strncmp(value, "false", 5)) {
6691 adev->vr_audio_mode_enabled = false;
6692 ALOGI("Setting vr mode to false");
6693 } else {
6694 ALOGI("wrong vr mode set");
6695 }
6696 }
6697
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306698 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006699done:
6700 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006701 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306702error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006703 ALOGV("%s: exit with code(%d)", __func__, status);
6704 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006705}
6706
6707static char* adev_get_parameters(const struct audio_hw_device *dev,
6708 const char *keys)
6709{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006710 struct audio_device *adev = (struct audio_device *)dev;
6711 struct str_parms *reply = str_parms_create();
6712 struct str_parms *query = str_parms_create_str(keys);
6713 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306714 char value[256] = {0};
6715 int ret = 0;
6716
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006717 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006718 if (reply) {
6719 str_parms_destroy(reply);
6720 }
6721 if (query) {
6722 str_parms_destroy(query);
6723 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006724 ALOGE("adev_get_parameters: failed to create query or reply");
6725 return NULL;
6726 }
6727
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006728 //handle vr audio getparam
6729
6730 ret = str_parms_get_str(query,
6731 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6732 value, sizeof(value));
6733
6734 if (ret >= 0) {
6735 bool vr_audio_enabled = false;
6736 pthread_mutex_lock(&adev->lock);
6737 vr_audio_enabled = adev->vr_audio_mode_enabled;
6738 pthread_mutex_unlock(&adev->lock);
6739
6740 ALOGI("getting vr mode to %d", vr_audio_enabled);
6741
6742 if (vr_audio_enabled) {
6743 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6744 "true");
6745 goto exit;
6746 } else {
6747 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6748 "false");
6749 goto exit;
6750 }
6751 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006752
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006753 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006754 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006755 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006756 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306757 pthread_mutex_unlock(&adev->lock);
6758
Naresh Tannirud7205b62014-06-20 02:54:48 +05306759exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006760 str = str_parms_to_str(reply);
6761 str_parms_destroy(query);
6762 str_parms_destroy(reply);
6763
6764 ALOGV("%s: exit: returns - %s", __func__, str);
6765 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006766}
6767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006768static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006769{
6770 return 0;
6771}
6772
6773static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6774{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006775 int ret;
6776 struct audio_device *adev = (struct audio_device *)dev;
6777 pthread_mutex_lock(&adev->lock);
6778 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006779 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006780 pthread_mutex_unlock(&adev->lock);
6781 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006782}
6783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006784static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6785 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006786{
6787 return -ENOSYS;
6788}
6789
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006790static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6791 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006792{
6793 return -ENOSYS;
6794}
6795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006796static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6797 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798{
6799 return -ENOSYS;
6800}
6801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006802static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6803 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006804{
6805 return -ENOSYS;
6806}
6807
6808static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6809{
6810 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07006811 struct listnode *node;
6812 struct audio_usecase *usecase = NULL;
6813 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006814 pthread_mutex_lock(&adev->lock);
6815 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006816 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006817 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006818 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07006819 list_for_each(node, &adev->usecase_list) {
6820 usecase = node_to_item(node, struct audio_usecase, list);
6821 if (usecase->type == VOICE_CALL)
6822 break;
6823 }
6824 if (usecase &&
6825 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
6826 ret = audio_extn_usb_check_and_set_svc_int(usecase,
6827 true);
6828 if (ret != 0) {
6829 /* default service interval was successfully updated,
6830 reopen USB backend with new service interval */
6831 check_usecases_codec_backend(adev,
6832 usecase,
6833 usecase->out_snd_device);
6834 }
6835 }
6836
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006837 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006838 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006839 adev->current_call_output = NULL;
6840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006841 }
6842 pthread_mutex_unlock(&adev->lock);
6843 return 0;
6844}
6845
6846static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6847{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006848 int ret;
6849
6850 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006851 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006852 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6853 pthread_mutex_unlock(&adev->lock);
6854
6855 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006856}
6857
6858static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6859{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006860 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861 return 0;
6862}
6863
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006864static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006865 const struct audio_config *config)
6866{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006867 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006869 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6870 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006871}
6872
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006873static bool adev_input_allow_hifi_record(struct audio_device *adev,
6874 audio_devices_t devices,
6875 audio_input_flags_t flags,
6876 audio_source_t source) {
6877 const bool allowed = true;
6878
6879 if (!audio_is_usb_in_device(devices))
6880 return !allowed;
6881
6882 switch (flags) {
6883 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006884 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006885 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6886 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006887 default:
6888 return !allowed;
6889 }
6890
6891 switch (source) {
6892 case AUDIO_SOURCE_DEFAULT:
6893 case AUDIO_SOURCE_MIC:
6894 case AUDIO_SOURCE_UNPROCESSED:
6895 break;
6896 default:
6897 return !allowed;
6898 }
6899
6900 switch (adev->mode) {
6901 case 0:
6902 break;
6903 default:
6904 return !allowed;
6905 }
6906
6907 return allowed;
6908}
6909
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006910static int adev_update_voice_comm_input_stream(struct stream_in *in,
6911 struct audio_config *config)
6912{
6913 bool valid_rate = (config->sample_rate == 8000 ||
6914 config->sample_rate == 16000 ||
6915 config->sample_rate == 32000 ||
6916 config->sample_rate == 48000);
6917 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
6918
6919#ifndef COMPRESS_VOIP_ENABLED
kunleizd96526c2018-04-09 11:12:32 +08006920 if (valid_rate && valid_ch &&
6921 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006922 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6923 in->config = default_pcm_config_voip_copp;
6924 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
6925 DEFAULT_VOIP_BUF_DURATION_MS,
6926 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6927 } else {
kunleizbdd9ad02018-04-24 10:53:17 +08006928 ALOGW("%s No valid input in voip, use defaults"
6929 "sample rate %u, channel mask 0x%X",
6930 __func__, config->sample_rate, in->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006931 }
6932 in->config.rate = config->sample_rate;
6933 in->sample_rate = config->sample_rate;
6934#else
6935 //XXX needed for voice_extn_compress_voip_open_input_stream
6936 in->config.rate = config->sample_rate;
6937 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6938 voice_extn_compress_voip_is_active(in->dev)) &&
6939 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6940 valid_rate && valid_ch) {
6941 voice_extn_compress_voip_open_input_stream(in);
6942 // update rate entries to match config from AF
6943 in->config.rate = config->sample_rate;
6944 in->sample_rate = config->sample_rate;
6945 } else {
6946 ALOGW("%s compress voip not active, use defaults", __func__);
6947 }
6948#endif
6949 return 0;
6950}
6951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006952static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006953 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006954 audio_devices_t devices,
6955 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006956 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306957 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006958 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006959 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006960{
6961 struct audio_device *adev = (struct audio_device *)dev;
6962 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006963 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006964 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006965 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306966 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006967 bool is_usb_dev = audio_is_usb_in_device(devices);
6968 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6969 devices,
6970 flags,
6971 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306972
kunleizdff872d2018-08-20 14:40:33 +08006973 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006974 is_usb_dev = false;
6975 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
6976 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
6977 __func__, devices);
6978 }
6979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006981
6982 if (!(is_usb_dev && may_use_hifi_record)) {
6983 if (config->sample_rate == 0)
6984 config->sample_rate = 48000;
6985 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6986 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6987 if (config->format == AUDIO_FORMAT_DEFAULT)
6988 config->format = AUDIO_FORMAT_PCM_16_BIT;
6989
6990 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6991
6992 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6993 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006995
6996 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006997
6998 if (!in) {
6999 ALOGE("failed to allocate input stream");
7000 return -ENOMEM;
7001 }
7002
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307003 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307004 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
7005 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007006 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007007 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009 in->stream.common.get_sample_rate = in_get_sample_rate;
7010 in->stream.common.set_sample_rate = in_set_sample_rate;
7011 in->stream.common.get_buffer_size = in_get_buffer_size;
7012 in->stream.common.get_channels = in_get_channels;
7013 in->stream.common.get_format = in_get_format;
7014 in->stream.common.set_format = in_set_format;
7015 in->stream.common.standby = in_standby;
7016 in->stream.common.dump = in_dump;
7017 in->stream.common.set_parameters = in_set_parameters;
7018 in->stream.common.get_parameters = in_get_parameters;
7019 in->stream.common.add_audio_effect = in_add_audio_effect;
7020 in->stream.common.remove_audio_effect = in_remove_audio_effect;
7021 in->stream.set_gain = in_set_gain;
7022 in->stream.read = in_read;
7023 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307024 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025
7026 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07007027 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007028 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007029 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007030 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007031 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07007032 in->bit_width = 16;
7033 in->af_period_multiplier = 1;
7034
7035 /* Update config params with the requested sample rate and channels */
7036 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
7037 (adev->mode != AUDIO_MODE_IN_CALL)) {
7038 ret = -EINVAL;
7039 goto err_open;
7040 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007041
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007042 if (is_usb_dev && may_use_hifi_record) {
7043 /* HiFi record selects an appropriate format, channel, rate combo
7044 depending on sink capabilities*/
7045 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
7046 &config->format,
7047 &in->supported_formats[0],
7048 MAX_SUPPORTED_FORMATS,
7049 &config->channel_mask,
7050 &in->supported_channel_masks[0],
7051 MAX_SUPPORTED_CHANNEL_MASKS,
7052 &config->sample_rate,
7053 &in->supported_sample_rates[0],
7054 MAX_SUPPORTED_SAMPLE_RATES);
7055 if (ret != 0) {
7056 ret = -EINVAL;
7057 goto err_open;
7058 }
7059 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007060 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307061 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05307062 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
7063 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
7064 in->config.format = PCM_FORMAT_S32_LE;
7065 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307066 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
7067 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
7068 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
7069 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7070 bool ret_error = false;
7071 in->bit_width = 24;
7072 /* 24 bit is restricted to UNPROCESSED source only,also format supported
7073 from HAL is 24_packed and 8_24
7074 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
7075 24_packed return error indicating supported format is 24_packed
7076 *> In case of any other source requesting 24 bit or float return error
7077 indicating format supported is 16 bit only.
7078
7079 on error flinger will retry with supported format passed
7080 */
7081 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
7082 (source != AUDIO_SOURCE_CAMCORDER)) {
7083 config->format = AUDIO_FORMAT_PCM_16_BIT;
7084 if (config->sample_rate > 48000)
7085 config->sample_rate = 48000;
7086 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07007087 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
7088 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307089 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
7090 ret_error = true;
7091 }
7092
7093 if (ret_error) {
7094 ret = -EINVAL;
7095 goto err_open;
7096 }
7097 }
7098
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007099 in->channel_mask = config->channel_mask;
7100 in->format = config->format;
7101
7102 in->usecase = USECASE_AUDIO_RECORD;
7103 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
7104 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
7105 is_low_latency = true;
7106#if LOW_LATENCY_CAPTURE_USE_CASE
7107 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
7108#endif
7109 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
7110 }
7111
7112 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
7113 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
7114 in->realtime = 0;
7115 in->usecase = USECASE_AUDIO_RECORD_MMAP;
7116 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07007117 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007118 in->stream.start = in_start;
7119 in->stream.stop = in_stop;
7120 in->stream.create_mmap_buffer = in_create_mmap_buffer;
7121 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007122 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007123 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
7124 } else if (in->realtime) {
7125 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07007126 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007127 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007128 in->sample_rate = in->config.rate;
7129 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07007130 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007131 in->usecase = USECASE_AUDIO_RECORD_HIFI;
7132 in->config = pcm_config_audio_capture;
7133 frame_size = audio_stream_in_frame_size(&in->stream);
7134 buffer_size = get_input_buffer_size(config->sample_rate,
7135 config->format,
7136 channel_count,
7137 false /*is_low_latency*/);
7138 in->config.period_size = buffer_size / frame_size;
7139 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007140 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07007141 switch (config->format) {
7142 case AUDIO_FORMAT_PCM_32_BIT:
7143 in->bit_width = 32;
7144 break;
7145 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
7146 case AUDIO_FORMAT_PCM_8_24_BIT:
7147 in->bit_width = 24;
7148 break;
7149 default:
7150 in->bit_width = 16;
7151 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007152 in->config.channels = channel_count;
Haynes Mathew Georgef29116e2018-01-31 12:48:20 -08007153 in->sample_rate = in->config.rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007154 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05307155 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007156 if (config->sample_rate == 0)
7157 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7158 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
7159 config->sample_rate != 8000) {
7160 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7161 ret = -EINVAL;
7162 goto err_open;
7163 }
7164 if (config->format == AUDIO_FORMAT_DEFAULT)
7165 config->format = AUDIO_FORMAT_PCM_16_BIT;
7166 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
7167 config->format = AUDIO_FORMAT_PCM_16_BIT;
7168 ret = -EINVAL;
7169 goto err_open;
7170 }
7171
7172 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
7173 in->config = pcm_config_afe_proxy_record;
7174 in->config.channels = channel_count;
7175 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307176 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07007177 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05307178 int ret_val;
7179 pthread_mutex_lock(&adev->lock);
7180 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
7181 in, config, &channel_mask_updated);
7182 pthread_mutex_unlock(&adev->lock);
7183
7184 if (!ret_val) {
7185 if (channel_mask_updated == true) {
7186 ALOGD("%s: return error to retry with updated channel mask (%#x)",
7187 __func__, config->channel_mask);
7188 ret = -EINVAL;
7189 goto err_open;
7190 }
7191 ALOGD("%s: created multi-channel session succesfully",__func__);
7192 } else if (audio_extn_compr_cap_enabled() &&
7193 audio_extn_compr_cap_format_supported(config->format) &&
7194 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
7195 audio_extn_compr_cap_init(in);
7196 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05307197 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05307198 ret = audio_extn_cin_configure_input_stream(in);
7199 if (ret)
7200 goto err_open;
7201 } else {
7202 in->config = pcm_config_audio_capture;
7203 in->config.rate = config->sample_rate;
7204 in->config.format = pcm_format_from_audio_format(config->format);
7205 in->config.channels = channel_count;
7206 in->sample_rate = config->sample_rate;
7207 in->format = config->format;
7208 frame_size = audio_stream_in_frame_size(&in->stream);
7209 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07007210 config->format,
7211 channel_count,
7212 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307213 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007214
Revathi Uddarajud2634032017-12-07 14:42:34 +05307215 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
7216 /* optionally use VOIP usecase depending on config(s) */
7217 ret = adev_update_voice_comm_input_stream(in, config);
7218 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007219
Revathi Uddarajud2634032017-12-07 14:42:34 +05307220 if (ret) {
7221 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
7222 goto err_open;
7223 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007224 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007225 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307226 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7227 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007228 devices, flags, in->format,
7229 in->sample_rate, in->bit_width,
7230 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307231 register_format(in->format, in->supported_formats);
7232 register_channel_mask(in->channel_mask, in->supported_channel_masks);
7233 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307234
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007235 /* This stream could be for sound trigger lab,
7236 get sound trigger pcm if present */
7237 audio_extn_sound_trigger_check_and_get_session(in);
7238
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307239 lock_input_stream(in);
7240 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
7241 pthread_mutex_lock(&adev->lock);
7242 in->card_status = adev->card_status;
7243 pthread_mutex_unlock(&adev->lock);
7244 pthread_mutex_unlock(&in->lock);
7245
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007246 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07007247 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08007248 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249
7250err_open:
7251 free(in);
7252 *stream_in = NULL;
7253 return ret;
7254}
7255
7256static void adev_close_input_stream(struct audio_hw_device *dev,
7257 struct audio_stream_in *stream)
7258{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007259 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007260 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007261 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307262
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307263 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007264
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307265 // must deregister from sndmonitor first to prevent races
7266 // between the callback and close_stream
7267 audio_extn_snd_mon_unregister_listener(stream);
7268
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307269 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07007270 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05307271
Pallavid7c7a272018-01-16 11:22:55 +05307272 if (in == NULL) {
7273 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
7274 return;
7275 }
7276
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007277 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307278 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007279 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307280 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007281 if (ret != 0)
7282 ALOGE("%s: Compress voip input cannot be closed, error:%d",
7283 __func__, ret);
7284 } else
7285 in_standby(&stream->common);
7286
Revathi Uddarajud2634032017-12-07 14:42:34 +05307287 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07007288 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007289 audio_extn_ssr_deinit();
7290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291
Garmond Leunge2433c32017-09-28 21:51:22 -07007292 if (audio_extn_ffv_get_stream() == in) {
7293 audio_extn_ffv_stream_deinit();
7294 }
7295
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307296 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07007297 audio_extn_compr_cap_format_supported(in->config.format))
7298 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307299
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307300 if (audio_extn_cin_attached_usecase(in->usecase))
7301 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007302
Mingming Yinfd7607b2016-01-22 12:48:44 -08007303 if (in->is_st_session) {
7304 ALOGV("%s: sound trigger pcm stop lab", __func__);
7305 audio_extn_sound_trigger_stop_lab(in);
7306 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007307 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307308 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007309 return;
7310}
7311
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307312int adev_create_audio_patch(struct audio_hw_device *dev,
7313 unsigned int num_sources,
7314 const struct audio_port_config *sources,
7315 unsigned int num_sinks,
7316 const struct audio_port_config *sinks,
7317 audio_patch_handle_t *handle)
7318{
7319
7320
7321 return audio_extn_hw_loopback_create_audio_patch(dev,
7322 num_sources,
7323 sources,
7324 num_sinks,
7325 sinks,
7326 handle);
7327
7328}
7329
7330int adev_release_audio_patch(struct audio_hw_device *dev,
7331 audio_patch_handle_t handle)
7332{
7333 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7334}
7335
7336int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7337{
7338 return audio_extn_hw_loopback_get_audio_port(dev, config);
7339}
7340
7341int adev_set_audio_port_config(struct audio_hw_device *dev,
7342 const struct audio_port_config *config)
7343{
7344 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7345}
7346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007347static int adev_dump(const audio_hw_device_t *device __unused,
7348 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007349{
7350 return 0;
7351}
7352
7353static int adev_close(hw_device_t *device)
7354{
7355 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007356
7357 if (!adev)
7358 return 0;
7359
7360 pthread_mutex_lock(&adev_init_lock);
7361
7362 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307363 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007364 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007365 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307366 audio_extn_utils_release_streams_cfg_lists(
7367 &adev->streams_output_cfg_list,
7368 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307369 if (audio_extn_qaf_is_enabled())
7370 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007371 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007372 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007373 free(adev->snd_dev_ref_cnt);
7374 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007375 if (adev->adm_deinit)
7376 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307377 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007378 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307379 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307380 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007381 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307382 if (adev->device_cfg_params) {
7383 free(adev->device_cfg_params);
7384 adev->device_cfg_params = NULL;
7385 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007386 free(device);
7387 adev = NULL;
7388 }
7389 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007391 return 0;
7392}
7393
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007394/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7395 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7396 * just that it _might_ work.
7397 */
7398static int period_size_is_plausible_for_low_latency(int period_size)
7399{
7400 switch (period_size) {
7401 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007402 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007403 case 240:
7404 case 320:
7405 case 480:
7406 return 1;
7407 default:
7408 return 0;
7409 }
7410}
7411
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307412static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7413{
7414 bool is_snd_card_status = false;
7415 bool is_ext_device_status = false;
7416 char value[32];
7417 int card = -1;
7418 card_status_t status;
7419
7420 if (cookie != adev || !parms)
7421 return;
7422
7423 if (!parse_snd_card_status(parms, &card, &status)) {
7424 is_snd_card_status = true;
7425 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7426 is_ext_device_status = true;
7427 } else {
7428 // not a valid event
7429 return;
7430 }
7431
7432 pthread_mutex_lock(&adev->lock);
7433 if (card == adev->snd_card || is_ext_device_status) {
7434 if (is_snd_card_status && adev->card_status != status) {
7435 adev->card_status = status;
7436 platform_snd_card_update(adev->platform, status);
7437 audio_extn_fm_set_parameters(adev, parms);
7438 } else if (is_ext_device_status) {
7439 platform_set_parameters(adev->platform, parms);
7440 }
7441 }
7442 pthread_mutex_unlock(&adev->lock);
7443 return;
7444}
7445
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307446/* out and adev lock held */
7447static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7448{
7449 struct audio_usecase *uc_info;
7450 float left_p;
7451 float right_p;
7452 audio_devices_t devices;
7453
7454 uc_info = get_usecase_from_list(adev, out->usecase);
7455 if (uc_info == NULL) {
7456 ALOGE("%s: Could not find the usecase (%d) in the list",
7457 __func__, out->usecase);
7458 return -EINVAL;
7459 }
7460
7461 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7462 out->usecase, use_case_table[out->usecase]);
7463
7464 if (restore) {
7465 // restore A2DP device for active usecases and unmute if required
7466 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7467 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7468 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7469 select_devices(adev, uc_info->id);
7470 pthread_mutex_lock(&out->compr_mute_lock);
7471 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7472 (out->a2dp_compress_mute)) {
7473 out->a2dp_compress_mute = false;
7474 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7475 }
7476 pthread_mutex_unlock(&out->compr_mute_lock);
7477 }
7478 } else {
7479 // mute compress stream if suspended
7480 pthread_mutex_lock(&out->compr_mute_lock);
7481 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7482 (!out->a2dp_compress_mute)) {
7483 if (!out->standby) {
7484 ALOGD("%s: selecting speaker and muting stream", __func__);
7485 devices = out->devices;
7486 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7487 left_p = out->volume_l;
7488 right_p = out->volume_r;
7489 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7490 compress_pause(out->compr);
7491 out_set_compr_volume(&out->stream, (float)0, (float)0);
7492 out->a2dp_compress_mute = true;
7493 select_devices(adev, out->usecase);
7494 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7495 compress_resume(out->compr);
7496 out->devices = devices;
7497 out->volume_l = left_p;
7498 out->volume_r = right_p;
7499 }
7500 }
7501 pthread_mutex_unlock(&out->compr_mute_lock);
7502 }
7503 ALOGV("%s: exit", __func__);
7504 return 0;
7505}
7506
7507int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7508{
7509 int ret = 0;
7510
7511 lock_output_stream(out);
7512 pthread_mutex_lock(&adev->lock);
7513
7514 ret = check_a2dp_restore_l(adev, out, restore);
7515
7516 pthread_mutex_unlock(&adev->lock);
7517 pthread_mutex_unlock(&out->lock);
7518 return ret;
7519}
7520
Haynes Mathew George01156f92018-04-13 15:29:54 -07007521void adev_on_battery_status_changed(bool charging)
7522{
7523 pthread_mutex_lock(&adev->lock);
7524 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
7525 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08007526 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07007527 pthread_mutex_unlock(&adev->lock);
7528}
7529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007530static int adev_open(const hw_module_t *module, const char *name,
7531 hw_device_t **device)
7532{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307533 int ret;
7534
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007535 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007536 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7537
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007538 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007539 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007540 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007541 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007542 ALOGD("%s: returning existing instance of adev", __func__);
7543 ALOGD("%s: exit", __func__);
7544 pthread_mutex_unlock(&adev_init_lock);
7545 return 0;
7546 }
7547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007548 adev = calloc(1, sizeof(struct audio_device));
7549
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007550 if (!adev) {
7551 pthread_mutex_unlock(&adev_init_lock);
7552 return -ENOMEM;
7553 }
7554
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007555 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7556
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307557#ifdef DYNAMIC_LOG_ENABLED
7558 register_for_dynamic_logging("hal");
7559#endif
7560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007561 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7562 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7563 adev->device.common.module = (struct hw_module_t *)module;
7564 adev->device.common.close = adev_close;
7565
7566 adev->device.init_check = adev_init_check;
7567 adev->device.set_voice_volume = adev_set_voice_volume;
7568 adev->device.set_master_volume = adev_set_master_volume;
7569 adev->device.get_master_volume = adev_get_master_volume;
7570 adev->device.set_master_mute = adev_set_master_mute;
7571 adev->device.get_master_mute = adev_get_master_mute;
7572 adev->device.set_mode = adev_set_mode;
7573 adev->device.set_mic_mute = adev_set_mic_mute;
7574 adev->device.get_mic_mute = adev_get_mic_mute;
7575 adev->device.set_parameters = adev_set_parameters;
7576 adev->device.get_parameters = adev_get_parameters;
7577 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7578 adev->device.open_output_stream = adev_open_output_stream;
7579 adev->device.close_output_stream = adev_close_output_stream;
7580 adev->device.open_input_stream = adev_open_input_stream;
7581 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307582 adev->device.create_audio_patch = adev_create_audio_patch;
7583 adev->device.release_audio_patch = adev_release_audio_patch;
7584 adev->device.get_audio_port = adev_get_audio_port;
7585 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007586 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307587 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007588
7589 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007590 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007591 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007592 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007593 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007594 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007595 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007596 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307597 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007598 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007599 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007600 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007601 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007602 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007603 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307604 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307605 adev->perf_lock_opts[0] = 0x101;
7606 adev->perf_lock_opts[1] = 0x20E;
7607 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007608 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007610 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007611 adev->platform = platform_init(adev);
7612 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007613 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007614 free(adev->snd_dev_ref_cnt);
7615 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007616 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07007617 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7618 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007619 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007620 return -EINVAL;
7621 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007622
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307623 if (audio_extn_qaf_is_enabled()) {
7624 ret = audio_extn_qaf_init(adev);
7625 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07007626 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307627 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07007628 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307629 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7630 *device = NULL;
7631 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307632 return ret;
7633 }
7634
7635 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7636 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7637 }
7638
Eric Laurentc4aef752013-09-12 17:45:53 -07007639 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7640 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7641 if (adev->visualizer_lib == NULL) {
7642 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7643 } else {
7644 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7645 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007646 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007647 "visualizer_hal_start_output");
7648 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007649 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007650 "visualizer_hal_stop_output");
7651 }
7652 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307653 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007654 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007655 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307656 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007657 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007658
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007659 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7660 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7661 if (adev->offload_effects_lib == NULL) {
7662 ALOGE("%s: DLOPEN failed for %s", __func__,
7663 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7664 } else {
7665 ALOGV("%s: DLOPEN successful for %s", __func__,
7666 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7667 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307668 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007669 "offload_effects_bundle_hal_start_output");
7670 adev->offload_effects_stop_output =
7671 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7672 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007673 adev->offload_effects_set_hpx_state =
7674 (int (*)(bool))dlsym(adev->offload_effects_lib,
7675 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307676 adev->offload_effects_get_parameters =
7677 (void (*)(struct str_parms *, struct str_parms *))
7678 dlsym(adev->offload_effects_lib,
7679 "offload_effects_bundle_get_parameters");
7680 adev->offload_effects_set_parameters =
7681 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7682 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007683 }
7684 }
7685
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007686 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7687 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7688 if (adev->adm_lib == NULL) {
7689 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7690 } else {
7691 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7692 adev->adm_init = (adm_init_t)
7693 dlsym(adev->adm_lib, "adm_init");
7694 adev->adm_deinit = (adm_deinit_t)
7695 dlsym(adev->adm_lib, "adm_deinit");
7696 adev->adm_register_input_stream = (adm_register_input_stream_t)
7697 dlsym(adev->adm_lib, "adm_register_input_stream");
7698 adev->adm_register_output_stream = (adm_register_output_stream_t)
7699 dlsym(adev->adm_lib, "adm_register_output_stream");
7700 adev->adm_deregister_stream = (adm_deregister_stream_t)
7701 dlsym(adev->adm_lib, "adm_deregister_stream");
7702 adev->adm_request_focus = (adm_request_focus_t)
7703 dlsym(adev->adm_lib, "adm_request_focus");
7704 adev->adm_abandon_focus = (adm_abandon_focus_t)
7705 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007706 adev->adm_set_config = (adm_set_config_t)
7707 dlsym(adev->adm_lib, "adm_set_config");
7708 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7709 dlsym(adev->adm_lib, "adm_request_focus_v2");
7710 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7711 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7712 adev->adm_on_routing_change = (adm_on_routing_change_t)
7713 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007714 }
7715 }
7716
Mingming Yin514a8bc2014-07-29 15:22:21 -07007717 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007718 //initialize this to false for now,
7719 //this will be set to true through set param
7720 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007721
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007722 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007723 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007724 adev->dsp_bit_width_enforce_mode =
7725 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007726
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307727 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7728 &adev->streams_output_cfg_list,
7729 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007730
Kiran Kandi910e1862013-10-29 13:29:42 -07007731 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007732
7733 char value[PROPERTY_VALUE_MAX];
7734 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007735 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007736 trial = atoi(value);
7737 if (period_size_is_plausible_for_low_latency(trial)) {
7738 pcm_config_low_latency.period_size = trial;
7739 pcm_config_low_latency.start_threshold = trial / 4;
7740 pcm_config_low_latency.avail_min = trial / 4;
7741 configured_low_latency_capture_period_size = trial;
7742 }
7743 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007744 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007745 trial = atoi(value);
7746 if (period_size_is_plausible_for_low_latency(trial)) {
7747 configured_low_latency_capture_period_size = trial;
7748 }
7749 }
7750
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08007751 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
7752
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007753 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007754 af_period_multiplier = atoi(value);
7755 if (af_period_multiplier < 0)
7756 af_period_multiplier = 2;
7757 else if (af_period_multiplier > 4)
7758 af_period_multiplier = 4;
7759
7760 ALOGV("new period_multiplier = %d", af_period_multiplier);
7761 }
7762
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007763 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007764 pthread_mutex_unlock(&adev_init_lock);
7765
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007766 if (adev->adm_init)
7767 adev->adm_data = adev->adm_init();
7768
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307769 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307770 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007771 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307772
7773 audio_extn_snd_mon_init();
7774 pthread_mutex_lock(&adev->lock);
7775 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7776 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07007777 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
7778 /*
7779 * if the battery state callback happens before charging can be queried,
7780 * it will be guarded with the adev->lock held in the cb function and so
7781 * the callback value will reflect the latest state
7782 */
7783 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307784 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08007785 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
7786 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307787 /* Allocate memory for Device config params */
7788 adev->device_cfg_params = (struct audio_device_config_param*)
7789 calloc(platform_get_max_codec_backend(),
7790 sizeof(struct audio_device_config_param));
7791 if (adev->device_cfg_params == NULL)
7792 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307793
Eric Laurent994a6932013-07-17 11:51:42 -07007794 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007795 return 0;
7796}
7797
7798static struct hw_module_methods_t hal_module_methods = {
7799 .open = adev_open,
7800};
7801
7802struct audio_module HAL_MODULE_INFO_SYM = {
7803 .common = {
7804 .tag = HARDWARE_MODULE_TAG,
7805 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7806 .hal_api_version = HARDWARE_HAL_API_VERSION,
7807 .id = AUDIO_HARDWARE_MODULE_ID,
7808 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007809 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007810 .methods = &hal_module_methods,
7811 },
7812};