blob: ef74440d17372ce334d7df91da309ed4bc9a4af3 [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;
440static pthread_mutex_t adev_init_lock;
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);
900
901 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
902 if (ret < 0) {
903 ALOGE("%s Failed to get module id %d", __func__, ret);
904 return ret;
905 }
906 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
907 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
908
909 if(enable)
910 param_value = effect_config.param_value;
911
912 /*Special handling for AEC & NS effects Param values need to be
913 updated if module ids are same*/
914
915 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
916 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
917 if (ret < 0)
918 return ret;
919 }
920
921 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
922
923 return ret;
924}
925
926static void check_and_enable_effect(struct audio_device *adev)
927{
928
929 if (adev->active_input->enable_aec) {
930 enable_disable_effect(adev, EFFECT_AEC, true);
931 }
932
933 if (adev->active_input->enable_ns &&
934 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
935 enable_disable_effect(adev, EFFECT_NS, true);
936 }
937}
938#else
939#define enable_disable_effect(x, y, z) ENOSYS
940#define check_and_enable_effect(x) ENOSYS
941#endif
942
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700943int pcm_ioctl(struct pcm *pcm, int request, ...)
944{
945 va_list ap;
946 void * arg;
947 int pcm_fd = *(int*)pcm;
948
949 va_start(ap, request);
950 arg = va_arg(ap, void *);
951 va_end(ap);
952
953 return ioctl(pcm_fd, request, arg);
954}
955
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700956int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700957 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700960 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530961 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800962
963 if (usecase == NULL)
964 return -EINVAL;
965
966 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
967
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800968 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800970 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800972
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800973#ifdef DS1_DOLBY_DAP_ENABLED
974 audio_extn_dolby_set_dmid(adev);
975 audio_extn_dolby_set_endpoint(adev);
976#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700977 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700978 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530979 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700980 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530981 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530982 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
983 out = usecase->stream.out;
984 if (out && out->compr)
985 audio_extn_utils_compress_set_clk_rec_mode(usecase);
986 }
987
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800988 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700989 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700990 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700991 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 ALOGV("%s: exit", __func__);
993 return 0;
994}
995
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700996int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700997 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001000 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001001
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301002 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001003 return -EINVAL;
1004
1005 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 if (usecase->type == PCM_CAPTURE)
1007 snd_device = usecase->in_snd_device;
1008 else
1009 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001010 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001011 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001012 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001013 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001014 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301015 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016 ALOGV("%s: exit", __func__);
1017 return 0;
1018}
1019
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001020int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001021 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301023 int i, num_devices = 0;
1024 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001025 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1026
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001027 if (snd_device < SND_DEVICE_MIN ||
1028 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001029 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001030 return -EINVAL;
1031 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032
1033 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001034
1035 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1036 ALOGE("%s: Invalid sound device returned", __func__);
1037 return -EINVAL;
1038 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001040 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001041 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 return 0;
1043 }
1044
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301045
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001046 if (audio_extn_spkr_prot_is_enabled())
1047 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001048
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001049 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1050 audio_extn_spkr_prot_is_enabled()) {
1051 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001052 adev->snd_dev_ref_cnt[snd_device]--;
1053 return -EINVAL;
1054 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001055 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001056 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001057 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001058 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001059 return -EINVAL;
1060 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001061 } else if (platform_split_snd_device(adev->platform,
1062 snd_device,
1063 &num_devices,
1064 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301065 for (i = 0; i < num_devices; i++) {
1066 enable_snd_device(adev, new_snd_devices[i]);
1067 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001068 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001069 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301070
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301071
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301072 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1073 (audio_extn_a2dp_start_playback() < 0)) {
1074 ALOGE(" fail to configure A2dp control path ");
1075 return -EINVAL;
1076 }
1077
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001078 /* due to the possibility of calibration overwrite between listen
1079 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001080 audio_extn_sound_trigger_update_device_status(snd_device,
1081 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301082 audio_extn_listen_update_device_status(snd_device,
1083 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001084 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001085 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001086 audio_extn_sound_trigger_update_device_status(snd_device,
1087 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301088 audio_extn_listen_update_device_status(snd_device,
1089 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001090 return -EINVAL;
1091 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001092 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001093 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301094
1095 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1096 !adev->native_playback_enabled &&
1097 audio_is_true_native_stream_active(adev)) {
1098 ALOGD("%s: %d: napb: enabling native mode in hardware",
1099 __func__, __LINE__);
1100 audio_route_apply_and_update_path(adev->audio_route,
1101 "true-native-mode");
1102 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301103 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001104 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1105 (audio_extn_ffv_get_stream() == adev->active_input)) {
1106 ALOGD("%s: init ec ref loopback", __func__);
1107 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 return 0;
1111}
1112
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001113int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001114 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301116 int i, num_devices = 0;
1117 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001118 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1119
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001120 if (snd_device < SND_DEVICE_MIN ||
1121 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001122 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001123 return -EINVAL;
1124 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1126 ALOGE("%s: device ref cnt is already 0", __func__);
1127 return -EINVAL;
1128 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001129
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001131
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001132 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1133 ALOGE("%s: Invalid sound device returned", __func__);
1134 return -EINVAL;
1135 }
1136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001138 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301139
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001140 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1141 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001142 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001143
1144 // when speaker device is disabled, reset swap.
1145 // will be renabled on usecase start
1146 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001147 } else if (platform_split_snd_device(adev->platform,
1148 snd_device,
1149 &num_devices,
1150 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301151 for (i = 0; i < num_devices; i++) {
1152 disable_snd_device(adev, new_snd_devices[i]);
1153 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001154 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001155 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001156 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001157
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301158 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1159 audio_extn_a2dp_stop_playback();
1160
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001161 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301162 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301163 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1164 adev->native_playback_enabled) {
1165 ALOGD("%s: %d: napb: disabling native mode in hardware",
1166 __func__, __LINE__);
1167 audio_route_reset_and_update_path(adev->audio_route,
1168 "true-native-mode");
1169 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301170 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1171 adev->asrc_mode_enabled) {
1172 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301173 disable_asrc_mode(adev);
1174 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301175 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001176 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1177 (audio_extn_ffv_get_stream() == adev->active_input)) {
1178 ALOGD("%s: deinit ec ref loopback", __func__);
1179 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1180 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001181 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001182 audio_extn_sound_trigger_update_device_status(snd_device,
1183 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301184 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001185 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188 return 0;
1189}
1190
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001191/*
1192 legend:
1193 uc - existing usecase
1194 new_uc - new usecase
1195 d1, d11, d2 - SND_DEVICE enums
1196 a1, a2 - corresponding ANDROID device enums
1197 B1, B2 - backend strings
1198
1199case 1
1200 uc->dev d1 (a1) B1
1201 new_uc->dev d1 (a1), d2 (a2) B1, B2
1202
1203 resolution: disable and enable uc->dev on d1
1204
1205case 2
1206 uc->dev d1 (a1) B1
1207 new_uc->dev d11 (a1) B1
1208
1209 resolution: need to switch uc since d1 and d11 are related
1210 (e.g. speaker and voice-speaker)
1211 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1212
1213case 3
1214 uc->dev d1 (a1) B1
1215 new_uc->dev d2 (a2) B2
1216
1217 resolution: no need to switch uc
1218
1219case 4
1220 uc->dev d1 (a1) B1
1221 new_uc->dev d2 (a2) B1
1222
1223 resolution: disable enable uc-dev on d2 since backends match
1224 we cannot enable two streams on two different devices if they
1225 share the same backend. e.g. if offload is on speaker device using
1226 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1227 using the same backend, offload must also be switched to voice-handset.
1228
1229case 5
1230 uc->dev d1 (a1) B1
1231 new_uc->dev d1 (a1), d2 (a2) B1
1232
1233 resolution: disable enable uc-dev on d2 since backends match
1234 we cannot enable two streams on two different devices if they
1235 share the same backend.
1236
1237case 6
1238 uc->dev d1 (a1) B1
1239 new_uc->dev d2 (a1) B2
1240
1241 resolution: no need to switch
1242
1243case 7
1244 uc->dev d1 (a1), d2 (a2) B1, B2
1245 new_uc->dev d1 (a1) B1
1246
1247 resolution: no need to switch
1248
1249*/
1250static snd_device_t derive_playback_snd_device(void * platform,
1251 struct audio_usecase *uc,
1252 struct audio_usecase *new_uc,
1253 snd_device_t new_snd_device)
1254{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301255 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001256
1257 snd_device_t d1 = uc->out_snd_device;
1258 snd_device_t d2 = new_snd_device;
1259
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301260 switch (uc->type) {
1261 case TRANSCODE_LOOPBACK :
1262 a1 = uc->stream.inout->out_config.devices;
1263 a2 = new_uc->stream.inout->out_config.devices;
1264 break;
1265 default :
1266 a1 = uc->stream.out->devices;
1267 a2 = new_uc->stream.out->devices;
1268 break;
1269 }
1270
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001271 // Treat as a special case when a1 and a2 are not disjoint
1272 if ((a1 != a2) && (a1 & a2)) {
1273 snd_device_t d3[2];
1274 int num_devices = 0;
1275 int ret = platform_split_snd_device(platform,
1276 popcount(a1) > 1 ? d1 : d2,
1277 &num_devices,
1278 d3);
1279 if (ret < 0) {
1280 if (ret != -ENOSYS) {
1281 ALOGW("%s failed to split snd_device %d",
1282 __func__,
1283 popcount(a1) > 1 ? d1 : d2);
1284 }
1285 goto end;
1286 }
1287
1288 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1289 // But if it does happen, we need to give priority to d2 if
1290 // the combo devices active on the existing usecase share a backend.
1291 // This is because we cannot have a usecase active on a combo device
1292 // and a new usecase requests one device in this combo pair.
1293 if (platform_check_backends_match(d3[0], d3[1])) {
1294 return d2; // case 5
1295 } else {
1296 return d1; // case 1
1297 }
1298 } else {
1299 if (platform_check_backends_match(d1, d2)) {
1300 return d2; // case 2, 4
1301 } else {
1302 return d1; // case 6, 3
1303 }
1304 }
1305
1306end:
1307 return d2; // return whatever was calculated before.
1308}
1309
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001310static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301311 struct audio_usecase *uc_info,
1312 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313{
1314 struct listnode *node;
1315 struct audio_usecase *usecase;
1316 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301317 snd_device_t uc_derive_snd_device;
1318 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001320 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301321 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001322 /*
1323 * This function is to make sure that all the usecases that are active on
1324 * the hardware codec backend are always routed to any one device that is
1325 * handled by the hardware codec.
1326 * For example, if low-latency and deep-buffer usecases are currently active
1327 * on speaker and out_set_parameters(headset) is received on low-latency
1328 * output, then we have to make sure deep-buffer is also switched to headset,
1329 * because of the limitation that both the devices cannot be enabled
1330 * at the same time as they share the same backend.
1331 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001332 /*
1333 * This call is to check if we need to force routing for a particular stream
1334 * If there is a backend configuration change for the device when a
1335 * new stream starts, then ADM needs to be closed and re-opened with the new
1336 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001337 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001338 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001339 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1340 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301341 /* For a2dp device reconfigure all active sessions
1342 * with new AFE encoder format based on a2dp state
1343 */
1344 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1345 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1346 audio_extn_a2dp_is_force_device_switch()) {
1347 force_routing = true;
1348 force_restart_session = true;
1349 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301350 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1351
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001353 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001354 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001355 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1356 switch_device[i] = false;
1357
1358 list_for_each(node, &adev->usecase_list) {
1359 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001360
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301361 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1362 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301363 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301364 platform_get_snd_device_name(usecase->out_snd_device),
1365 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301366 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1367 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1368 usecase, uc_info, snd_device);
1369 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1370 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1371 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1372 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1373 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1374 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1375 ((force_restart_session) ||
1376 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301377 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1378 __func__, use_case_table[usecase->id],
1379 platform_get_snd_device_name(usecase->out_snd_device));
1380 disable_audio_route(adev, usecase);
1381 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301382 /* Enable existing usecase on derived playback device */
1383 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301384 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301385 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001386 }
1387 }
1388
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301389 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1390 num_uc_to_switch);
1391
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001393 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301395 /* Make sure the previous devices to be disabled first and then enable the
1396 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 list_for_each(node, &adev->usecase_list) {
1398 usecase = node_to_item(node, struct audio_usecase, list);
1399 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001401 }
1402 }
1403
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001404 list_for_each(node, &adev->usecase_list) {
1405 usecase = node_to_item(node, struct audio_usecase, list);
1406 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301407 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001408 }
1409 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 /* Re-route all the usecases on the shared backend other than the
1412 specified usecase to new snd devices */
1413 list_for_each(node, &adev->usecase_list) {
1414 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301415 /* Update the out_snd_device only before enabling the audio route */
1416 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301417 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301418 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301419 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301420 use_case_table[usecase->id],
1421 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001422 /* Update voc calibration before enabling VoIP route */
1423 if (usecase->type == VOIP_CALL)
1424 status = platform_switch_voice_call_device_post(adev->platform,
1425 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001426 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301427 enable_audio_route(adev, usecase);
Yidong Huang7939a3b2018-01-23 17:32:30 +08001428 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1429 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1430 if (parms)
1431 audio_extn_fm_set_parameters(adev, parms);
1432 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301433 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 }
1435 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001436 }
1437}
1438
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301439static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001440 struct audio_usecase *uc_info,
1441 snd_device_t snd_device)
1442{
1443 struct listnode *node;
1444 struct audio_usecase *usecase;
1445 bool switch_device[AUDIO_USECASE_MAX];
1446 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301447 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001448 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001449
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301450 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1451 snd_device);
1452 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301453
1454 /*
1455 * Make sure out devices is checked against out codec backend device and
1456 * also in devices against in codec backend. Checking out device against in
1457 * codec backend or vice versa causes issues.
1458 */
1459 if (uc_info->type == PCM_CAPTURE)
1460 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001461 /*
1462 * This function is to make sure that all the active capture usecases
1463 * are always routed to the same input sound device.
1464 * For example, if audio-record and voice-call usecases are currently
1465 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1466 * is received for voice call then we have to make sure that audio-record
1467 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1468 * because of the limitation that two devices cannot be enabled
1469 * at the same time if they share the same backend.
1470 */
1471 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1472 switch_device[i] = false;
1473
1474 list_for_each(node, &adev->usecase_list) {
1475 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301476 /*
1477 * TODO: Enhance below condition to handle BT sco/USB multi recording
1478 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001479 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001480 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301481 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301482 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301483 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301484 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001485 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001486 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1487 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001488 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001489 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001490 switch_device[usecase->id] = true;
1491 num_uc_to_switch++;
1492 }
1493 }
1494
1495 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001496 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001497
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301498 /* Make sure the previous devices to be disabled first and then enable the
1499 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001500 list_for_each(node, &adev->usecase_list) {
1501 usecase = node_to_item(node, struct audio_usecase, list);
1502 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001503 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001504 }
1505 }
1506
1507 list_for_each(node, &adev->usecase_list) {
1508 usecase = node_to_item(node, struct audio_usecase, list);
1509 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001510 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001511 }
1512 }
1513
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001514 /* Re-route all the usecases on the shared backend other than the
1515 specified usecase to new snd devices */
1516 list_for_each(node, &adev->usecase_list) {
1517 usecase = node_to_item(node, struct audio_usecase, list);
1518 /* Update the in_snd_device only before enabling the audio route */
1519 if (switch_device[usecase->id] ) {
1520 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001521 if (usecase->type != VOICE_CALL) {
1522 /* Update voc calibration before enabling VoIP route */
1523 if (usecase->type == VOIP_CALL)
1524 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001525 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001526 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301527 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001528 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001529 }
1530 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001531 }
1532}
1533
Mingming Yin3a941d42016-02-17 18:08:05 -08001534static void reset_hdmi_sink_caps(struct stream_out *out) {
1535 int i = 0;
1536
1537 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1538 out->supported_channel_masks[i] = 0;
1539 }
1540 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1541 out->supported_formats[i] = 0;
1542 }
1543 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1544 out->supported_sample_rates[i] = 0;
1545 }
1546}
1547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001549static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550{
Mingming Yin3a941d42016-02-17 18:08:05 -08001551 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001552 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553
Mingming Yin3a941d42016-02-17 18:08:05 -08001554 reset_hdmi_sink_caps(out);
1555
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001556 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001557 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001558 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001559 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001560 }
1561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001564 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001565 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001566 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1567 case 6:
1568 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1569 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1570 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1571 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1572 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1573 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574 break;
1575 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001576 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001577 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 break;
1579 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001580
1581 // check channel format caps
1582 i = 0;
1583 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1584 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1585 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1586 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1587 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1588 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1589 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1590 }
1591
Ben Romberger1aaaf862017-04-06 17:49:46 -07001592 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1593 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1594 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1595 }
1596
Mingming Yin3a941d42016-02-17 18:08:05 -08001597 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1598 ALOGV(":%s HDMI supports DTS format", __func__);
1599 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1600 }
1601
1602 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1603 ALOGV(":%s HDMI supports DTS HD format", __func__);
1604 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1605 }
1606
Naresh Tanniru928f0862017-04-07 16:44:23 -07001607 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1608 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1609 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1610 }
1611
Mingming Yin3a941d42016-02-17 18:08:05 -08001612
1613 // check sample rate caps
1614 i = 0;
1615 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1616 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1617 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1618 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1619 }
1620 }
1621
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001622 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623}
1624
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001625static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1626 uint32_t *supported_sample_rates __unused,
1627 uint32_t max_rates __unused)
1628{
1629 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1630 supported_sample_rates,
1631 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301632 ssize_t i = 0;
1633
1634 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001635 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1636 supported_sample_rates[i]);
1637 }
1638 return count;
1639}
1640
1641static inline int read_usb_sup_channel_masks(bool is_playback,
1642 audio_channel_mask_t *supported_channel_masks,
1643 uint32_t max_masks)
1644{
1645 int channels = audio_extn_usb_get_max_channels(is_playback);
1646 int channel_count;
1647 uint32_t num_masks = 0;
1648 if (channels > MAX_HIFI_CHANNEL_COUNT)
1649 channels = MAX_HIFI_CHANNEL_COUNT;
1650
1651 if (is_playback) {
1652 // For playback we never report mono because the framework always outputs stereo
1653 channel_count = DEFAULT_CHANNEL_COUNT;
1654 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1655 // above 2 but we want indexed masks here. So we
1656 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1657 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1658 }
1659 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1660 supported_channel_masks[num_masks++] =
1661 audio_channel_mask_for_index_assignment_from_count(channel_count);
1662 }
1663 } else {
1664 // For capture we report all supported channel masks from 1 channel up.
1665 channel_count = MIN_CHANNEL_COUNT;
1666 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1667 // indexed mask
1668 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1669 supported_channel_masks[num_masks++] =
1670 audio_channel_in_mask_from_count(channel_count);
1671 }
1672 }
1673 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1674 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1675 return num_masks;
1676}
1677
1678static inline int read_usb_sup_formats(bool is_playback __unused,
1679 audio_format_t *supported_formats,
1680 uint32_t max_formats __unused)
1681{
1682 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1683 switch (bitwidth) {
1684 case 24:
1685 // XXX : usb.c returns 24 for s24 and s24_le?
1686 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1687 break;
1688 case 32:
1689 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1690 break;
1691 case 16:
1692 default :
1693 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1694 break;
1695 }
1696 ALOGV("%s: %s supported format %d", __func__,
1697 is_playback ? "P" : "C", bitwidth);
1698 return 1;
1699}
1700
1701static inline int read_usb_sup_params_and_compare(bool is_playback,
1702 audio_format_t *format,
1703 audio_format_t *supported_formats,
1704 uint32_t max_formats,
1705 audio_channel_mask_t *mask,
1706 audio_channel_mask_t *supported_channel_masks,
1707 uint32_t max_masks,
1708 uint32_t *rate,
1709 uint32_t *supported_sample_rates,
1710 uint32_t max_rates) {
1711 int ret = 0;
1712 int num_formats;
1713 int num_masks;
1714 int num_rates;
1715 int i;
1716
1717 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1718 max_formats);
1719 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1720 max_masks);
1721
1722 num_rates = read_usb_sup_sample_rates(is_playback,
1723 supported_sample_rates, max_rates);
1724
1725#define LUT(table, len, what, dflt) \
1726 for (i=0; i<len && (table[i] != what); i++); \
1727 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1728
1729 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1730 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1731 LUT(supported_sample_rates, num_rates, *rate, 0);
1732
1733#undef LUT
1734 return ret < 0 ? -EINVAL : 0; // HACK TBD
1735}
1736
Alexy Josephb1379942016-01-29 15:49:38 -08001737audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001738 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001739{
1740 struct audio_usecase *usecase;
1741 struct listnode *node;
1742
1743 list_for_each(node, &adev->usecase_list) {
1744 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001745 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001746 ALOGV("%s: usecase id %d", __func__, usecase->id);
1747 return usecase->id;
1748 }
1749 }
1750 return USECASE_INVALID;
1751}
1752
Alexy Josephb1379942016-01-29 15:49:38 -08001753struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001754 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755{
1756 struct audio_usecase *usecase;
1757 struct listnode *node;
1758
1759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
1761 if (usecase->id == uc_id)
1762 return usecase;
1763 }
1764 return NULL;
1765}
1766
Dhananjay Kumard4833242016-10-06 22:09:12 +05301767struct stream_in *get_next_active_input(const struct audio_device *adev)
1768{
1769 struct audio_usecase *usecase;
1770 struct listnode *node;
1771
1772 list_for_each_reverse(node, &adev->usecase_list) {
1773 usecase = node_to_item(node, struct audio_usecase, list);
1774 if (usecase->type == PCM_CAPTURE)
1775 return usecase->stream.in;
1776 }
1777 return NULL;
1778}
1779
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301780/*
1781 * is a true native playback active
1782 */
1783bool audio_is_true_native_stream_active(struct audio_device *adev)
1784{
1785 bool active = false;
1786 int i = 0;
1787 struct listnode *node;
1788
1789 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1790 ALOGV("%s:napb: not in true mode or non hdphones device",
1791 __func__);
1792 active = false;
1793 goto exit;
1794 }
1795
1796 list_for_each(node, &adev->usecase_list) {
1797 struct audio_usecase *uc;
1798 uc = node_to_item(node, struct audio_usecase, list);
1799 struct stream_out *curr_out =
1800 (struct stream_out*) uc->stream.out;
1801
1802 if (curr_out && PCM_PLAYBACK == uc->type) {
1803 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1804 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1805 uc->id, curr_out->sample_rate,
1806 curr_out->bit_width,
1807 platform_get_snd_device_name(uc->out_snd_device));
1808
1809 if (is_offload_usecase(uc->id) &&
1810 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1811 active = true;
1812 ALOGD("%s:napb:native stream detected", __func__);
1813 }
1814 }
1815 }
1816exit:
1817 return active;
1818}
1819
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001820uint32_t adev_get_dsp_bit_width_enforce_mode()
1821{
1822 if (adev == NULL) {
1823 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1824 return 0;
1825 }
1826 return adev->dsp_bit_width_enforce_mode;
1827}
1828
1829static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1830{
1831 char value[PROPERTY_VALUE_MAX];
1832 int trial;
1833 uint32_t dsp_bit_width_enforce_mode = 0;
1834
1835 if (!mixer) {
1836 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1837 __func__);
1838 return 0;
1839 }
1840
1841 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1842 value, NULL) > 0) {
1843 trial = atoi(value);
1844 switch (trial) {
1845 case 16:
1846 dsp_bit_width_enforce_mode = 16;
1847 break;
1848 case 24:
1849 dsp_bit_width_enforce_mode = 24;
1850 break;
1851 case 32:
1852 dsp_bit_width_enforce_mode = 32;
1853 break;
1854 default:
1855 dsp_bit_width_enforce_mode = 0;
1856 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1857 break;
1858 }
1859 }
1860
1861 return dsp_bit_width_enforce_mode;
1862}
1863
1864static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1865 uint32_t enforce_mode,
1866 bool enable)
1867{
1868 struct mixer_ctl *ctl = NULL;
1869 const char *mixer_ctl_name = "ASM Bit Width";
1870 uint32_t asm_bit_width_mode = 0;
1871
1872 if (enforce_mode == 0) {
1873 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1874 return;
1875 }
1876
1877 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1878 if (!ctl) {
1879 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1880 __func__, mixer_ctl_name);
1881 return;
1882 }
1883
1884 if (enable)
1885 asm_bit_width_mode = enforce_mode;
1886 else
1887 asm_bit_width_mode = 0;
1888
1889 ALOGV("%s DSP bit width feature status is %d width=%d",
1890 __func__, enable, asm_bit_width_mode);
1891 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1892 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1893 asm_bit_width_mode);
1894
1895 return;
1896}
1897
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301898/*
1899 * if native DSD playback active
1900 */
1901bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1902{
1903 bool active = false;
1904 struct listnode *node = NULL;
1905 struct audio_usecase *uc = NULL;
1906 struct stream_out *curr_out = NULL;
1907
1908 list_for_each(node, &adev->usecase_list) {
1909 uc = node_to_item(node, struct audio_usecase, list);
1910 curr_out = (struct stream_out*) uc->stream.out;
1911
1912 if (curr_out && PCM_PLAYBACK == uc->type &&
1913 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1914 active = true;
1915 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301916 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301917 }
1918 }
1919 return active;
1920}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301921
1922static bool force_device_switch(struct audio_usecase *usecase)
1923{
1924 bool ret = false;
1925 bool is_it_true_mode = false;
1926
Zhou Song30f2c3e2018-02-08 14:02:15 +08001927 if (usecase->type == PCM_CAPTURE ||
1928 usecase->type == TRANSCODE_LOOPBACK) {
1929 return false;
1930 }
1931
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001932 if(usecase->stream.out == NULL) {
1933 ALOGE("%s: stream.out is NULL", __func__);
1934 return false;
1935 }
1936
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301937 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001938 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1939 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1940 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301941 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1942 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1943 (!is_it_true_mode && adev->native_playback_enabled)){
1944 ret = true;
1945 ALOGD("napb: time to toggle native mode");
1946 }
1947 }
1948
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301949 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301950 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1951 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001952 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301953 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301954 ALOGD("Force a2dp device switch to update new encoder config");
1955 ret = true;
1956 }
1957
Manish Dewangan671a4202017-08-18 17:30:46 +05301958 if (usecase->stream.out->stream_config_changed) {
1959 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1960 return true;
1961 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301962 return ret;
1963}
1964
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301965bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1966{
1967 bool ret=false;
1968 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1969 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1970 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1971 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1972 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1973 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1974 ret = true;
1975
1976 return ret;
1977}
1978
1979bool is_a2dp_device(snd_device_t out_snd_device)
1980{
1981 bool ret=false;
1982 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1983 ret = true;
1984
1985 return ret;
1986}
1987
1988bool is_bt_soc_on(struct audio_device *adev)
1989{
1990 struct mixer_ctl *ctl;
1991 char *mixer_ctl_name = "BT SOC status";
1992 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1993 bool bt_soc_status = true;
1994 if (!ctl) {
1995 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1996 __func__, mixer_ctl_name);
1997 /*This is to ensure we dont break targets which dont have the kernel change*/
1998 return true;
1999 }
2000 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2001 ALOGD("BT SOC status: %d",bt_soc_status);
2002 return bt_soc_status;
2003}
2004
2005int out_standby_l(struct audio_stream *stream);
2006
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002007int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002009 snd_device_t out_snd_device = SND_DEVICE_NONE;
2010 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002011 struct audio_usecase *usecase = NULL;
2012 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002013 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002014 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302015 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002016 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002017 int status = 0;
Weiyin Jiang5d608082018-02-01 17:24:33 +08002018 audio_devices_t audio_device;
2019 audio_channel_mask_t channel_mask;
2020 int sample_rate;
2021 int acdb_id;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302023 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2024
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002025 usecase = get_usecase_from_list(adev, uc_id);
2026 if (usecase == NULL) {
2027 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2028 return -EINVAL;
2029 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002031 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002032 (usecase->type == VOIP_CALL) ||
2033 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302034 if(usecase->stream.out == NULL) {
2035 ALOGE("%s: stream.out is NULL", __func__);
2036 return -EINVAL;
2037 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002038 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002039 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002040 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002041 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302042 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2043 if (usecase->stream.inout == NULL) {
2044 ALOGE("%s: stream.inout is NULL", __func__);
2045 return -EINVAL;
2046 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302047 stream_out.devices = usecase->stream.inout->out_config.devices;
2048 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2049 stream_out.format = usecase->stream.inout->out_config.format;
2050 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2051 out_snd_device = platform_get_output_snd_device(adev->platform,
2052 &stream_out);
2053 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302054 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002055 } else {
2056 /*
2057 * If the voice call is active, use the sound devices of voice call usecase
2058 * so that it would not result any device switch. All the usecases will
2059 * be switched to new device when select_devices() is called for voice call
2060 * usecase. This is to avoid switching devices for voice call when
2061 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002062 * choose voice call device only if the use case device is
2063 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002064 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002065 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002066 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002067 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002068 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2069 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302070 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2071 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002072 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002073 in_snd_device = vc_usecase->in_snd_device;
2074 out_snd_device = vc_usecase->out_snd_device;
2075 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002076 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002077 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002078 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002079 if ((voip_usecase != NULL) &&
2080 (usecase->type == PCM_PLAYBACK) &&
2081 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002082 out_snd_device_backend_match = platform_check_backends_match(
2083 voip_usecase->out_snd_device,
2084 platform_get_output_snd_device(
2085 adev->platform,
2086 usecase->stream.out));
2087 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002088 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002089 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2090 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002091 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002092 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002093 in_snd_device = voip_usecase->in_snd_device;
2094 out_snd_device = voip_usecase->out_snd_device;
2095 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002096 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002097 hfp_ucid = audio_extn_hfp_get_usecase();
2098 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002099 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002100 in_snd_device = hfp_usecase->in_snd_device;
2101 out_snd_device = hfp_usecase->out_snd_device;
2102 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002103 }
2104 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302105 if (usecase->stream.out == NULL) {
2106 ALOGE("%s: stream.out is NULL", __func__);
2107 return -EINVAL;
2108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002109 usecase->devices = usecase->stream.out->devices;
2110 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002111 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002112 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002113 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002114 if (usecase->stream.out == adev->primary_output &&
2115 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08002116 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002117 select_devices(adev, adev->active_input->usecase);
2118 }
2119 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002120 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302121 if (usecase->stream.in == NULL) {
2122 ALOGE("%s: stream.in is NULL", __func__);
2123 return -EINVAL;
2124 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002125 usecase->devices = usecase->stream.in->device;
2126 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002127 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002128 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002129 if (adev->active_input &&
2130 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302131 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
2132 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
2133 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002134 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002135 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002136 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2137 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002138 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002139 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 }
2142 }
2143
2144 if (out_snd_device == usecase->out_snd_device &&
2145 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302146
2147 if (!force_device_switch(usecase))
2148 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 }
2150
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302151 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2152 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2153 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2154 return 0;
2155 }
2156
sangwoobc677242013-08-08 16:53:43 +09002157 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002158 out_snd_device, platform_get_snd_device_name(out_snd_device),
2159 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 /*
2162 * Limitation: While in call, to do a device switch we need to disable
2163 * and enable both RX and TX devices though one of them is same as current
2164 * device.
2165 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002166 if ((usecase->type == VOICE_CALL) &&
2167 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2168 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002169 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002170 }
2171
2172 if (((usecase->type == VOICE_CALL) ||
2173 (usecase->type == VOIP_CALL)) &&
2174 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2175 /* Disable sidetone only if voice/voip call already exists */
2176 if (voice_is_call_state_active(adev) ||
2177 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002178 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002179
2180 /* Disable aanc only if voice call exists */
2181 if (voice_is_call_state_active(adev))
2182 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002183 }
2184
Zhou Songc66eb7e2017-08-08 18:29:07 +08002185 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302186 (!audio_extn_a2dp_is_ready())) {
2187 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002188 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302189 }
2190
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002191 /* Disable current sound devices */
2192 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002193 disable_audio_route(adev, usecase);
2194 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 }
2196
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002198 disable_audio_route(adev, usecase);
2199 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 }
2201
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002202 /* Applicable only on the targets that has external modem.
2203 * New device information should be sent to modem before enabling
2204 * the devices to reduce in-call device switch time.
2205 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002206 if ((usecase->type == VOICE_CALL) &&
2207 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2208 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002209 status = platform_switch_voice_call_enable_device_config(adev->platform,
2210 out_snd_device,
2211 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002212 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002213
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002214 /* Enable new sound devices */
2215 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002216 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302217 if (platform_check_codec_asrc_support(adev->platform))
2218 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002219 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 }
2221
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002222 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302223 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002224 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002225 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226
Avinash Vaish71a8b972014-07-24 15:36:33 +05302227 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002228 status = platform_switch_voice_call_device_post(adev->platform,
2229 out_snd_device,
2230 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302231 enable_audio_route_for_voice_usecases(adev, usecase);
2232 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002233
sangwoo170731f2013-06-08 15:36:36 +09002234 usecase->in_snd_device = in_snd_device;
2235 usecase->out_snd_device = out_snd_device;
2236
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302237 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2238 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302239 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002240 if ((24 == usecase->stream.out->bit_width) &&
2241 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2242 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2243 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2244 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2245 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2246 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2247 /*
2248 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2249 * configured device sample rate, if not update the COPP rate to be equal to the
2250 * device sample rate, else open COPP at stream sample rate
2251 */
2252 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2253 usecase->stream.out->sample_rate,
2254 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302255 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2256 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002257 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2258 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2259 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2260 }
2261
Weiyin Jiang5d608082018-02-01 17:24:33 +08002262 /* Cache stream information to be notified to gef clients */
2263 audio_device = usecase->stream.out->devices;
2264 channel_mask = usecase->stream.out->channel_mask;
2265 sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
2266 acdb_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302267 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002268 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002269
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002270 /* If input stream is already running then effect needs to be
2271 applied on the new input device that's being enabled here. */
2272 if ((in_snd_device != SND_DEVICE_NONE) && (!adev->active_input->standby))
2273 check_and_enable_effect(adev);
2274
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002275 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002276 /* Enable aanc only if voice call exists */
2277 if (voice_is_call_state_active(adev))
2278 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2279
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002280 /* Enable sidetone only if other voice/voip call already exists */
2281 if (voice_is_call_state_active(adev) ||
2282 voice_extn_compress_voip_is_started(adev))
2283 voice_set_sidetone(adev, out_snd_device, true);
2284 }
2285
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002286 /* Applicable only on the targets that has external modem.
2287 * Enable device command should be sent to modem only after
2288 * enabling voice call mixer controls
2289 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002290 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002291 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2292 out_snd_device,
2293 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302294
2295 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2296
2297 if (usecase->type == VOIP_CALL) {
2298 if (adev->active_input != NULL &&
2299 !adev->active_input->standby) {
2300 if (is_bt_soc_on(adev) == false){
2301 ALOGD("BT SCO MIC disconnected while in connection");
2302 if (adev->active_input->pcm != NULL)
2303 pcm_stop(adev->active_input->pcm);
2304 }
2305 }
2306 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2307 && usecase->stream.out->started) {
2308 if (is_bt_soc_on(adev) == false) {
2309 ALOGD("BT SCO/A2DP disconnected while in connection");
2310 out_standby_l(&usecase->stream.out->stream.common);
2311 }
2312 }
2313 } else if ((usecase->stream.out != NULL) &&
2314 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2315 usecase->stream.out->started) {
2316 if (is_bt_soc_on(adev) == false) {
2317 ALOGD("BT SCO/A2dp disconnected while in connection");
2318 out_standby_l(&usecase->stream.out->stream.common);
2319 }
2320 }
2321 }
2322
Weiyin Jiang5d608082018-02-01 17:24:33 +08002323 /* Notify device change info to effect clients registered
2324 * NOTE: device lock has to be unlock temporarily here.
2325 * To the worst case, we notify stale info to clients.
2326 */
2327 if (usecase->type == PCM_PLAYBACK) {
2328 pthread_mutex_unlock(&adev->lock);
2329 audio_extn_gef_notify_device_config(audio_device, channel_mask, sample_rate, acdb_id);
2330 pthread_mutex_lock(&adev->lock);
2331 }
2332
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302333 ALOGD("%s: done",__func__);
2334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 return status;
2336}
2337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338static int stop_input_stream(struct stream_in *in)
2339{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302340 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302342
2343 if (in == NULL) {
2344 ALOGE("%s: stream_in ptr is NULL", __func__);
2345 return -EINVAL;
2346 }
2347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348 struct audio_device *adev = in->dev;
2349
Eric Laurent994a6932013-07-17 11:51:42 -07002350 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002351 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 uc_info = get_usecase_from_list(adev, in->usecase);
2353 if (uc_info == NULL) {
2354 ALOGE("%s: Could not find the usecase (%d) in the list",
2355 __func__, in->usecase);
2356 return -EINVAL;
2357 }
2358
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002359 /* Close in-call recording streams */
2360 voice_check_and_stop_incall_rec_usecase(adev, in);
2361
Eric Laurent150dbfe2013-02-27 14:31:02 -08002362 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002363 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002364
2365 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002366 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002368 list_remove(&uc_info->list);
2369 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002371 adev->active_input = get_next_active_input(adev);
2372
Eric Laurent994a6932013-07-17 11:51:42 -07002373 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 return ret;
2375}
2376
2377int start_input_stream(struct stream_in *in)
2378{
2379 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002380 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302382
2383 if (in == NULL) {
2384 ALOGE("%s: stream_in ptr is NULL", __func__);
2385 return -EINVAL;
2386 }
2387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002389 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002390 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391
Mingming Yin2664a5b2015-09-03 10:53:11 -07002392 if (get_usecase_from_list(adev, usecase) == NULL)
2393 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302394 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2395 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002396
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302397 if (CARD_STATUS_OFFLINE == in->card_status||
2398 CARD_STATUS_OFFLINE == adev->card_status) {
2399 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302400 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302401 goto error_config;
2402 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302403
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302404 if (audio_is_bluetooth_sco_device(in->device)) {
2405 if (!adev->bt_sco_on) {
2406 ALOGE("%s: SCO profile is not ready, return error", __func__);
2407 ret = -EIO;
2408 goto error_config;
2409 }
2410 }
2411
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002412 /* Check if source matches incall recording usecase criteria */
2413 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2414 if (ret)
2415 goto error_config;
2416 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002417 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2418
2419 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2420 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2421 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002422 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002423 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002424
Eric Laurentb23d5282013-05-14 15:27:20 -07002425 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 if (in->pcm_device_id < 0) {
2427 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2428 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002429 ret = -EINVAL;
2430 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002432
2433 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002435
2436 if (!uc_info) {
2437 ret = -ENOMEM;
2438 goto error_config;
2439 }
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 uc_info->id = in->usecase;
2442 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002443 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002444 uc_info->devices = in->device;
2445 uc_info->in_snd_device = SND_DEVICE_NONE;
2446 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002448 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302449 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2450 adev->perf_lock_opts,
2451 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002452 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453
Haynes Mathew George16081042017-05-31 17:16:49 -07002454 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302455 ret = audio_extn_cin_start_input_stream(in);
2456 if (ret)
2457 goto error_open;
2458 else
2459 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002460 }
2461
Haynes Mathew George16081042017-05-31 17:16:49 -07002462 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002463 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002464 ALOGE("%s: pcm stream not ready", __func__);
2465 goto error_open;
2466 }
2467 ret = pcm_start(in->pcm);
2468 if (ret < 0) {
2469 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2470 goto error_open;
2471 }
2472 } else {
2473 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2474 unsigned int pcm_open_retry_count = 0;
2475
2476 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2477 flags |= PCM_MMAP | PCM_NOIRQ;
2478 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2479 } else if (in->realtime) {
2480 flags |= PCM_MMAP | PCM_NOIRQ;
2481 }
2482
Garmond Leunge2433c32017-09-28 21:51:22 -07002483 if (audio_extn_ffv_get_stream() == in) {
2484 ALOGD("%s: ffv stream, update pcm config", __func__);
2485 audio_extn_ffv_update_pcm_config(&config);
2486 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002487 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2488 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2489
2490 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002491 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002492 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002493 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002494 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002495 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2496 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2497 if (in->pcm != NULL) {
2498 pcm_close(in->pcm);
2499 in->pcm = NULL;
2500 }
2501 if (pcm_open_retry_count-- == 0) {
2502 ret = -EIO;
2503 goto error_open;
2504 }
2505 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2506 continue;
2507 }
2508 break;
2509 }
2510
2511 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002512 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002513 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002514 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002515 if (ret < 0) {
2516 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2517 pcm_close(in->pcm);
2518 in->pcm = NULL;
2519 goto error_open;
2520 }
2521 register_in_stream(in);
2522 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002523 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002524 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002525 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002526 if (ret < 0) {
2527 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002528 pcm_close(in->pcm);
2529 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002530 goto error_open;
2531 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002532 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002533 }
2534
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002535 check_and_enable_effect(adev);
2536
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302537done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302538 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002539 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002540
Eric Laurentc8400632013-02-14 19:04:54 -08002541 return ret;
2542
2543error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302544 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002546error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302547 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302548 /*
2549 * sleep 50ms to allow sufficient time for kernel
2550 * drivers to recover incases like SSR.
2551 */
2552 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002553 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002554
2555 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556}
2557
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002558void lock_input_stream(struct stream_in *in)
2559{
2560 pthread_mutex_lock(&in->pre_lock);
2561 pthread_mutex_lock(&in->lock);
2562 pthread_mutex_unlock(&in->pre_lock);
2563}
2564
2565void lock_output_stream(struct stream_out *out)
2566{
2567 pthread_mutex_lock(&out->pre_lock);
2568 pthread_mutex_lock(&out->lock);
2569 pthread_mutex_unlock(&out->pre_lock);
2570}
2571
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572/* must be called with out->lock locked */
2573static int send_offload_cmd_l(struct stream_out* out, int command)
2574{
2575 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2576
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002577 if (!cmd) {
2578 ALOGE("failed to allocate mem for command 0x%x", command);
2579 return -ENOMEM;
2580 }
2581
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 ALOGVV("%s %d", __func__, command);
2583
2584 cmd->cmd = command;
2585 list_add_tail(&out->offload_cmd_list, &cmd->node);
2586 pthread_cond_signal(&out->offload_cond);
2587 return 0;
2588}
2589
2590/* must be called iwth out->lock locked */
2591static void stop_compressed_output_l(struct stream_out *out)
2592{
2593 out->offload_state = OFFLOAD_STATE_IDLE;
2594 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002595 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 if (out->compr != NULL) {
2597 compress_stop(out->compr);
2598 while (out->offload_thread_blocked) {
2599 pthread_cond_wait(&out->cond, &out->lock);
2600 }
2601 }
2602}
2603
Varun Balaraje49253e2017-07-06 19:48:56 +05302604bool is_interactive_usecase(audio_usecase_t uc_id)
2605{
2606 unsigned int i;
2607 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2608 if (uc_id == interactive_usecases[i])
2609 return true;
2610 }
2611 return false;
2612}
2613
2614static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2615{
2616 audio_usecase_t ret_uc = USECASE_INVALID;
2617 unsigned int intract_uc_index;
2618 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2619
2620 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2621 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2622 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2623 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2624 ret_uc = interactive_usecases[intract_uc_index];
2625 break;
2626 }
2627 }
2628
2629 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2630 return ret_uc;
2631}
2632
2633static void free_interactive_usecase(struct audio_device *adev,
2634 audio_usecase_t uc_id)
2635{
2636 unsigned int interact_uc_index;
2637 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2638
2639 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2640 if (interactive_usecases[interact_uc_index] == uc_id) {
2641 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2642 break;
2643 }
2644 }
2645 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2646}
2647
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002648bool is_offload_usecase(audio_usecase_t uc_id)
2649{
2650 unsigned int i;
2651 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2652 if (uc_id == offload_usecases[i])
2653 return true;
2654 }
2655 return false;
2656}
2657
Dhananjay Kumarac341582017-02-23 23:42:25 +05302658static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002659{
vivek mehta446c3962015-09-14 10:57:35 -07002660 audio_usecase_t ret_uc = USECASE_INVALID;
2661 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002662 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002663 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302664 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002665 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2666 else
2667 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002668
vivek mehta446c3962015-09-14 10:57:35 -07002669 pthread_mutex_lock(&adev->lock);
2670 if (get_usecase_from_list(adev, ret_uc) != NULL)
2671 ret_uc = USECASE_INVALID;
2672 pthread_mutex_unlock(&adev->lock);
2673
2674 return ret_uc;
2675 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002676
2677 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002678 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2679 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2680 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2681 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002682 break;
2683 }
2684 }
vivek mehta446c3962015-09-14 10:57:35 -07002685
2686 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2687 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002688}
2689
2690static void free_offload_usecase(struct audio_device *adev,
2691 audio_usecase_t uc_id)
2692{
vivek mehta446c3962015-09-14 10:57:35 -07002693 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002694 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002695
2696 if (!adev->multi_offload_enable)
2697 return;
2698
2699 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2700 if (offload_usecases[offload_uc_index] == uc_id) {
2701 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002702 break;
2703 }
2704 }
2705 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2706}
2707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002708static void *offload_thread_loop(void *context)
2709{
2710 struct stream_out *out = (struct stream_out *) context;
2711 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002712 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002714 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2715 set_sched_policy(0, SP_FOREGROUND);
2716 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2717
2718 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002719 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 for (;;) {
2721 struct offload_cmd *cmd = NULL;
2722 stream_callback_event_t event;
2723 bool send_callback = false;
2724
2725 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2726 __func__, list_empty(&out->offload_cmd_list),
2727 out->offload_state);
2728 if (list_empty(&out->offload_cmd_list)) {
2729 ALOGV("%s SLEEPING", __func__);
2730 pthread_cond_wait(&out->offload_cond, &out->lock);
2731 ALOGV("%s RUNNING", __func__);
2732 continue;
2733 }
2734
2735 item = list_head(&out->offload_cmd_list);
2736 cmd = node_to_item(item, struct offload_cmd, node);
2737 list_remove(item);
2738
2739 ALOGVV("%s STATE %d CMD %d out->compr %p",
2740 __func__, out->offload_state, cmd->cmd, out->compr);
2741
2742 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2743 free(cmd);
2744 break;
2745 }
2746
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002747 // allow OFFLOAD_CMD_ERROR reporting during standby
2748 // this is needed to handle failures during compress_open
2749 // Note however that on a pause timeout, the stream is closed
2750 // and no offload usecase will be active. Therefore this
2751 // special case is needed for compress_open failures alone
2752 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2753 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002754 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002755 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002756 pthread_cond_signal(&out->cond);
2757 continue;
2758 }
2759 out->offload_thread_blocked = true;
2760 pthread_mutex_unlock(&out->lock);
2761 send_callback = false;
2762 switch(cmd->cmd) {
2763 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002764 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002766 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002767 send_callback = true;
2768 event = STREAM_CBK_EVENT_WRITE_READY;
2769 break;
2770 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002771 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302772 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002773 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302774 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002775 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302776 if (ret < 0)
2777 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302778 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302779 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002780 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002781 else
2782 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002783 if (-ENETRESET != ret && !(-EINTR == ret &&
2784 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302785 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302786 pthread_mutex_lock(&out->lock);
2787 out->send_new_metadata = 1;
2788 out->send_next_track_params = true;
2789 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302790 event = STREAM_CBK_EVENT_DRAIN_READY;
2791 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2792 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302793 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794 break;
2795 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002796 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08002797 ret = compress_drain(out->compr);
2798 ALOGD("copl(%p):out of compress_drain", out);
2799 // EINTR check avoids drain interruption due to SSR
2800 if (-ENETRESET != ret && !(-EINTR == ret &&
2801 CARD_STATUS_OFFLINE == out->card_status)) {
2802 send_callback = true;
2803 event = STREAM_CBK_EVENT_DRAIN_READY;
2804 } else
2805 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302807 case OFFLOAD_CMD_ERROR:
2808 ALOGD("copl(%p): sending error callback to AF", out);
2809 send_callback = true;
2810 event = STREAM_CBK_EVENT_ERROR;
2811 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002812 default:
2813 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2814 break;
2815 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002816 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 out->offload_thread_blocked = false;
2818 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002819 if (send_callback && out->client_callback) {
2820 ALOGVV("%s: sending client_callback event %d", __func__, event);
2821 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002822 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 free(cmd);
2824 }
2825
2826 pthread_cond_signal(&out->cond);
2827 while (!list_empty(&out->offload_cmd_list)) {
2828 item = list_head(&out->offload_cmd_list);
2829 list_remove(item);
2830 free(node_to_item(item, struct offload_cmd, node));
2831 }
2832 pthread_mutex_unlock(&out->lock);
2833
2834 return NULL;
2835}
2836
2837static int create_offload_callback_thread(struct stream_out *out)
2838{
2839 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2840 list_init(&out->offload_cmd_list);
2841 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2842 offload_thread_loop, out);
2843 return 0;
2844}
2845
2846static int destroy_offload_callback_thread(struct stream_out *out)
2847{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002848 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 stop_compressed_output_l(out);
2850 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2851
2852 pthread_mutex_unlock(&out->lock);
2853 pthread_join(out->offload_thread, (void **) NULL);
2854 pthread_cond_destroy(&out->offload_cond);
2855
2856 return 0;
2857}
2858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859static int stop_output_stream(struct stream_out *out)
2860{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302861 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862 struct audio_usecase *uc_info;
2863 struct audio_device *adev = out->dev;
2864
Eric Laurent994a6932013-07-17 11:51:42 -07002865 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002866 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 uc_info = get_usecase_from_list(adev, out->usecase);
2868 if (uc_info == NULL) {
2869 ALOGE("%s: Could not find the usecase (%d) in the list",
2870 __func__, out->usecase);
2871 return -EINVAL;
2872 }
2873
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002874 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302875 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002876 if (adev->visualizer_stop_output != NULL)
2877 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002878
2879 audio_extn_dts_remove_state_notifier_node(out->usecase);
2880
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002881 if (adev->offload_effects_stop_output != NULL)
2882 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2883 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002884
Eric Laurent150dbfe2013-02-27 14:31:02 -08002885 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002886 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002887
2888 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002889 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002891 if (is_offload_usecase(out->usecase)) {
2892 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2893 adev->dsp_bit_width_enforce_mode,
2894 false);
2895 }
2896
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002897 list_remove(&uc_info->list);
2898 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302899 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002900 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302901 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902 ALOGV("Disable passthrough , reset mixer to pcm");
2903 /* NO_PASSTHROUGH */
2904 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002905 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002906 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2907 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002908
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302909 /* Must be called after removing the usecase from list */
2910 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05302911 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302912
Manish Dewangan21a850a2017-08-14 12:03:55 +05302913 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002914 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2915 if (ret < 0)
2916 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2917 }
2918
Eric Laurent994a6932013-07-17 11:51:42 -07002919 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 return ret;
2921}
2922
2923int start_output_stream(struct stream_out *out)
2924{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 struct audio_usecase *uc_info;
2927 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002928 char mixer_ctl_name[128];
2929 struct mixer_ctl *ctl = NULL;
2930 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302931 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932
Haynes Mathew George380745d2017-10-04 15:27:45 -07002933 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002934 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2935 ret = -EINVAL;
2936 goto error_config;
2937 }
2938
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302939 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2940 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2941 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302942
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302943 if (CARD_STATUS_OFFLINE == out->card_status ||
2944 CARD_STATUS_OFFLINE == adev->card_status) {
2945 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302946 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302947 goto error_config;
2948 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302949
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302950 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2951 if (!audio_extn_a2dp_is_ready()) {
2952 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302953 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302954 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302955 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2956 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2957 ret = -EAGAIN;
2958 goto error_config;
2959 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302960 }
2961 }
2962 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302963 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2964 if (!adev->bt_sco_on) {
2965 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2966 //combo usecase just by pass a2dp
2967 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2968 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2969 } else {
2970 ALOGE("%s: SCO profile is not ready, return error", __func__);
2971 ret = -EAGAIN;
2972 goto error_config;
2973 }
2974 }
2975 }
2976
Eric Laurentb23d5282013-05-14 15:27:20 -07002977 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 if (out->pcm_device_id < 0) {
2979 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2980 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002981 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002982 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 }
2984
2985 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002986
2987 if (!uc_info) {
2988 ret = -ENOMEM;
2989 goto error_config;
2990 }
2991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 uc_info->id = out->usecase;
2993 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002994 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002995 uc_info->devices = out->devices;
2996 uc_info->in_snd_device = SND_DEVICE_NONE;
2997 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002998 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303000 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3001 adev->perf_lock_opts,
3002 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303003
3004 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303005 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303006 if (audio_extn_passthru_is_enabled() &&
3007 audio_extn_passthru_is_passthrough_stream(out)) {
3008 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303009 }
3010 }
3011
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303012 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3013 (!audio_extn_a2dp_is_ready())) {
3014 if (!a2dp_combo) {
3015 check_a2dp_restore_l(adev, out, false);
3016 } else {
3017 audio_devices_t dev = out->devices;
3018 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3019 select_devices(adev, out->usecase);
3020 out->devices = dev;
3021 }
3022 } else {
3023 select_devices(adev, out->usecase);
3024 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003025
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003026 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3027 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003028
3029 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3030 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3031 ALOGE("%s: pcm stream not ready", __func__);
3032 goto error_open;
3033 }
3034 ret = pcm_start(out->pcm);
3035 if (ret < 0) {
3036 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3037 goto error_open;
3038 }
3039 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003040 unsigned int flags = PCM_OUT;
3041 unsigned int pcm_open_retry_count = 0;
3042 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3043 flags |= PCM_MMAP | PCM_NOIRQ;
3044 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003045 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003046 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003047 } else
3048 flags |= PCM_MONOTONIC;
3049
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003050 if ((adev->vr_audio_mode_enabled) &&
3051 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3052 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3053 "PCM_Dev %d Topology", out->pcm_device_id);
3054 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3055 if (!ctl) {
3056 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3057 __func__, mixer_ctl_name);
3058 } else {
3059 //if success use ULLPP
3060 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3061 __func__, mixer_ctl_name, out->pcm_device_id);
3062 //There is a still a possibility that some sessions
3063 // that request for FAST|RAW when 3D audio is active
3064 //can go through ULLPP. Ideally we expects apps to
3065 //listen to audio focus and stop concurrent playback
3066 //Also, we will look for mode flag (voice_in_communication)
3067 //before enabling the realtime flag.
3068 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3069 }
3070 }
3071
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003072 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003073 ATRACE_BEGIN("pcm_open");
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003074 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3075 flags, &out->config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003076 ATRACE_END();
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003077 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3078 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3079 if (out->pcm != NULL) {
3080 pcm_close(out->pcm);
3081 out->pcm = NULL;
3082 }
3083 if (pcm_open_retry_count-- == 0) {
3084 ret = -EIO;
3085 goto error_open;
3086 }
3087 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3088 continue;
3089 }
3090 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003092
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003093 ALOGV("%s: pcm_prepare", __func__);
3094 if (pcm_is_ready(out->pcm)) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003095 ATRACE_BEGIN("pcm_prepare");
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003096 ret = pcm_prepare(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003097 ATRACE_END();
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003098 if (ret < 0) {
3099 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3100 pcm_close(out->pcm);
3101 out->pcm = NULL;
3102 goto error_open;
3103 }
3104 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303105 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303106 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003107 // apply volume for voip playback after path is set up
3108 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3109 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003111 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303112 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003113 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3114 adev->dsp_bit_width_enforce_mode,
3115 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003117 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003118 out->compr = compress_open(adev->snd_card,
3119 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003121 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003123 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 compress_close(out->compr);
3125 out->compr = NULL;
3126 ret = -EIO;
3127 goto error_open;
3128 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303129 /* compress_open sends params of the track, so reset the flag here */
3130 out->is_compr_metadata_avail = false;
3131
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003132 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003134
Fred Oh3f43e742015-03-04 18:42:34 -08003135 /* Since small bufs uses blocking writes, a write will be blocked
3136 for the default max poll time (20s) in the event of an SSR.
3137 Reduce the poll time to observe and deal with SSR faster.
3138 */
Ashish Jain5106d362016-05-11 19:23:33 +05303139 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003140 compress_set_max_poll_wait(out->compr, 1000);
3141 }
3142
Manish Dewangan69426c82017-01-30 17:35:36 +05303143 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303144 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303145
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003146 audio_extn_dts_create_state_notifier_node(out->usecase);
3147 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3148 popcount(out->channel_mask),
3149 out->playback_started);
3150
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003151#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303152 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003153 audio_extn_dolby_send_ddp_endp_params(adev);
3154#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303155 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3156 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003157 if (adev->visualizer_start_output != NULL)
3158 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3159 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303160 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003161 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003164
3165 if (ret == 0) {
3166 register_out_stream(out);
3167 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003168 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3169 ALOGE("%s: pcm stream not ready", __func__);
3170 goto error_open;
3171 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003172 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003173 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003174 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003175 if (ret < 0)
3176 goto error_open;
3177 }
3178 }
3179
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303180 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003181 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003182
Manish Dewangan21a850a2017-08-14 12:03:55 +05303183 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003184 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003185 if (ret < 0)
3186 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3187 }
3188
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003189 // consider a scenario where on pause lower layers are tear down.
3190 // so on resume, swap mixer control need to be sent only when
3191 // backend is active, hence rather than sending from enable device
3192 // sending it from start of streamtream
3193
3194 platform_set_swap_channels(adev, true);
3195
Haynes Mathew George380745d2017-10-04 15:27:45 -07003196 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003197 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303199 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003201error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303202 /*
3203 * sleep 50ms to allow sufficient time for kernel
3204 * drivers to recover incases like SSR.
3205 */
3206 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003207 ATRACE_END();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003208 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209}
3210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211static int check_input_parameters(uint32_t sample_rate,
3212 audio_format_t format,
3213 int channel_count)
3214{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003215 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303217 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3218 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3219 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003220 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003221 !audio_extn_compr_cap_format_supported(format))
3222 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003223
3224 switch (channel_count) {
3225 case 1:
3226 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303227 case 3:
3228 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003229 case 6:
3230 break;
3231 default:
3232 ret = -EINVAL;
3233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234
3235 switch (sample_rate) {
3236 case 8000:
3237 case 11025:
3238 case 12000:
3239 case 16000:
3240 case 22050:
3241 case 24000:
3242 case 32000:
3243 case 44100:
3244 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003245 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303246 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003247 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303248 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 break;
3250 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003251 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 }
3253
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003254 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255}
3256
3257static size_t get_input_buffer_size(uint32_t sample_rate,
3258 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003259 int channel_count,
3260 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261{
3262 size_t size = 0;
3263
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003264 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3265 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003267 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003268 if (is_low_latency)
3269 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303270
3271 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003273 /* make sure the size is multiple of 32 bytes
3274 * At 48 kHz mono 16-bit PCM:
3275 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3276 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3277 */
3278 size += 0x1f;
3279 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003280
3281 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282}
3283
Ashish Jain058165c2016-09-28 23:18:48 +05303284static size_t get_output_period_size(uint32_t sample_rate,
3285 audio_format_t format,
3286 int channel_count,
3287 int duration /*in millisecs*/)
3288{
3289 size_t size = 0;
3290 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3291
3292 if ((duration == 0) || (sample_rate == 0) ||
3293 (bytes_per_sample == 0) || (channel_count == 0)) {
3294 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3295 bytes_per_sample, channel_count);
3296 return -EINVAL;
3297 }
3298
3299 size = (sample_rate *
3300 duration *
3301 bytes_per_sample *
3302 channel_count) / 1000;
3303 /*
3304 * To have same PCM samples for all channels, the buffer size requires to
3305 * be multiple of (number of channels * bytes per sample)
3306 * For writes to succeed, the buffer must be written at address which is multiple of 32
3307 */
3308 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3309
3310 return (size/(channel_count * bytes_per_sample));
3311}
3312
Zhou Song48453a02018-01-10 17:50:59 +08003313static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303314{
3315 uint64_t actual_frames_rendered = 0;
3316 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3317
3318 /* This adjustment accounts for buffering after app processor.
3319 * It is based on estimated DSP latency per use case, rather than exact.
3320 */
3321 int64_t platform_latency = platform_render_latency(out->usecase) *
3322 out->sample_rate / 1000000LL;
3323
Zhou Song48453a02018-01-10 17:50:59 +08003324 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303325 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3326 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3327 * hence only estimate.
3328 */
3329 int64_t signed_frames = out->written - kernel_buffer_size;
3330
3331 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3332
Zhou Song48453a02018-01-10 17:50:59 +08003333 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303334 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003335 if (timestamp != NULL )
3336 *timestamp = out->writeAt;
3337 } else if (timestamp != NULL) {
3338 clock_gettime(CLOCK_MONOTONIC, timestamp);
3339 }
3340 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303341
3342 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3343 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3344 (long long int)out->written, (int)kernel_buffer_size,
3345 audio_bytes_per_sample(out->compr_config.codec->format),
3346 popcount(out->channel_mask));
3347
3348 return actual_frames_rendered;
3349}
3350
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3352{
3353 struct stream_out *out = (struct stream_out *)stream;
3354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356}
3357
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003358static int out_set_sample_rate(struct audio_stream *stream __unused,
3359 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360{
3361 return -ENOSYS;
3362}
3363
3364static size_t out_get_buffer_size(const struct audio_stream *stream)
3365{
3366 struct stream_out *out = (struct stream_out *)stream;
3367
Varun Balaraje49253e2017-07-06 19:48:56 +05303368 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303369 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303370 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303371 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3372 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3373 else
3374 return out->compr_config.fragment_size;
3375 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003376 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003377 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3378 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 +05303379 else if (is_offload_usecase(out->usecase) &&
3380 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303381 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003383 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003384 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385}
3386
3387static uint32_t out_get_channels(const struct audio_stream *stream)
3388{
3389 struct stream_out *out = (struct stream_out *)stream;
3390
3391 return out->channel_mask;
3392}
3393
3394static audio_format_t out_get_format(const struct audio_stream *stream)
3395{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003396 struct stream_out *out = (struct stream_out *)stream;
3397
3398 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399}
3400
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003401static int out_set_format(struct audio_stream *stream __unused,
3402 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403{
3404 return -ENOSYS;
3405}
3406
3407static int out_standby(struct audio_stream *stream)
3408{
3409 struct stream_out *out = (struct stream_out *)stream;
3410 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003411 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303413 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3414 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003416 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003418 if (adev->adm_deregister_stream)
3419 adev->adm_deregister_stream(adev->adm_data, out->handle);
3420
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003421 if (is_offload_usecase(out->usecase))
3422 stop_compressed_output_l(out);
3423
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003424 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003426 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3427 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303428 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003429 pthread_mutex_unlock(&adev->lock);
3430 pthread_mutex_unlock(&out->lock);
3431 ALOGD("VOIP output entered standby");
3432 return 0;
3433 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003434 if (out->pcm) {
3435 pcm_close(out->pcm);
3436 out->pcm = NULL;
3437 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003438 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3439 do_stop = out->playback_started;
3440 out->playback_started = false;
3441 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003442 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003443 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303444 out->send_next_track_params = false;
3445 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003446 out->gapless_mdata.encoder_delay = 0;
3447 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 if (out->compr != NULL) {
3449 compress_close(out->compr);
3450 out->compr = NULL;
3451 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003452 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003453 if (do_stop) {
3454 stop_output_stream(out);
3455 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003456 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 }
3458 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303459 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 return 0;
3461}
3462
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303463static int out_on_error(struct audio_stream *stream)
3464{
3465 struct stream_out *out = (struct stream_out *)stream;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303466
3467 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003468 // always send CMD_ERROR for offload streams, this
3469 // is needed e.g. when SSR happens within compress_open
3470 // since the stream is active, offload_callback_thread is also active.
3471 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3472 stop_compressed_output_l(out);
3473 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303474 }
3475 pthread_mutex_unlock(&out->lock);
3476
Aniket Kumar Lata28abfc12017-12-28 10:53:07 -08003477 return out_standby(&out->stream.common);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303478}
3479
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303480/*
3481 *standby implementation without locks, assumes that the callee already
3482 *has taken adev and out lock.
3483 */
3484int out_standby_l(struct audio_stream *stream)
3485{
3486 struct stream_out *out = (struct stream_out *)stream;
3487 struct audio_device *adev = out->dev;
3488
3489 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3490 stream, out->usecase, use_case_table[out->usecase]);
3491
3492 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003493 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303494 if (adev->adm_deregister_stream)
3495 adev->adm_deregister_stream(adev->adm_data, out->handle);
3496
3497 if (is_offload_usecase(out->usecase))
3498 stop_compressed_output_l(out);
3499
3500 out->standby = true;
3501 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3502 voice_extn_compress_voip_close_output_stream(stream);
3503 out->started = 0;
3504 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003505 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303506 return 0;
3507 } else if (!is_offload_usecase(out->usecase)) {
3508 if (out->pcm) {
3509 pcm_close(out->pcm);
3510 out->pcm = NULL;
3511 }
3512 } else {
3513 ALOGD("copl(%p):standby", out);
3514 out->send_next_track_params = false;
3515 out->is_compr_metadata_avail = false;
3516 out->gapless_mdata.encoder_delay = 0;
3517 out->gapless_mdata.encoder_padding = 0;
3518 if (out->compr != NULL) {
3519 compress_close(out->compr);
3520 out->compr = NULL;
3521 }
3522 }
3523 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003524 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303525 }
3526 ALOGD("%s: exit", __func__);
3527 return 0;
3528}
3529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003530static int out_dump(const struct audio_stream *stream __unused,
3531 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532{
3533 return 0;
3534}
3535
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003536static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3537{
3538 int ret = 0;
3539 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003540
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003541 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003542 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003543 return -EINVAL;
3544 }
3545
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303546 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003547
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003548 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3549 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303550 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003551 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003552 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3553 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303554 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003555 }
3556
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003557 ALOGV("%s new encoder delay %u and padding %u", __func__,
3558 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3559
3560 return 0;
3561}
3562
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003563static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3564{
3565 return out == adev->primary_output || out == adev->voice_tx_output;
3566}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003567
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303568// note: this call is safe only if the stream_cb is
3569// removed first in close_output_stream (as is done now).
3570static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3571{
3572 if (!stream || !parms)
3573 return;
3574
3575 struct stream_out *out = (struct stream_out *)stream;
3576 struct audio_device *adev = out->dev;
3577
3578 card_status_t status;
3579 int card;
3580 if (parse_snd_card_status(parms, &card, &status) < 0)
3581 return;
3582
3583 pthread_mutex_lock(&adev->lock);
3584 bool valid_cb = (card == adev->snd_card);
3585 pthread_mutex_unlock(&adev->lock);
3586
3587 if (!valid_cb)
3588 return;
3589
3590 lock_output_stream(out);
3591 if (out->card_status != status)
3592 out->card_status = status;
3593 pthread_mutex_unlock(&out->lock);
3594
3595 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3596 use_case_table[out->usecase],
3597 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3598
3599 if (status == CARD_STATUS_OFFLINE)
3600 out_on_error(stream);
3601
3602 return;
3603}
3604
Kevin Rocardfce19002017-08-07 19:21:36 -07003605static int get_alive_usb_card(struct str_parms* parms) {
3606 int card;
3607 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
3608 !audio_extn_usb_alive(card)) {
3609 return card;
3610 }
3611 return -ENODEV;
3612}
3613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3615{
3616 struct stream_out *out = (struct stream_out *)stream;
3617 struct audio_device *adev = out->dev;
3618 struct str_parms *parms;
3619 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003620 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303621 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622
sangwoobc677242013-08-08 16:53:43 +09003623 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003624 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303626 if (!parms)
3627 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003628 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3629 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003631 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003632 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003634 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003635 * When HDMI cable is unplugged the music playback is paused and
3636 * the policy manager sends routing=0. But the audioflinger continues
3637 * to write data until standby time (3sec). As the HDMI core is
3638 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003639 * Avoid this by routing audio to speaker until standby.
3640 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003641 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3642 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303643 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003644 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3645 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003646 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303647 /*
3648 * When A2DP is disconnected the
3649 * music playback is paused and the policy manager sends routing=0
3650 * But the audioflingercontinues to write data until standby time
3651 * (3sec). As BT is turned off, the write gets blocked.
3652 * Avoid this by routing audio to speaker until standby.
3653 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003654 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07003655 (val == AUDIO_DEVICE_NONE) &&
3656 !audio_extn_a2dp_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303657 val = AUDIO_DEVICE_OUT_SPEAKER;
3658 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303659 /* To avoid a2dp to sco overlapping / BT device improper state
3660 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303661 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303662 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3663 if (!audio_extn_a2dp_is_ready()) {
3664 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3665 //combo usecase just by pass a2dp
3666 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303667 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303668 } else {
3669 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3670 /* update device to a2dp and don't route as BT returned error
3671 * However it is still possible a2dp routing called because
3672 * of current active device disconnection (like wired headset)
3673 */
3674 out->devices = val;
3675 pthread_mutex_unlock(&out->lock);
3676 pthread_mutex_unlock(&adev->lock);
3677 goto error;
3678 }
3679 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303680 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003681
3682 audio_devices_t new_dev = val;
3683
3684 // Workaround: If routing to an non existing usb device, fail gracefully
3685 // The routing request will otherwise block during 10 second
3686 int card;
3687 if (audio_is_usb_out_device(new_dev) &&
3688 (card = get_alive_usb_card(parms)) >= 0) {
3689
3690 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
3691 pthread_mutex_unlock(&adev->lock);
3692 pthread_mutex_unlock(&out->lock);
3693 ret = -ENOSYS;
3694 goto routing_fail;
3695 }
3696
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003697 /*
3698 * select_devices() call below switches all the usecases on the same
3699 * backend to the new device. Refer to check_usecases_codec_backend() in
3700 * the select_devices(). But how do we undo this?
3701 *
3702 * For example, music playback is active on headset (deep-buffer usecase)
3703 * and if we go to ringtones and select a ringtone, low-latency usecase
3704 * will be started on headset+speaker. As we can't enable headset+speaker
3705 * and headset devices at the same time, select_devices() switches the music
3706 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3707 * So when the ringtone playback is completed, how do we undo the same?
3708 *
3709 * We are relying on the out_set_parameters() call on deep-buffer output,
3710 * once the ringtone playback is ended.
3711 * NOTE: We should not check if the current devices are same as new devices.
3712 * Because select_devices() must be called to switch back the music
3713 * playback to headset.
3714 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003715 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003716 audio_devices_t new_dev = val;
3717 bool same_dev = out->devices == new_dev;
3718 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003719
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003720 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08003721 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003722 if (adev->mode == AUDIO_MODE_IN_CALL) {
3723 adev->current_call_output = out;
3724 ret = voice_start_call(adev);
3725 }
3726 } else {
3727 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003728 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003729 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003730 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003731
3732 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003733 if (!same_dev) {
3734 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303735 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3736 adev->perf_lock_opts,
3737 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003738 if (adev->adm_on_routing_change)
3739 adev->adm_on_routing_change(adev->adm_data,
3740 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003741 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303742 if (!bypass_a2dp) {
3743 select_devices(adev, out->usecase);
3744 } else {
3745 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3746 select_devices(adev, out->usecase);
3747 out->devices = new_dev;
3748 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003749
3750 if (!same_dev) {
3751 // on device switch force swap, lower functions will make sure
3752 // to check if swap is allowed or not.
3753 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303754 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003755 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303756 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3757 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003758 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303759 pthread_mutex_lock(&out->compr_mute_lock);
3760 out->a2dp_compress_mute = false;
3761 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3762 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08003763 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3764 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303765 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003766 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003767 }
3768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003770 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 }
Kevin Rocardfce19002017-08-07 19:21:36 -07003772 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003773
3774 if (out == adev->primary_output) {
3775 pthread_mutex_lock(&adev->lock);
3776 audio_extn_set_parameters(adev, parms);
3777 pthread_mutex_unlock(&adev->lock);
3778 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003779 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003780 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003781 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003782
3783 audio_extn_dts_create_state_notifier_node(out->usecase);
3784 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3785 popcount(out->channel_mask),
3786 out->playback_started);
3787
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003788 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003789 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003790
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303791 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3792 if (err >= 0) {
3793 strlcpy(out->profile, value, sizeof(out->profile));
3794 ALOGV("updating stream profile with value '%s'", out->profile);
3795 lock_output_stream(out);
3796 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3797 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003798 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303799 out->sample_rate, out->bit_width,
3800 out->channel_mask, out->profile,
3801 &out->app_type_cfg);
3802 pthread_mutex_unlock(&out->lock);
3803 }
3804
Alexy Joseph98988832017-01-13 14:56:59 -08003805 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08003806 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
3807 // and vendor.audio.hal.output.suspend.supported is set to true
3808 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08003809 //check suspend parameter only for low latency and if the property
3810 //is enabled
3811 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3812 ALOGI("%s: got suspend_playback %s", __func__, value);
3813 lock_output_stream(out);
3814 if (!strncmp(value, "false", 5)) {
3815 //suspend_playback=false is supposed to set QOS value back to 75%
3816 //the mixer control sent with value Enable will achieve that
3817 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3818 } else if (!strncmp (value, "true", 4)) {
3819 //suspend_playback=true is supposed to remove QOS value
3820 //resetting the mixer control will set the default value
3821 //for the mixer control which is Disable and this removes the QOS vote
3822 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3823 } else {
3824 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3825 " got %s", __func__, value);
3826 ret = -1;
3827 }
3828
3829 if (ret != 0) {
3830 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3831 __func__, out->pm_qos_mixer_path, ret);
3832 }
3833
3834 pthread_mutex_unlock(&out->lock);
3835 }
3836 }
3837 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303839error:
Eric Laurent994a6932013-07-17 11:51:42 -07003840 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 return ret;
3842}
3843
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003844static bool stream_get_parameter_channels(struct str_parms *query,
3845 struct str_parms *reply,
3846 audio_channel_mask_t *supported_channel_masks) {
3847 int ret = -1;
3848 char value[512];
3849 bool first = true;
3850 size_t i, j;
3851
3852 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3853 ret = 0;
3854 value[0] = '\0';
3855 i = 0;
3856 while (supported_channel_masks[i] != 0) {
3857 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3858 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
3859 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303860 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003861
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303862 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003863 first = false;
3864 break;
3865 }
3866 }
3867 i++;
3868 }
3869 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3870 }
3871 return ret == 0;
3872}
3873
3874static bool stream_get_parameter_formats(struct str_parms *query,
3875 struct str_parms *reply,
3876 audio_format_t *supported_formats) {
3877 int ret = -1;
3878 char value[256];
3879 size_t i, j;
3880 bool first = true;
3881
3882 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3883 ret = 0;
3884 value[0] = '\0';
3885 i = 0;
3886 while (supported_formats[i] != 0) {
3887 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3888 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
3889 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303890 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003891 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303892 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003893 first = false;
3894 break;
3895 }
3896 }
3897 i++;
3898 }
3899 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
3900 }
3901 return ret == 0;
3902}
3903
3904static bool stream_get_parameter_rates(struct str_parms *query,
3905 struct str_parms *reply,
3906 uint32_t *supported_sample_rates) {
3907
3908 int i;
3909 char value[256];
3910 int ret = -1;
3911 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3912 ret = 0;
3913 value[0] = '\0';
3914 i=0;
3915 int cursor = 0;
3916 while (supported_sample_rates[i]) {
3917 int avail = sizeof(value) - cursor;
3918 ret = snprintf(value + cursor, avail, "%s%d",
3919 cursor > 0 ? "|" : "",
3920 supported_sample_rates[i]);
3921 if (ret < 0 || ret >= avail) {
3922 // if cursor is at the last element of the array
3923 // overwrite with \0 is duplicate work as
3924 // snprintf already put a \0 in place.
3925 // else
3926 // we had space to write the '|' at value[cursor]
3927 // (which will be overwritten) or no space to fill
3928 // the first element (=> cursor == 0)
3929 value[cursor] = '\0';
3930 break;
3931 }
3932 cursor += ret;
3933 ++i;
3934 }
3935 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3936 value);
3937 }
3938 return ret >= 0;
3939}
3940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3942{
3943 struct stream_out *out = (struct stream_out *)stream;
3944 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003945 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 char value[256];
3947 struct str_parms *reply = str_parms_create();
3948 size_t i, j;
3949 int ret;
3950 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003951
3952 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003953 if (reply) {
3954 str_parms_destroy(reply);
3955 }
3956 if (query) {
3957 str_parms_destroy(query);
3958 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003959 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3960 return NULL;
3961 }
3962
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003963 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3965 if (ret >= 0) {
3966 value[0] = '\0';
3967 i = 0;
3968 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003969 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3970 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003972 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003974 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975 first = false;
3976 break;
3977 }
3978 }
3979 i++;
3980 }
3981 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3982 str = str_parms_to_str(reply);
3983 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003984 voice_extn_out_get_parameters(out, query, reply);
3985 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003987
Alexy Joseph62142aa2015-11-16 15:10:34 -08003988
3989 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3990 if (ret >= 0) {
3991 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303992 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3993 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003994 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303995 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003996 } else {
3997 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303998 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003999 }
4000 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004001 if (str)
4002 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004003 str = str_parms_to_str(reply);
4004 }
4005
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004006 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4007 if (ret >= 0) {
4008 value[0] = '\0';
4009 i = 0;
4010 first = true;
4011 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004012 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4013 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004014 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004015 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004016 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004017 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004018 first = false;
4019 break;
4020 }
4021 }
4022 i++;
4023 }
4024 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004025 if (str)
4026 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004027 str = str_parms_to_str(reply);
4028 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004029
4030 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4031 if (ret >= 0) {
4032 value[0] = '\0';
4033 i = 0;
4034 first = true;
4035 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004036 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4037 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004038 if (!first) {
4039 strlcat(value, "|", sizeof(value));
4040 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004041 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004042 first = false;
4043 break;
4044 }
4045 }
4046 i++;
4047 }
4048 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4049 if (str)
4050 free(str);
4051 str = str_parms_to_str(reply);
4052 }
4053
Alexy Joseph98988832017-01-13 14:56:59 -08004054 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4055 //only low latency track supports suspend_resume
4056 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004057 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004058 if (str)
4059 free(str);
4060 str = str_parms_to_str(reply);
4061 }
4062
4063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 str_parms_destroy(query);
4065 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004066 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 return str;
4068}
4069
4070static uint32_t out_get_latency(const struct audio_stream_out *stream)
4071{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004072 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004074 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075
Alexy Josephaa54c872014-12-03 02:46:47 -08004076 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304077 lock_output_stream(out);
4078 latency = audio_extn_utils_compress_get_dsp_latency(out);
4079 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004080 } else if ((out->realtime) ||
4081 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004082 // since the buffer won't be filled up faster than realtime,
4083 // return a smaller number
4084 if (out->config.rate)
4085 period_ms = (out->af_period_multiplier * out->config.period_size *
4086 1000) / (out->config.rate);
4087 else
4088 period_ms = 0;
4089 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004090 } else {
4091 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004092 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004093 }
4094
yidongh0515e042017-07-06 15:00:34 +08004095 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004096 latency += audio_extn_a2dp_get_encoder_latency();
4097
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304098 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004099 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100}
4101
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304102static float AmpToDb(float amplification)
4103{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304104 float db = DSD_VOLUME_MIN_DB;
4105 if (amplification > 0) {
4106 db = 20 * log10(amplification);
4107 if(db < DSD_VOLUME_MIN_DB)
4108 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304109 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304110 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304111}
4112
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304113static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4114 float right)
4115{
4116 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304117 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304118 char mixer_ctl_name[128];
4119 struct audio_device *adev = out->dev;
4120 struct mixer_ctl *ctl;
4121 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4122 PCM_PLAYBACK);
4123
4124 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4125 "Compress Playback %d Volume", pcm_device_id);
4126 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4127 if (!ctl) {
4128 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4129 __func__, mixer_ctl_name);
4130 return -EINVAL;
4131 }
4132 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4133 __func__, mixer_ctl_name, left, right);
4134 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4135 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4136 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4137
4138 return 0;
4139}
4140
Zhou Song2b8f28f2017-09-11 10:51:38 +08004141static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4142 float right)
4143{
4144 struct stream_out *out = (struct stream_out *)stream;
4145 char mixer_ctl_name[] = "App Type Gain";
4146 struct audio_device *adev = out->dev;
4147 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304148 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004149
4150 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4151 if (!ctl) {
4152 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4153 __func__, mixer_ctl_name);
4154 return -EINVAL;
4155 }
4156
4157 set_values[0] = 0; //0: Rx Session 1:Tx Session
4158 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304159 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4160 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004161
4162 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4163 return 0;
4164}
4165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166static int out_set_volume(struct audio_stream_out *stream, float left,
4167 float right)
4168{
Eric Laurenta9024de2013-04-04 09:19:12 -07004169 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004170 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304171 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004172
Eric Laurenta9024de2013-04-04 09:19:12 -07004173 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4174 /* only take left channel into account: the API is for stereo anyway */
4175 out->muted = (left == 0.0f);
4176 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004177 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304178 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004179 /*
4180 * Set mute or umute on HDMI passthrough stream.
4181 * Only take left channel into account.
4182 * Mute is 0 and unmute 1
4183 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304184 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304185 } else if (out->format == AUDIO_FORMAT_DSD){
4186 char mixer_ctl_name[128] = "DSD Volume";
4187 struct audio_device *adev = out->dev;
4188 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4189
4190 if (!ctl) {
4191 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4192 __func__, mixer_ctl_name);
4193 return -EINVAL;
4194 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304195 volume[0] = (long)(AmpToDb(left));
4196 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304197 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4198 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004199 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304200 pthread_mutex_lock(&out->compr_mute_lock);
4201 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4202 if (!out->a2dp_compress_mute)
4203 ret = out_set_compr_volume(stream, left, right);
4204 out->volume_l = left;
4205 out->volume_r = right;
4206 pthread_mutex_unlock(&out->compr_mute_lock);
4207 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004208 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004209 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004210 if (!out->standby)
4211 ret = out_set_voip_volume(stream, left, right);
4212 out->volume_l = left;
4213 out->volume_r = right;
4214 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004215 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 return -ENOSYS;
4218}
4219
Zhou Songc9672822017-08-16 16:01:39 +08004220static void update_frames_written(struct stream_out *out, size_t bytes)
4221{
4222 size_t bpf = 0;
4223
4224 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4225 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4226 bpf = 1;
4227 else if (!is_offload_usecase(out->usecase))
4228 bpf = audio_bytes_per_sample(out->format) *
4229 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004230
4231 pthread_mutex_lock(&out->position_query_lock);
4232 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004233 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004234 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4235 }
4236 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004237}
4238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4240 size_t bytes)
4241{
4242 struct stream_out *out = (struct stream_out *)stream;
4243 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004244 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304245 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246
Haynes Mathew George380745d2017-10-04 15:27:45 -07004247 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004248 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304249
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304250 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004251
Dhananjay Kumarac341582017-02-23 23:42:25 +05304252 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304253 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304254 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4255 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004256 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304257 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304258 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304259 ALOGD(" %s: sound card is not active/SSR state", __func__);
4260 ret= -EIO;
4261 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304262 }
4263 }
4264
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304265 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304266 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304267 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304268 goto exit;
4269 }
4270
Haynes Mathew George16081042017-05-31 17:16:49 -07004271 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4272 ret = -EINVAL;
4273 goto exit;
4274 }
4275
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304276 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4277 !out->is_iec61937_info_available) {
4278
4279 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4280 out->is_iec61937_info_available = true;
4281 } else if (audio_extn_passthru_is_enabled()) {
4282 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304283 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304284
4285 if((out->format == AUDIO_FORMAT_DTS) ||
4286 (out->format == AUDIO_FORMAT_DTS_HD)) {
4287 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4288 buffer, bytes);
4289 if (ret) {
4290 if (ret != -ENOSYS) {
4291 out->is_iec61937_info_available = false;
4292 ALOGD("iec61937 transmission info not yet updated retry");
4293 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304294 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304295 /* if stream has started and after that there is
4296 * stream config change (iec transmission config)
4297 * then trigger select_device to update backend configuration.
4298 */
4299 out->stream_config_changed = true;
4300 pthread_mutex_lock(&adev->lock);
4301 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304302 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4303 ret = -EINVAL;
4304 goto exit;
4305 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304306 pthread_mutex_unlock(&adev->lock);
4307 out->stream_config_changed = false;
4308 out->is_iec61937_info_available = true;
4309 }
4310 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304311
Garmond Leung317cbf12017-09-13 16:20:50 -07004312 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304313 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4314 (out->is_iec61937_info_available == true)) {
4315 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4316 ret = -EINVAL;
4317 goto exit;
4318 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304319 }
4320 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304321
4322 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4323 (audio_extn_a2dp_is_suspended())) {
4324 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4325 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304326 ret = -EIO;
4327 goto exit;
4328 }
4329 }
4330 }
4331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004333 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004334 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004335 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4336 ret = voice_extn_compress_voip_start_output_stream(out);
4337 else
4338 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004339 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004340 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004342 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343 goto exit;
4344 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304345 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004346 if (last_known_cal_step != -1) {
4347 ALOGD("%s: retry previous failed cal level set", __func__);
4348 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304349 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004350 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304351
4352 if ((out->is_iec61937_info_available == true) &&
4353 (audio_extn_passthru_is_passthrough_stream(out))&&
4354 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4355 ret = -EINVAL;
4356 goto exit;
4357 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359
Ashish Jain81eb2a82015-05-13 10:52:34 +05304360 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004361 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304362 adev->is_channel_status_set = true;
4363 }
4364
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004365 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004366 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004367 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004368 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004369 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4370 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304371 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4372 ALOGD("copl(%p):send next track params in gapless", out);
4373 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4374 out->send_next_track_params = false;
4375 out->is_compr_metadata_avail = false;
4376 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004377 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304378 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304379 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004380
Ashish Jain83a6cc22016-06-28 14:34:17 +05304381 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304382 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304383 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304384 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004385 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05304386 return -EINVAL;
4387 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304388 audio_format_t dst_format = out->hal_op_format;
4389 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304390
4391 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4392 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4393
Ashish Jain83a6cc22016-06-28 14:34:17 +05304394 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304395 dst_format,
4396 buffer,
4397 src_format,
4398 frames);
4399
Ashish Jain83a6cc22016-06-28 14:34:17 +05304400 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304401 bytes_to_write);
4402
4403 /*Convert written bytes in audio flinger format*/
4404 if (ret > 0)
4405 ret = ((ret * format_to_bitwidth_table[out->format]) /
4406 format_to_bitwidth_table[dst_format]);
4407 }
4408 } else
4409 ret = compress_write(out->compr, buffer, bytes);
4410
Zhou Songc9672822017-08-16 16:01:39 +08004411 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4412 update_frames_written(out, bytes);
4413
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304414 if (ret < 0)
4415 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304416 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304417 /*msg to cb thread only if non blocking write is enabled*/
4418 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304419 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004420 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304421 } else if (-ENETRESET == ret) {
4422 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304423 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304424 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304425 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004426 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05304427 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004428 }
Ashish Jain5106d362016-05-11 19:23:33 +05304429
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304430 /* Call compr start only when non-zero bytes of data is there to be rendered */
4431 if (!out->playback_started && ret > 0) {
4432 int status = compress_start(out->compr);
4433 if (status < 0) {
4434 ret = status;
4435 ALOGE("%s: compr start failed with err %d", __func__, errno);
4436 goto exit;
4437 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004438 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004439 out->playback_started = 1;
4440 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004441
4442 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4443 popcount(out->channel_mask),
4444 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004445 }
4446 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004447 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004448 return ret;
4449 } else {
4450 if (out->pcm) {
4451 if (out->muted)
4452 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004453
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304454 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004455
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004456 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004457
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004458 if (out->config.rate)
4459 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4460 out->config.rate;
4461
4462 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4463
4464 request_out_focus(out, ns);
4465
4466 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004467 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004468 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304469 out->convert_buffer != NULL) {
4470
4471 memcpy_by_audio_format(out->convert_buffer,
4472 out->hal_op_format,
4473 buffer,
4474 out->hal_ip_format,
4475 out->config.period_size * out->config.channels);
4476
4477 ret = pcm_write(out->pcm, out->convert_buffer,
4478 (out->config.period_size *
4479 out->config.channels *
4480 format_to_bitwidth_table[out->hal_op_format]));
4481 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304482 /*
4483 * To avoid underrun in DSP when the application is not pumping
4484 * data at required rate, check for the no. of bytes and ignore
4485 * pcm_write if it is less than actual buffer size.
4486 * It is a work around to a change in compress VOIP driver.
4487 */
4488 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4489 bytes < (out->config.period_size * out->config.channels *
4490 audio_bytes_per_sample(out->format))) {
4491 size_t voip_buf_size =
4492 out->config.period_size * out->config.channels *
4493 audio_bytes_per_sample(out->format);
4494 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4495 __func__, bytes, voip_buf_size);
4496 usleep(((uint64_t)voip_buf_size - bytes) *
4497 1000000 / audio_stream_out_frame_size(stream) /
4498 out_get_sample_rate(&out->stream.common));
4499 ret = 0;
4500 } else
4501 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304502 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004503
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004504 release_out_focus(out);
4505
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304506 if (ret < 0)
4507 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004508 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304509 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511 }
4512
4513exit:
Zhou Songc9672822017-08-16 16:01:39 +08004514 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304515 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304516 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518 pthread_mutex_unlock(&out->lock);
4519
4520 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004521 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004522 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304523 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304524 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304525 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304526 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304527 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304528 out->standby = true;
4529 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304530 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304531 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4532 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4533 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004534
4535 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05304536 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004537 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004538 return ret;
4539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004541 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 return bytes;
4543}
4544
4545static int out_get_render_position(const struct audio_stream_out *stream,
4546 uint32_t *dsp_frames)
4547{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004548 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004549
4550 if (dsp_frames == NULL)
4551 return -EINVAL;
4552
4553 *dsp_frames = 0;
4554 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004555 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304556
4557 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4558 * this operation and adev_close_output_stream(where out gets reset).
4559 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304560 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004561 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05304562 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004563 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304564 return 0;
4565 }
4566
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004567 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304568 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304569 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004570 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304571 if (ret < 0)
4572 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004573 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304574 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004575 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304576 if (-ENETRESET == ret) {
4577 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304578 out->card_status = CARD_STATUS_OFFLINE;
4579 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304580 } else if(ret < 0) {
4581 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304582 ret = -EINVAL;
4583 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304584 /*
4585 * Handle corner case where compress session is closed during SSR
4586 * and timestamp is queried
4587 */
4588 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304589 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304590 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304591 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004592 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05304593 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304594 pthread_mutex_unlock(&out->lock);
4595 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004596 } else if (audio_is_linear_pcm(out->format)) {
4597 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07004598 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08004599 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004600 } else
4601 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602}
4603
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004604static int out_add_audio_effect(const struct audio_stream *stream __unused,
4605 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606{
4607 return 0;
4608}
4609
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004610static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4611 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612{
4613 return 0;
4614}
4615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004616static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4617 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304619 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620}
4621
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004622static int out_get_presentation_position(const struct audio_stream_out *stream,
4623 uint64_t *frames, struct timespec *timestamp)
4624{
4625 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05304626 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07004627 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004628
Ashish Jain5106d362016-05-11 19:23:33 +05304629 /* below piece of code is not guarded against any lock because audioFliner serializes
4630 * this operation and adev_close_output_stream( where out gets reset).
4631 */
4632 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304633 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08004634 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05304635 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4636 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4637 return 0;
4638 }
4639
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004640 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004641
Ashish Jain5106d362016-05-11 19:23:33 +05304642 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4643 ret = compress_get_tstamp(out->compr, &dsp_frames,
4644 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004645 // Adjustment accounts for A2dp encoder latency with offload usecases
4646 // Note: Encoder latency is returned in ms.
4647 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4648 unsigned long offset =
4649 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4650 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4651 }
Ashish Jain5106d362016-05-11 19:23:33 +05304652 ALOGVV("%s rendered frames %ld sample_rate %d",
4653 __func__, dsp_frames, out->sample_rate);
4654 *frames = dsp_frames;
4655 if (ret < 0)
4656 ret = -errno;
4657 if (-ENETRESET == ret) {
4658 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304659 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304660 ret = -EINVAL;
4661 } else
4662 ret = 0;
4663 /* this is the best we can do */
4664 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004665 } else {
4666 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08004667 unsigned int avail;
4668 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4669 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
4670 int64_t signed_frames = out->written - kernel_buffer_size + avail;
4671 // This adjustment accounts for buffering after app processor.
4672 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004673 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08004674 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004675
Weiyin Jiangd4633762018-03-16 12:05:03 +08004676 // Adjustment accounts for A2dp encoder latency with non offload usecases
4677 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4678 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4679 signed_frames -=
4680 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4681 }
4682
4683 // It would be unusual for this value to be negative, but check just in case ...
4684 if (signed_frames >= 0) {
4685 *frames = signed_frames;
4686 ret = 0;
4687 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004688 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304689 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304690 *frames = out->written;
4691 clock_gettime(CLOCK_MONOTONIC, timestamp);
4692 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004693 }
4694 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004695 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004696 return ret;
4697}
4698
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004699static int out_set_callback(struct audio_stream_out *stream,
4700 stream_callback_t callback, void *cookie)
4701{
4702 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004703 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004704
4705 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004706 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004707 out->client_callback = callback;
4708 out->client_cookie = cookie;
4709 if (out->adsp_hdlr_stream_handle) {
4710 ret = audio_extn_adsp_hdlr_stream_set_callback(
4711 out->adsp_hdlr_stream_handle,
4712 callback,
4713 cookie);
4714 if (ret)
4715 ALOGW("%s:adsp hdlr callback registration failed %d",
4716 __func__, ret);
4717 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004718 pthread_mutex_unlock(&out->lock);
4719 return 0;
4720}
4721
4722static int out_pause(struct audio_stream_out* stream)
4723{
4724 struct stream_out *out = (struct stream_out *)stream;
4725 int status = -ENOSYS;
4726 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004727 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004728 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004729 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004730 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304731 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304732 status = compress_pause(out->compr);
4733
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004734 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004735
Mingming Yin21854652016-04-13 11:54:02 -07004736 if (audio_extn_passthru_is_active()) {
4737 ALOGV("offload use case, pause passthru");
4738 audio_extn_passthru_on_pause(out);
4739 }
4740
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304741 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004742 audio_extn_dts_notify_playback_state(out->usecase, 0,
4743 out->sample_rate, popcount(out->channel_mask),
4744 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004745 }
4746 pthread_mutex_unlock(&out->lock);
4747 }
4748 return status;
4749}
4750
4751static int out_resume(struct audio_stream_out* stream)
4752{
4753 struct stream_out *out = (struct stream_out *)stream;
4754 int status = -ENOSYS;
4755 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004756 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004757 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004758 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004759 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004760 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304761 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304762 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004763 }
4764 if (!status) {
4765 out->offload_state = OFFLOAD_STATE_PLAYING;
4766 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304767 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004768 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4769 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004770 }
4771 pthread_mutex_unlock(&out->lock);
4772 }
4773 return status;
4774}
4775
4776static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4777{
4778 struct stream_out *out = (struct stream_out *)stream;
4779 int status = -ENOSYS;
4780 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004781 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004782 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004783 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4784 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4785 else
4786 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4787 pthread_mutex_unlock(&out->lock);
4788 }
4789 return status;
4790}
4791
4792static int out_flush(struct audio_stream_out* stream)
4793{
4794 struct stream_out *out = (struct stream_out *)stream;
4795 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004796 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004797 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004798 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004799 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4800 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004801 } else {
4802 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4803 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004804 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004805 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004806 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004807 return 0;
4808 }
4809 return -ENOSYS;
4810}
4811
Haynes Mathew George16081042017-05-31 17:16:49 -07004812static int out_stop(const struct audio_stream_out* stream)
4813{
4814 struct stream_out *out = (struct stream_out *)stream;
4815 struct audio_device *adev = out->dev;
4816 int ret = -ENOSYS;
4817
4818 ALOGV("%s", __func__);
4819 pthread_mutex_lock(&adev->lock);
4820 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4821 out->playback_started && out->pcm != NULL) {
4822 pcm_stop(out->pcm);
4823 ret = stop_output_stream(out);
4824 out->playback_started = false;
4825 }
4826 pthread_mutex_unlock(&adev->lock);
4827 return ret;
4828}
4829
4830static int out_start(const struct audio_stream_out* stream)
4831{
4832 struct stream_out *out = (struct stream_out *)stream;
4833 struct audio_device *adev = out->dev;
4834 int ret = -ENOSYS;
4835
4836 ALOGV("%s", __func__);
4837 pthread_mutex_lock(&adev->lock);
4838 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4839 !out->playback_started && out->pcm != NULL) {
4840 ret = start_output_stream(out);
4841 if (ret == 0) {
4842 out->playback_started = true;
4843 }
4844 }
4845 pthread_mutex_unlock(&adev->lock);
4846 return ret;
4847}
4848
4849/*
4850 * Modify config->period_count based on min_size_frames
4851 */
4852static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4853{
4854 int periodCountRequested = (min_size_frames + config->period_size - 1)
4855 / config->period_size;
4856 int periodCount = MMAP_PERIOD_COUNT_MIN;
4857
4858 ALOGV("%s original config.period_size = %d config.period_count = %d",
4859 __func__, config->period_size, config->period_count);
4860
4861 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4862 periodCount *= 2;
4863 }
4864 config->period_count = periodCount;
4865
4866 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4867}
4868
4869static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4870 int32_t min_size_frames,
4871 struct audio_mmap_buffer_info *info)
4872{
4873 struct stream_out *out = (struct stream_out *)stream;
4874 struct audio_device *adev = out->dev;
4875 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07004876 unsigned int offset1 = 0;
4877 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07004878 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004879 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004880
4881 ALOGV("%s", __func__);
4882 pthread_mutex_lock(&adev->lock);
4883
4884 if (info == NULL || min_size_frames == 0) {
4885 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4886 ret = -EINVAL;
4887 goto exit;
4888 }
4889 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4890 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4891 ret = -ENOSYS;
4892 goto exit;
4893 }
4894 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4895 if (out->pcm_device_id < 0) {
4896 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4897 __func__, out->pcm_device_id, out->usecase);
4898 ret = -EINVAL;
4899 goto exit;
4900 }
4901
4902 adjust_mmap_period_count(&out->config, min_size_frames);
4903
4904 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4905 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4906 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4907 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4908 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4909 step = "open";
4910 ret = -ENODEV;
4911 goto exit;
4912 }
4913 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4914 if (ret < 0) {
4915 step = "begin";
4916 goto exit;
4917 }
4918 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4919 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004920 ret = platform_get_mmap_data_fd(adev->platform,
4921 out->pcm_device_id, 0 /*playback*/,
4922 &info->shared_memory_fd,
4923 &mmap_size);
4924 if (ret < 0) {
4925 step = "get_mmap_fd";
4926 goto exit;
4927 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004928 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004929 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004930
4931 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4932 if (ret < 0) {
4933 step = "commit";
4934 goto exit;
4935 }
4936
4937 out->standby = false;
4938 ret = 0;
4939
4940 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4941 __func__, info->shared_memory_address, info->buffer_size_frames);
4942
4943exit:
4944 if (ret != 0) {
4945 if (out->pcm == NULL) {
4946 ALOGE("%s: %s - %d", __func__, step, ret);
4947 } else {
4948 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4949 pcm_close(out->pcm);
4950 out->pcm = NULL;
4951 }
4952 }
4953 pthread_mutex_unlock(&adev->lock);
4954 return ret;
4955}
4956
4957static int out_get_mmap_position(const struct audio_stream_out *stream,
4958 struct audio_mmap_position *position)
4959{
4960 struct stream_out *out = (struct stream_out *)stream;
4961 ALOGVV("%s", __func__);
4962 if (position == NULL) {
4963 return -EINVAL;
4964 }
4965 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004966 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004967 return -ENOSYS;
4968 }
4969 if (out->pcm == NULL) {
4970 return -ENOSYS;
4971 }
4972
4973 struct timespec ts = { 0, 0 };
4974 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4975 if (ret < 0) {
4976 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4977 return ret;
4978 }
4979 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4980 return 0;
4981}
4982
4983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984/** audio_stream_in implementation **/
4985static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4986{
4987 struct stream_in *in = (struct stream_in *)stream;
4988
4989 return in->config.rate;
4990}
4991
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004992static int in_set_sample_rate(struct audio_stream *stream __unused,
4993 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994{
4995 return -ENOSYS;
4996}
4997
4998static size_t in_get_buffer_size(const struct audio_stream *stream)
4999{
5000 struct stream_in *in = (struct stream_in *)stream;
5001
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005002 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5003 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005004 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5005 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 -07005006 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5007 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305008 else if(audio_extn_cin_attached_usecase(in->usecase))
5009 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005010
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005011 return in->config.period_size * in->af_period_multiplier *
5012 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013}
5014
5015static uint32_t in_get_channels(const struct audio_stream *stream)
5016{
5017 struct stream_in *in = (struct stream_in *)stream;
5018
5019 return in->channel_mask;
5020}
5021
5022static audio_format_t in_get_format(const struct audio_stream *stream)
5023{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005024 struct stream_in *in = (struct stream_in *)stream;
5025
5026 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027}
5028
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005029static int in_set_format(struct audio_stream *stream __unused,
5030 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031{
5032 return -ENOSYS;
5033}
5034
5035static int in_standby(struct audio_stream *stream)
5036{
5037 struct stream_in *in = (struct stream_in *)stream;
5038 struct audio_device *adev = in->dev;
5039 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305040 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5041 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005042 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305043
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005044 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005045 if (!in->standby && in->is_st_session) {
5046 ALOGD("%s: sound trigger pcm stop lab", __func__);
5047 audio_extn_sound_trigger_stop_lab(in);
5048 in->standby = 1;
5049 }
5050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005051 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005052 if (adev->adm_deregister_stream)
5053 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5054
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005055 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005056 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005057 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005058 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005059 voice_extn_compress_voip_close_input_stream(stream);
5060 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005061 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5062 do_stop = in->capture_started;
5063 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005064 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305065 if (audio_extn_cin_attached_usecase(in->usecase))
5066 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005067 }
5068
5069 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08005070 if (in->pcm) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07005071 ATRACE_BEGIN("pcm_in_close");
Zhou Songa8895042016-07-05 17:54:22 +08005072 pcm_close(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005073 ATRACE_END();
Zhou Songa8895042016-07-05 17:54:22 +08005074 in->pcm = NULL;
5075 }
5076 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005077 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08005078 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005079 }
5080 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005081 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082 return status;
5083}
5084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005085static int in_dump(const struct audio_stream *stream __unused,
5086 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087{
5088 return 0;
5089}
5090
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305091static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5092{
5093 if (!stream || !parms)
5094 return;
5095
5096 struct stream_in *in = (struct stream_in *)stream;
5097 struct audio_device *adev = in->dev;
5098
5099 card_status_t status;
5100 int card;
5101 if (parse_snd_card_status(parms, &card, &status) < 0)
5102 return;
5103
5104 pthread_mutex_lock(&adev->lock);
5105 bool valid_cb = (card == adev->snd_card);
5106 pthread_mutex_unlock(&adev->lock);
5107
5108 if (!valid_cb)
5109 return;
5110
5111 lock_input_stream(in);
5112 if (in->card_status != status)
5113 in->card_status = status;
5114 pthread_mutex_unlock(&in->lock);
5115
5116 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5117 use_case_table[in->usecase],
5118 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5119
5120 // a better solution would be to report error back to AF and let
5121 // it put the stream to standby
5122 if (status == CARD_STATUS_OFFLINE)
5123 in_standby(&in->stream.common);
5124
5125 return;
5126}
5127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005128static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5129{
5130 struct stream_in *in = (struct stream_in *)stream;
5131 struct audio_device *adev = in->dev;
5132 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005133 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005134 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305136 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 parms = str_parms_create_str(kvpairs);
5138
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305139 if (!parms)
5140 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005141 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005142 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005143
5144 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5145 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005146 val = atoi(value);
5147 /* no audio source uses val == 0 */
5148 if ((in->source != val) && (val != 0)) {
5149 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005150 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5151 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5152 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005153 (in->config.rate == 8000 || in->config.rate == 16000 ||
5154 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005155 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005156 err = voice_extn_compress_voip_open_input_stream(in);
5157 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005158 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005159 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005160 }
5161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 }
5163 }
5164
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005165 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5166 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005167 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07005168 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
5169
5170 // Workaround: If routing to an non existing usb device, fail gracefully
5171 // The routing request will otherwise block during 10 second
5172 int card;
5173 if (audio_is_usb_in_device(val) &&
5174 (card = get_alive_usb_card(parms)) >= 0) {
5175
5176 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
5177 ret = -ENOSYS;
5178 } else {
5179
5180 in->device = val;
5181 /* If recording is in progress, change the tx device to new device */
5182 if (!in->standby && !in->is_st_session) {
5183 ALOGV("update input routing change");
5184 // inform adm before actual routing to prevent glitches.
5185 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07005186 adev->adm_on_routing_change(adev->adm_data,
5187 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07005188 ret = select_devices(adev, in->usecase);
5189 }
5190 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 }
5193 }
5194
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305195 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5196 if (err >= 0) {
5197 strlcpy(in->profile, value, sizeof(in->profile));
5198 ALOGV("updating stream profile with value '%s'", in->profile);
5199 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5200 &adev->streams_input_cfg_list,
5201 in->device, in->flags, in->format,
5202 in->sample_rate, in->bit_width,
5203 in->profile, &in->app_type_cfg);
5204 }
5205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005206 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005207 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005208
5209 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305210error:
Eric Laurent994a6932013-07-17 11:51:42 -07005211 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 return ret;
5213}
5214
5215static char* in_get_parameters(const struct audio_stream *stream,
5216 const char *keys)
5217{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005218 struct stream_in *in = (struct stream_in *)stream;
5219 struct str_parms *query = str_parms_create_str(keys);
5220 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005221 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005222
5223 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005224 if (reply) {
5225 str_parms_destroy(reply);
5226 }
5227 if (query) {
5228 str_parms_destroy(query);
5229 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005230 ALOGE("in_get_parameters: failed to create query or reply");
5231 return NULL;
5232 }
5233
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005234 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005235
5236 voice_extn_in_get_parameters(in, query, reply);
5237
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005238 stream_get_parameter_channels(query, reply,
5239 &in->supported_channel_masks[0]);
5240 stream_get_parameter_formats(query, reply,
5241 &in->supported_formats[0]);
5242 stream_get_parameter_rates(query, reply,
5243 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005244 str = str_parms_to_str(reply);
5245 str_parms_destroy(query);
5246 str_parms_destroy(reply);
5247
5248 ALOGV("%s: exit: returns - %s", __func__, str);
5249 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250}
5251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005252static int in_set_gain(struct audio_stream_in *stream __unused,
5253 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254{
5255 return 0;
5256}
5257
5258static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5259 size_t bytes)
5260{
5261 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05305262
5263 if (in == NULL) {
5264 ALOGE("%s: stream_in ptr is NULL", __func__);
5265 return -EINVAL;
5266 }
5267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305269 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305270 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005272 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305273
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005274 if (in->is_st_session) {
5275 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5276 /* Read from sound trigger HAL */
5277 audio_extn_sound_trigger_read(in, buffer, bytes);
5278 pthread_mutex_unlock(&in->lock);
5279 return bytes;
5280 }
5281
Haynes Mathew George16081042017-05-31 17:16:49 -07005282 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5283 ret = -ENOSYS;
5284 goto exit;
5285 }
5286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005287 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005288 pthread_mutex_lock(&adev->lock);
5289 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5290 ret = voice_extn_compress_voip_start_input_stream(in);
5291 else
5292 ret = start_input_stream(in);
5293 pthread_mutex_unlock(&adev->lock);
5294 if (ret != 0) {
5295 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296 }
5297 in->standby = 0;
5298 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005300 // what's the duration requested by the client?
5301 long ns = 0;
5302
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305303 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005304 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5305 in->config.rate;
5306
5307 request_in_focus(in, ns);
5308 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005309
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305310 if (audio_extn_cin_attached_usecase(in->usecase)) {
5311 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5312 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305313 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005314 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305315 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005316 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005317 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005318 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005319 } else if (audio_extn_ffv_get_stream() == in) {
5320 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305321 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005322 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305323 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5324 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5325 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5326 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305327 ret = -EINVAL;
5328 goto exit;
5329 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305330 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305331 ret = -errno;
5332 }
5333 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305334 /* bytes read is always set to bytes for non compress usecases */
5335 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005336 }
5337
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005338 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340 /*
5341 * Instead of writing zeroes here, we could trust the hardware
5342 * to always provide zeroes when muted.
5343 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305344 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5345 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346 memset(buffer, 0, bytes);
5347
5348exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005349 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305350 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351 pthread_mutex_unlock(&in->lock);
5352
5353 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305354 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305355 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305356 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305357 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305358 in->standby = true;
5359 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305360 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5361 bytes_read = bytes;
5362 memset(buffer, 0, bytes);
5363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005364 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005365 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305366 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305367 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005368 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305369 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005370}
5371
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005372static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373{
5374 return 0;
5375}
5376
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005377static int add_remove_audio_effect(const struct audio_stream *stream,
5378 effect_handle_t effect,
5379 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005380{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005381 struct stream_in *in = (struct stream_in *)stream;
5382 int status = 0;
5383 effect_descriptor_t desc;
5384
5385 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005386 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5387
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005388 if (status != 0)
5389 return status;
5390
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005391 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005392 pthread_mutex_lock(&in->dev->lock);
5393 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5394 in->enable_aec != enable &&
5395 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5396 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005397 if (!in->standby) {
5398 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5399 select_devices(in->dev, in->usecase);
5400 }
5401
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005402 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005403 if (in->enable_ns != enable &&
5404 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5405 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005406 if (!in->standby) {
5407 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
5408 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5409 select_devices(in->dev, in->usecase);
5410 } else
5411 select_devices(in->dev, in->usecase);
5412 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005413 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005414 pthread_mutex_unlock(&in->dev->lock);
5415 pthread_mutex_unlock(&in->lock);
5416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005417 return 0;
5418}
5419
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005420static int in_add_audio_effect(const struct audio_stream *stream,
5421 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422{
Eric Laurent994a6932013-07-17 11:51:42 -07005423 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005424 return add_remove_audio_effect(stream, effect, true);
5425}
5426
5427static int in_remove_audio_effect(const struct audio_stream *stream,
5428 effect_handle_t effect)
5429{
Eric Laurent994a6932013-07-17 11:51:42 -07005430 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005431 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432}
5433
Haynes Mathew George16081042017-05-31 17:16:49 -07005434static int in_stop(const struct audio_stream_in* stream)
5435{
5436 struct stream_in *in = (struct stream_in *)stream;
5437 struct audio_device *adev = in->dev;
5438
5439 int ret = -ENOSYS;
5440 ALOGV("%s", __func__);
5441 pthread_mutex_lock(&adev->lock);
5442 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5443 in->capture_started && in->pcm != NULL) {
5444 pcm_stop(in->pcm);
5445 ret = stop_input_stream(in);
5446 in->capture_started = false;
5447 }
5448 pthread_mutex_unlock(&adev->lock);
5449 return ret;
5450}
5451
5452static int in_start(const struct audio_stream_in* stream)
5453{
5454 struct stream_in *in = (struct stream_in *)stream;
5455 struct audio_device *adev = in->dev;
5456 int ret = -ENOSYS;
5457
5458 ALOGV("%s in %p", __func__, in);
5459 pthread_mutex_lock(&adev->lock);
5460 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5461 !in->capture_started && in->pcm != NULL) {
5462 if (!in->capture_started) {
5463 ret = start_input_stream(in);
5464 if (ret == 0) {
5465 in->capture_started = true;
5466 }
5467 }
5468 }
5469 pthread_mutex_unlock(&adev->lock);
5470 return ret;
5471}
5472
5473static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5474 int32_t min_size_frames,
5475 struct audio_mmap_buffer_info *info)
5476{
5477 struct stream_in *in = (struct stream_in *)stream;
5478 struct audio_device *adev = in->dev;
5479 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005480 unsigned int offset1 = 0;
5481 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005482 const char *step = "";
5483
5484 pthread_mutex_lock(&adev->lock);
5485 ALOGV("%s in %p", __func__, in);
5486
5487 if (info == NULL || min_size_frames == 0) {
5488 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5489 ret = -EINVAL;
5490 goto exit;
5491 }
5492 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5493 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5494 ALOGV("%s in %p", __func__, in);
5495 ret = -ENOSYS;
5496 goto exit;
5497 }
5498 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5499 if (in->pcm_device_id < 0) {
5500 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5501 __func__, in->pcm_device_id, in->usecase);
5502 ret = -EINVAL;
5503 goto exit;
5504 }
5505
5506 adjust_mmap_period_count(&in->config, min_size_frames);
5507
5508 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5509 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5510 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5511 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5512 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5513 step = "open";
5514 ret = -ENODEV;
5515 goto exit;
5516 }
5517
5518 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5519 if (ret < 0) {
5520 step = "begin";
5521 goto exit;
5522 }
5523 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5524 info->burst_size_frames = in->config.period_size;
5525 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5526
5527 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5528 info->buffer_size_frames));
5529
5530 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5531 if (ret < 0) {
5532 step = "commit";
5533 goto exit;
5534 }
5535
5536 in->standby = false;
5537 ret = 0;
5538
5539 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5540 __func__, info->shared_memory_address, info->buffer_size_frames);
5541
5542exit:
5543 if (ret != 0) {
5544 if (in->pcm == NULL) {
5545 ALOGE("%s: %s - %d", __func__, step, ret);
5546 } else {
5547 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5548 pcm_close(in->pcm);
5549 in->pcm = NULL;
5550 }
5551 }
5552 pthread_mutex_unlock(&adev->lock);
5553 return ret;
5554}
5555
5556static int in_get_mmap_position(const struct audio_stream_in *stream,
5557 struct audio_mmap_position *position)
5558{
5559 struct stream_in *in = (struct stream_in *)stream;
5560 ALOGVV("%s", __func__);
5561 if (position == NULL) {
5562 return -EINVAL;
5563 }
5564 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5565 return -ENOSYS;
5566 }
5567 if (in->pcm == NULL) {
5568 return -ENOSYS;
5569 }
5570 struct timespec ts = { 0, 0 };
5571 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5572 if (ret < 0) {
5573 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5574 return ret;
5575 }
5576 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5577 return 0;
5578}
5579
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305580int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005581 audio_io_handle_t handle,
5582 audio_devices_t devices,
5583 audio_output_flags_t flags,
5584 struct audio_config *config,
5585 struct audio_stream_out **stream_out,
5586 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005587{
5588 struct audio_device *adev = (struct audio_device *)dev;
5589 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305590 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005591 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005592 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305593 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005594 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5595 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5596 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5597 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005599 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5602
Mingming Yin3a941d42016-02-17 18:08:05 -08005603 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5604 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305605 devices, flags, &out->stream);
5606
5607
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005608 if (!out) {
5609 return -ENOMEM;
5610 }
5611
Haynes Mathew George204045b2015-02-25 20:32:03 -08005612 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005613 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305614 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08005615 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005616 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005618 if (devices == AUDIO_DEVICE_NONE)
5619 devices = AUDIO_DEVICE_OUT_SPEAKER;
5620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005621 out->flags = flags;
5622 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005623 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005624 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005625 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305626 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305627 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5628 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5629 else
5630 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005631 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005632 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005633 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305634 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305635 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305636 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005637 out->hal_output_suspend_supported = 0;
5638 out->dynamic_pm_qos_config_supported = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005639
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305640 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05305641 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07005642 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5643
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005644 if (audio_is_linear_pcm(out->format) &&
5645 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5646 pthread_mutex_lock(&adev->lock);
5647 if (is_hdmi) {
5648 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5649 ret = read_hdmi_sink_caps(out);
5650 } else if (is_usb_dev) {
5651 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5652 &config->format,
5653 &out->supported_formats[0],
5654 MAX_SUPPORTED_FORMATS,
5655 &config->channel_mask,
5656 &out->supported_channel_masks[0],
5657 MAX_SUPPORTED_CHANNEL_MASKS,
5658 &config->sample_rate,
5659 &out->supported_sample_rates[0],
5660 MAX_SUPPORTED_SAMPLE_RATES);
5661 ALOGV("plugged dev USB ret %d", ret);
5662 } else {
5663 ret = -1;
5664 }
5665 pthread_mutex_unlock(&adev->lock);
5666 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005667 if (ret == -ENOSYS) {
5668 /* ignore and go with default */
5669 ret = 0;
5670 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005671 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005672 goto error_open;
5673 }
5674 }
5675 }
5676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005677 /* Init use case and pcm_config */
Vikram Pandurangafa3128d2017-10-16 16:57:22 -07005678#ifndef COMPRESS_VOIP_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005679 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5680 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5681 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5682 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5683 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5684 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5685
5686 out->config = default_pcm_config_voip_copp;
5687 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5688 out->config.rate = out->sample_rate;
5689
5690#else
Preetam Singh Ranawat319b1cd2017-10-12 10:46:30 +05305691 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005692 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005693 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005694 ret = voice_extn_compress_voip_open_output_stream(out);
5695 if (ret != 0) {
5696 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5697 __func__, ret);
5698 goto error_open;
5699 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005700#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005701 } else if (audio_is_linear_pcm(out->format) &&
5702 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5703 out->channel_mask = config->channel_mask;
5704 out->sample_rate = config->sample_rate;
5705 out->format = config->format;
5706 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5707 // does this change?
5708 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5709 out->config.rate = config->sample_rate;
5710 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5711 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5712 audio_bytes_per_sample(config->format));
5713 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005714 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305715 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305716 pthread_mutex_lock(&adev->lock);
5717 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5718 pthread_mutex_unlock(&adev->lock);
5719
5720 // reject offload during card offline to allow
5721 // fallback to s/w paths
5722 if (offline) {
5723 ret = -ENODEV;
5724 goto error_open;
5725 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005726
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005727 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5728 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5729 ALOGE("%s: Unsupported Offload information", __func__);
5730 ret = -EINVAL;
5731 goto error_open;
5732 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005733
Atul Khare3fa6e542017-08-09 00:56:17 +05305734 if (config->offload_info.format == 0)
5735 config->offload_info.format = config->format;
5736 if (config->offload_info.sample_rate == 0)
5737 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005738
Mingming Yin90310102013-11-13 16:57:00 -08005739 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305740 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005741 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005742 ret = -EINVAL;
5743 goto error_open;
5744 }
5745
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005746 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5747 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5748 (audio_extn_passthru_is_passthrough_stream(out)) &&
5749 !((config->sample_rate == 48000) ||
5750 (config->sample_rate == 96000) ||
5751 (config->sample_rate == 192000))) {
5752 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5753 __func__, config->sample_rate, config->offload_info.format);
5754 ret = -EINVAL;
5755 goto error_open;
5756 }
5757
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005758 out->compr_config.codec = (struct snd_codec *)
5759 calloc(1, sizeof(struct snd_codec));
5760
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005761 if (!out->compr_config.codec) {
5762 ret = -ENOMEM;
5763 goto error_open;
5764 }
5765
Dhananjay Kumarac341582017-02-23 23:42:25 +05305766 out->stream.pause = out_pause;
5767 out->stream.resume = out_resume;
5768 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305769 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305770 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005771 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305772 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005773 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305774 } else {
5775 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5776 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005777 }
vivek mehta446c3962015-09-14 10:57:35 -07005778
5779 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005780 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5781 config->format == 0 && config->sample_rate == 0 &&
5782 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005783 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005784 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5785 } else {
5786 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5787 ret = -EEXIST;
5788 goto error_open;
5789 }
vivek mehta446c3962015-09-14 10:57:35 -07005790 }
5791
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005792 if (config->offload_info.channel_mask)
5793 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005794 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005795 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005796 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005797 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305798 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005799 ret = -EINVAL;
5800 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005801 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005802
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005803 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005804 out->sample_rate = config->offload_info.sample_rate;
5805
Mingming Yin3ee55c62014-08-04 14:23:35 -07005806 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005807
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305808 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305809 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305810 audio_extn_dolby_send_ddp_endp_params(adev);
5811 audio_extn_dolby_set_dmid(adev);
5812 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005814 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005815 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005816 out->compr_config.codec->bit_rate =
5817 config->offload_info.bit_rate;
5818 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305819 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005820 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305821 /* Update bit width only for non passthrough usecases.
5822 * For passthrough usecases, the output will always be opened @16 bit
5823 */
5824 if (!audio_extn_passthru_is_passthrough_stream(out))
5825 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305826
5827 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5828 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5829 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5830
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005831 /*TODO: Do we need to change it for passthrough */
5832 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005833
Manish Dewangana6fc5442015-08-24 20:30:31 +05305834 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5835 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305836 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305837 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305838 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5839 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305840
5841 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5842 AUDIO_FORMAT_PCM) {
5843
5844 /*Based on platform support, configure appropriate alsa format for corresponding
5845 *hal input format.
5846 */
5847 out->compr_config.codec->format = hal_format_to_alsa(
5848 config->offload_info.format);
5849
Ashish Jain83a6cc22016-06-28 14:34:17 +05305850 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305851 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305852 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305853
Dhananjay Kumarac341582017-02-23 23:42:25 +05305854 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305855 *hal input format and alsa format might differ based on platform support.
5856 */
5857 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305858 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305859
5860 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5861
5862 /* Check if alsa session is configured with the same format as HAL input format,
5863 * if not then derive correct fragment size needed to accomodate the
5864 * conversion of HAL input format to alsa format.
5865 */
5866 audio_extn_utils_update_direct_pcm_fragment_size(out);
5867
5868 /*if hal input and output fragment size is different this indicates HAL input format is
5869 *not same as the alsa format
5870 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305871 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305872 /*Allocate a buffer to convert input data to the alsa configured format.
5873 *size of convert buffer is equal to the size required to hold one fragment size
5874 *worth of pcm data, this is because flinger does not write more than fragment_size
5875 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305876 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5877 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305878 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5879 ret = -ENOMEM;
5880 goto error_open;
5881 }
5882 }
5883 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5884 out->compr_config.fragment_size =
5885 audio_extn_passthru_get_buffer_size(&config->offload_info);
5886 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5887 } else {
5888 out->compr_config.fragment_size =
5889 platform_get_compress_offload_buffer_size(&config->offload_info);
5890 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5891 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005892
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305893 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5894 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5895 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005896 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305897 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005898
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305899 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5900 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5901 }
5902
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005903 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5904 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005905
Manish Dewangan69426c82017-01-30 17:35:36 +05305906 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5907 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5908 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5909 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5910 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5911 } else {
5912 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5913 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005914
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305915 memset(&out->channel_map_param, 0,
5916 sizeof(struct audio_out_channel_map_param));
5917
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005918 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305919 out->send_next_track_params = false;
5920 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005921 out->offload_state = OFFLOAD_STATE_IDLE;
5922 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08005923 out->writeAt.tv_sec = 0;
5924 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005925
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005926 audio_extn_dts_create_state_notifier_node(out->usecase);
5927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005928 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5929 __func__, config->offload_info.version,
5930 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305931
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305932 /* Check if DSD audio format is supported in codec
5933 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305934 */
5935
5936 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305937 (!platform_check_codec_dsd_support(adev->platform) ||
5938 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305939 ret = -EINVAL;
5940 goto error_open;
5941 }
5942
Ashish Jain5106d362016-05-11 19:23:33 +05305943 /* Disable gapless if any of the following is true
5944 * passthrough playback
5945 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305946 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305947 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305948 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305949 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005950 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305951 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305952 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305953 check_and_set_gapless_mode(adev, false);
5954 } else
5955 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005956
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305957 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005958 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5959 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305960 if (config->format == AUDIO_FORMAT_DSD) {
5961 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5962 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5963 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005964
5965 create_offload_callback_thread(out);
5966
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005967 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305968 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005969 if (ret != 0) {
5970 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5971 __func__, ret);
5972 goto error_open;
5973 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005974 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5975 if (config->sample_rate == 0)
5976 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5977 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5978 config->sample_rate != 8000) {
5979 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5980 ret = -EINVAL;
5981 goto error_open;
5982 }
5983 out->sample_rate = config->sample_rate;
5984 out->config.rate = config->sample_rate;
5985 if (config->format == AUDIO_FORMAT_DEFAULT)
5986 config->format = AUDIO_FORMAT_PCM_16_BIT;
5987 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5988 config->format = AUDIO_FORMAT_PCM_16_BIT;
5989 ret = -EINVAL;
5990 goto error_open;
5991 }
5992 out->format = config->format;
5993 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5994 out->config = pcm_config_afe_proxy_playback;
5995 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005996 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305997 unsigned int channels = 0;
5998 /*Update config params to default if not set by the caller*/
5999 if (config->sample_rate == 0)
6000 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6001 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6002 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
6003 if (config->format == AUDIO_FORMAT_DEFAULT)
6004 config->format = AUDIO_FORMAT_PCM_16_BIT;
6005
6006 channels = audio_channel_count_from_out_mask(out->channel_mask);
6007
Varun Balaraje49253e2017-07-06 19:48:56 +05306008 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
6009 out->usecase = get_interactive_usecase(adev);
6010 out->config = pcm_config_low_latency;
6011 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306012 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006013 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
6014 out->flags);
6015 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07006016 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6017 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6018 out->config = pcm_config_mmap_playback;
6019 out->stream.start = out_start;
6020 out->stream.stop = out_stop;
6021 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6022 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306023 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
6024 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006025 out->hal_output_suspend_supported =
6026 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
6027 out->dynamic_pm_qos_config_supported =
6028 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
6029 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08006030 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
6031 } else {
6032 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
6033 //the mixer path will be a string similar to "low-latency-playback resume"
6034 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
6035 strlcat(out->pm_qos_mixer_path,
6036 " resume", MAX_MIXER_PATH_LEN);
6037 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
6038 out->pm_qos_mixer_path);
6039 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306040 out->config = pcm_config_low_latency;
6041 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
6042 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
6043 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05306044 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
6045 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
6046 if (out->config.period_size <= 0) {
6047 ALOGE("Invalid configuration period size is not valid");
6048 ret = -EINVAL;
6049 goto error_open;
6050 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306051 } else {
6052 /* primary path is the default path selected if no other outputs are available/suitable */
6053 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
6054 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
6055 }
6056 out->hal_ip_format = format = out->format;
6057 out->config.format = hal_format_to_pcm(out->hal_ip_format);
6058 out->hal_op_format = pcm_format_to_hal(out->config.format);
6059 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
6060 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07006061 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05306062 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306063 if (out->hal_ip_format != out->hal_op_format) {
6064 uint32_t buffer_size = out->config.period_size *
6065 format_to_bitwidth_table[out->hal_op_format] *
6066 out->config.channels;
6067 out->convert_buffer = calloc(1, buffer_size);
6068 if (out->convert_buffer == NULL){
6069 ALOGE("Allocation failed for convert buffer for size %d",
6070 out->compr_config.fragment_size);
6071 ret = -ENOMEM;
6072 goto error_open;
6073 }
6074 ALOGD("Convert buffer allocated of size %d", buffer_size);
6075 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006076 }
6077
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006078 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
6079 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05306080
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006081 /* TODO remove this hardcoding and check why width is zero*/
6082 if (out->bit_width == 0)
6083 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306084 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006085 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07006086 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306087 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05306088 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08006089 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
6090 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
6091 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006092 if(adev->primary_output == NULL)
6093 adev->primary_output = out;
6094 else {
6095 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006096 ret = -EEXIST;
6097 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006098 }
6099 }
6100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006101 /* Check if this usecase is already existing */
6102 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07006103 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
6104 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006105 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006106 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006107 ret = -EEXIST;
6108 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006109 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006111 pthread_mutex_unlock(&adev->lock);
6112
6113 out->stream.common.get_sample_rate = out_get_sample_rate;
6114 out->stream.common.set_sample_rate = out_set_sample_rate;
6115 out->stream.common.get_buffer_size = out_get_buffer_size;
6116 out->stream.common.get_channels = out_get_channels;
6117 out->stream.common.get_format = out_get_format;
6118 out->stream.common.set_format = out_set_format;
6119 out->stream.common.standby = out_standby;
6120 out->stream.common.dump = out_dump;
6121 out->stream.common.set_parameters = out_set_parameters;
6122 out->stream.common.get_parameters = out_get_parameters;
6123 out->stream.common.add_audio_effect = out_add_audio_effect;
6124 out->stream.common.remove_audio_effect = out_remove_audio_effect;
6125 out->stream.get_latency = out_get_latency;
6126 out->stream.set_volume = out_set_volume;
6127 out->stream.write = out_write;
6128 out->stream.get_render_position = out_get_render_position;
6129 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006130 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006131
Haynes Mathew George16081042017-05-31 17:16:49 -07006132 if (out->realtime)
6133 out->af_period_multiplier = af_period_multiplier;
6134 else
6135 out->af_period_multiplier = 1;
6136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006137 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07006138 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006139 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006140
6141 config->format = out->stream.common.get_format(&out->stream.common);
6142 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
6143 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
6144
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306145 /*
6146 By locking output stream before registering, we allow the callback
6147 to update stream's state only after stream's initial state is set to
6148 adev state.
6149 */
6150 lock_output_stream(out);
6151 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6152 pthread_mutex_lock(&adev->lock);
6153 out->card_status = adev->card_status;
6154 pthread_mutex_unlock(&adev->lock);
6155 pthread_mutex_unlock(&out->lock);
6156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006157 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306158 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006159 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006160
6161 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6162 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6163 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006164 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306165 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006166 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006167 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306168 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006169 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6170 out->usecase, PCM_PLAYBACK);
6171 hdlr_stream_cfg.flags = out->flags;
6172 hdlr_stream_cfg.type = PCM_PLAYBACK;
6173 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6174 &hdlr_stream_cfg);
6175 if (ret) {
6176 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6177 out->adsp_hdlr_stream_handle = NULL;
6178 }
6179 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306180 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006181 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006182 if (ret < 0) {
6183 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6184 out->ip_hdlr_handle = NULL;
6185 }
6186 }
Eric Laurent994a6932013-07-17 11:51:42 -07006187 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006188 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006189
6190error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306191 if (out->convert_buffer)
6192 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006193 free(out);
6194 *stream_out = NULL;
6195 ALOGD("%s: exit: ret %d", __func__, ret);
6196 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006197}
6198
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306199void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 struct audio_stream_out *stream)
6201{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006202 struct stream_out *out = (struct stream_out *)stream;
6203 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006204 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006205
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006206 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306207
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306208 // must deregister from sndmonitor first to prevent races
6209 // between the callback and close_stream
6210 audio_extn_snd_mon_unregister_listener(out);
6211
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006212 /* close adsp hdrl session before standby */
6213 if (out->adsp_hdlr_stream_handle) {
6214 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6215 if (ret)
6216 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6217 out->adsp_hdlr_stream_handle = NULL;
6218 }
6219
Manish Dewangan21a850a2017-08-14 12:03:55 +05306220 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006221 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6222 out->ip_hdlr_handle = NULL;
6223 }
6224
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006225 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306226 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006227 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306228 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306229 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006230 if(ret != 0)
6231 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6232 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006233 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006234 out_standby(&stream->common);
6235
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006236 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006237 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006238 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006239 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006240 if (out->compr_config.codec != NULL)
6241 free(out->compr_config.codec);
6242 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006243
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306244 out->a2dp_compress_mute = false;
6245
Varun Balaraje49253e2017-07-06 19:48:56 +05306246 if (is_interactive_usecase(out->usecase))
6247 free_interactive_usecase(adev, out->usecase);
6248
Ashish Jain83a6cc22016-06-28 14:34:17 +05306249 if (out->convert_buffer != NULL) {
6250 free(out->convert_buffer);
6251 out->convert_buffer = NULL;
6252 }
6253
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006254 if (adev->voice_tx_output == out)
6255 adev->voice_tx_output = NULL;
6256
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306257 if (adev->primary_output == out)
6258 adev->primary_output = NULL;
6259
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006260 pthread_cond_destroy(&out->cond);
6261 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006262 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006263 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006264}
6265
6266static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6267{
6268 struct audio_device *adev = (struct audio_device *)dev;
6269 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006270 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006271 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006272 int ret;
6273 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006275 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006276 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006277
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306278 if (!parms)
6279 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306280
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306281 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6282 if (ret >= 0) {
6283 /* When set to false, HAL should disable EC and NS */
6284 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6285 adev->bt_sco_on = true;
6286 else
6287 adev->bt_sco_on = false;
6288 }
6289
Naresh Tanniru4c630392014-05-12 01:05:52 +05306290 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006291 status = voice_set_parameters(adev, parms);
6292 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006293 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006294
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006295 status = platform_set_parameters(adev->platform, parms);
6296 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006297 goto done;
6298
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006299 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6300 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006301 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006302 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6303 adev->bluetooth_nrec = true;
6304 else
6305 adev->bluetooth_nrec = false;
6306 }
6307
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006308 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6309 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006310 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6311 adev->screen_off = false;
6312 else
6313 adev->screen_off = true;
6314 }
6315
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006316 ret = str_parms_get_int(parms, "rotation", &val);
6317 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006318 bool reverse_speakers = false;
6319 switch(val) {
6320 // FIXME: note that the code below assumes that the speakers are in the correct placement
6321 // relative to the user when the device is rotated 90deg from its default rotation. This
6322 // assumption is device-specific, not platform-specific like this code.
6323 case 270:
6324 reverse_speakers = true;
6325 break;
6326 case 0:
6327 case 90:
6328 case 180:
6329 break;
6330 default:
6331 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006332 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006333 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006334 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006335 // check and set swap
6336 // - check if orientation changed and speaker active
6337 // - set rotation and cache the rotation value
6338 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006339 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006340 }
6341
Mingming Yin514a8bc2014-07-29 15:22:21 -07006342 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6343 if (ret >= 0) {
6344 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6345 adev->bt_wb_speech_enabled = true;
6346 else
6347 adev->bt_wb_speech_enabled = false;
6348 }
6349
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006350 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6351 if (ret >= 0) {
6352 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306353 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08006354 if (audio_is_output_device(val) &&
6355 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006356 ALOGV("cache new ext disp type and edid");
6357 ret = platform_get_ext_disp_type(adev->platform);
6358 if (ret < 0) {
6359 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08006360 status = ret;
6361 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006362 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006363 platform_cache_edid(adev->platform);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306364 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07006365 /*
6366 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6367 * Per AudioPolicyManager, USB device is higher priority than WFD.
6368 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6369 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6370 * starting voice call on USB
6371 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006372 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306373 if (ret >= 0)
6374 audio_extn_usb_add_device(device, atoi(value));
6375
Zhou Song6f862822017-11-06 17:27:57 +08006376 if (!audio_extn_usb_is_tunnel_supported()) {
6377 ALOGV("detected USB connect .. disable proxy");
6378 adev->allow_afe_proxy_usage = false;
6379 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006380 }
6381 }
6382
6383 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6384 if (ret >= 0) {
6385 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306386 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07006387 /*
6388 * The HDMI / Displayport disconnect handling has been moved to
6389 * audio extension to ensure that its parameters are not
6390 * invalidated prior to updating sysfs of the disconnect event
6391 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6392 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306393 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006394 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05306395 if (ret >= 0)
6396 audio_extn_usb_remove_device(device, atoi(value));
6397
Zhou Song6f862822017-11-06 17:27:57 +08006398 if (!audio_extn_usb_is_tunnel_supported()) {
6399 ALOGV("detected USB disconnect .. enable proxy");
6400 adev->allow_afe_proxy_usage = true;
6401 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006402 }
6403 }
6404
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306405 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6406 if (ret >= 0) {
6407 struct audio_usecase *usecase;
6408 struct listnode *node;
6409 list_for_each(node, &adev->usecase_list) {
6410 usecase = node_to_item(node, struct audio_usecase, list);
6411 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006412 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306413 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006414
6415 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306416 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006417 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306418 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306419 //force device switch to re configure encoder
6420 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306421 audio_extn_a2dp_set_handoff_mode(false);
6422 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306423 break;
6424 }
6425 }
6426 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006427
6428 //handle vr audio setparam
6429 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6430 value, sizeof(value));
6431 if (ret >= 0) {
6432 ALOGI("Setting vr mode to be %s", value);
6433 if (!strncmp(value, "true", 4)) {
6434 adev->vr_audio_mode_enabled = true;
6435 ALOGI("Setting vr mode to true");
6436 } else if (!strncmp(value, "false", 5)) {
6437 adev->vr_audio_mode_enabled = false;
6438 ALOGI("Setting vr mode to false");
6439 } else {
6440 ALOGI("wrong vr mode set");
6441 }
6442 }
6443
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306444 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006445done:
6446 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006447 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306448error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006449 ALOGV("%s: exit with code(%d)", __func__, status);
6450 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006451}
6452
6453static char* adev_get_parameters(const struct audio_hw_device *dev,
6454 const char *keys)
6455{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006456 struct audio_device *adev = (struct audio_device *)dev;
6457 struct str_parms *reply = str_parms_create();
6458 struct str_parms *query = str_parms_create_str(keys);
6459 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306460 char value[256] = {0};
6461 int ret = 0;
6462
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006463 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006464 if (reply) {
6465 str_parms_destroy(reply);
6466 }
6467 if (query) {
6468 str_parms_destroy(query);
6469 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006470 ALOGE("adev_get_parameters: failed to create query or reply");
6471 return NULL;
6472 }
6473
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006474 //handle vr audio getparam
6475
6476 ret = str_parms_get_str(query,
6477 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6478 value, sizeof(value));
6479
6480 if (ret >= 0) {
6481 bool vr_audio_enabled = false;
6482 pthread_mutex_lock(&adev->lock);
6483 vr_audio_enabled = adev->vr_audio_mode_enabled;
6484 pthread_mutex_unlock(&adev->lock);
6485
6486 ALOGI("getting vr mode to %d", vr_audio_enabled);
6487
6488 if (vr_audio_enabled) {
6489 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6490 "true");
6491 goto exit;
6492 } else {
6493 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6494 "false");
6495 goto exit;
6496 }
6497 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006498
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006499 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006500 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006501 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006502 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306503 pthread_mutex_unlock(&adev->lock);
6504
Naresh Tannirud7205b62014-06-20 02:54:48 +05306505exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006506 str = str_parms_to_str(reply);
6507 str_parms_destroy(query);
6508 str_parms_destroy(reply);
6509
6510 ALOGV("%s: exit: returns - %s", __func__, str);
6511 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006512}
6513
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006514static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006515{
6516 return 0;
6517}
6518
6519static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6520{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006521 int ret;
6522 struct audio_device *adev = (struct audio_device *)dev;
6523 pthread_mutex_lock(&adev->lock);
6524 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006525 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006526 pthread_mutex_unlock(&adev->lock);
6527 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006528}
6529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006530static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6531 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006532{
6533 return -ENOSYS;
6534}
6535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006536static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6537 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006538{
6539 return -ENOSYS;
6540}
6541
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006542static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6543 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006544{
6545 return -ENOSYS;
6546}
6547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006548static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6549 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006550{
6551 return -ENOSYS;
6552}
6553
6554static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6555{
6556 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006558 pthread_mutex_lock(&adev->lock);
6559 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006560 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006561 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006562 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006563 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006564 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006565 adev->current_call_output = NULL;
6566 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006567 }
6568 pthread_mutex_unlock(&adev->lock);
6569 return 0;
6570}
6571
6572static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6573{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006574 int ret;
6575
6576 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006577 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006578 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6579 pthread_mutex_unlock(&adev->lock);
6580
6581 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006582}
6583
6584static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6585{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006586 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006587 return 0;
6588}
6589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006590static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591 const struct audio_config *config)
6592{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006593 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006594
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006595 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6596 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006597}
6598
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006599static bool adev_input_allow_hifi_record(struct audio_device *adev,
6600 audio_devices_t devices,
6601 audio_input_flags_t flags,
6602 audio_source_t source) {
6603 const bool allowed = true;
6604
6605 if (!audio_is_usb_in_device(devices))
6606 return !allowed;
6607
6608 switch (flags) {
6609 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006610 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07006611 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
6612 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006613 default:
6614 return !allowed;
6615 }
6616
6617 switch (source) {
6618 case AUDIO_SOURCE_DEFAULT:
6619 case AUDIO_SOURCE_MIC:
6620 case AUDIO_SOURCE_UNPROCESSED:
6621 break;
6622 default:
6623 return !allowed;
6624 }
6625
6626 switch (adev->mode) {
6627 case 0:
6628 break;
6629 default:
6630 return !allowed;
6631 }
6632
6633 return allowed;
6634}
6635
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006636static int adev_update_voice_comm_input_stream(struct stream_in *in,
6637 struct audio_config *config)
6638{
6639 bool valid_rate = (config->sample_rate == 8000 ||
6640 config->sample_rate == 16000 ||
6641 config->sample_rate == 32000 ||
6642 config->sample_rate == 48000);
6643 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
6644
6645#ifndef COMPRESS_VOIP_ENABLED
6646 if (valid_rate && valid_ch) {
6647 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6648 in->config = default_pcm_config_voip_copp;
6649 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
6650 DEFAULT_VOIP_BUF_DURATION_MS,
6651 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6652 } else {
6653 if (!valid_ch) config->channel_mask = 1;
6654 if (!valid_rate) config->sample_rate = 48000;
6655 return -EINVAL;
6656 }
6657 in->config.rate = config->sample_rate;
6658 in->sample_rate = config->sample_rate;
6659#else
6660 //XXX needed for voice_extn_compress_voip_open_input_stream
6661 in->config.rate = config->sample_rate;
6662 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6663 voice_extn_compress_voip_is_active(in->dev)) &&
6664 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6665 valid_rate && valid_ch) {
6666 voice_extn_compress_voip_open_input_stream(in);
6667 // update rate entries to match config from AF
6668 in->config.rate = config->sample_rate;
6669 in->sample_rate = config->sample_rate;
6670 } else {
6671 ALOGW("%s compress voip not active, use defaults", __func__);
6672 }
6673#endif
6674 return 0;
6675}
6676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006677static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006678 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006679 audio_devices_t devices,
6680 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006681 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306682 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006683 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006684 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006685{
6686 struct audio_device *adev = (struct audio_device *)dev;
6687 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006688 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006689 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006690 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306691 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006692 bool is_usb_dev = audio_is_usb_in_device(devices);
6693 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6694 devices,
6695 flags,
6696 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006699
6700 if (!(is_usb_dev && may_use_hifi_record)) {
6701 if (config->sample_rate == 0)
6702 config->sample_rate = 48000;
6703 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6704 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6705 if (config->format == AUDIO_FORMAT_DEFAULT)
6706 config->format = AUDIO_FORMAT_PCM_16_BIT;
6707
6708 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6709
6710 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6711 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006713
6714 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006715
6716 if (!in) {
6717 ALOGE("failed to allocate input stream");
6718 return -ENOMEM;
6719 }
6720
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306721 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306722 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6723 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006724 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006725 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727 in->stream.common.get_sample_rate = in_get_sample_rate;
6728 in->stream.common.set_sample_rate = in_set_sample_rate;
6729 in->stream.common.get_buffer_size = in_get_buffer_size;
6730 in->stream.common.get_channels = in_get_channels;
6731 in->stream.common.get_format = in_get_format;
6732 in->stream.common.set_format = in_set_format;
6733 in->stream.common.standby = in_standby;
6734 in->stream.common.dump = in_dump;
6735 in->stream.common.set_parameters = in_set_parameters;
6736 in->stream.common.get_parameters = in_get_parameters;
6737 in->stream.common.add_audio_effect = in_add_audio_effect;
6738 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6739 in->stream.set_gain = in_set_gain;
6740 in->stream.read = in_read;
6741 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6742
6743 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006744 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006745 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006746 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006747 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006748 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07006749 in->bit_width = 16;
6750 in->af_period_multiplier = 1;
6751
6752 /* Update config params with the requested sample rate and channels */
6753 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6754 (adev->mode != AUDIO_MODE_IN_CALL)) {
6755 ret = -EINVAL;
6756 goto err_open;
6757 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006758
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006759 if (is_usb_dev && may_use_hifi_record) {
6760 /* HiFi record selects an appropriate format, channel, rate combo
6761 depending on sink capabilities*/
6762 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
6763 &config->format,
6764 &in->supported_formats[0],
6765 MAX_SUPPORTED_FORMATS,
6766 &config->channel_mask,
6767 &in->supported_channel_masks[0],
6768 MAX_SUPPORTED_CHANNEL_MASKS,
6769 &config->sample_rate,
6770 &in->supported_sample_rates[0],
6771 MAX_SUPPORTED_SAMPLE_RATES);
6772 if (ret != 0) {
6773 ret = -EINVAL;
6774 goto err_open;
6775 }
6776 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006777 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306778 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05306779 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
6780 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
6781 in->config.format = PCM_FORMAT_S32_LE;
6782 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306783 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6784 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6785 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6786 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6787 bool ret_error = false;
6788 in->bit_width = 24;
6789 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6790 from HAL is 24_packed and 8_24
6791 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6792 24_packed return error indicating supported format is 24_packed
6793 *> In case of any other source requesting 24 bit or float return error
6794 indicating format supported is 16 bit only.
6795
6796 on error flinger will retry with supported format passed
6797 */
6798 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6799 (source != AUDIO_SOURCE_CAMCORDER)) {
6800 config->format = AUDIO_FORMAT_PCM_16_BIT;
6801 if (config->sample_rate > 48000)
6802 config->sample_rate = 48000;
6803 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07006804 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
6805 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306806 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6807 ret_error = true;
6808 }
6809
6810 if (ret_error) {
6811 ret = -EINVAL;
6812 goto err_open;
6813 }
6814 }
6815
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006816 in->channel_mask = config->channel_mask;
6817 in->format = config->format;
6818
6819 in->usecase = USECASE_AUDIO_RECORD;
6820 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
6821 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
6822 is_low_latency = true;
6823#if LOW_LATENCY_CAPTURE_USE_CASE
6824 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6825#endif
6826 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6827 }
6828
6829 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6830 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6831 in->realtime = 0;
6832 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6833 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07006834 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006835 in->stream.start = in_start;
6836 in->stream.stop = in_stop;
6837 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6838 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006839 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6840 } else if (in->realtime) {
6841 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07006842 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006843 in->config.channels = channel_count;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006844 in->sample_rate = in->config.rate;
6845 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07006846 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006847 in->usecase = USECASE_AUDIO_RECORD_HIFI;
6848 in->config = pcm_config_audio_capture;
6849 frame_size = audio_stream_in_frame_size(&in->stream);
6850 buffer_size = get_input_buffer_size(config->sample_rate,
6851 config->format,
6852 channel_count,
6853 false /*is_low_latency*/);
6854 in->config.period_size = buffer_size / frame_size;
6855 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006856 in->config.format = pcm_format_from_audio_format(config->format);
6857 in->config.channels = channel_count;
6858 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306859 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006860 if (config->sample_rate == 0)
6861 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6862 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6863 config->sample_rate != 8000) {
6864 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6865 ret = -EINVAL;
6866 goto err_open;
6867 }
6868 if (config->format == AUDIO_FORMAT_DEFAULT)
6869 config->format = AUDIO_FORMAT_PCM_16_BIT;
6870 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6871 config->format = AUDIO_FORMAT_PCM_16_BIT;
6872 ret = -EINVAL;
6873 goto err_open;
6874 }
6875
6876 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6877 in->config = pcm_config_afe_proxy_record;
6878 in->config.channels = channel_count;
6879 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306880 in->sample_rate = config->sample_rate;
Haynes Mathew George46740472017-10-27 18:40:12 -07006881 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05306882 int ret_val;
6883 pthread_mutex_lock(&adev->lock);
6884 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
6885 in, config, &channel_mask_updated);
6886 pthread_mutex_unlock(&adev->lock);
6887
6888 if (!ret_val) {
6889 if (channel_mask_updated == true) {
6890 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6891 __func__, config->channel_mask);
6892 ret = -EINVAL;
6893 goto err_open;
6894 }
6895 ALOGD("%s: created multi-channel session succesfully",__func__);
6896 } else if (audio_extn_compr_cap_enabled() &&
6897 audio_extn_compr_cap_format_supported(config->format) &&
6898 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
6899 audio_extn_compr_cap_init(in);
6900 } else if (audio_extn_cin_applicable_stream(in)) {
Sachin Mohan Gadag16273f72017-12-19 18:10:48 +05306901 in->sample_rate = config->sample_rate;
Revathi Uddarajud2634032017-12-07 14:42:34 +05306902 ret = audio_extn_cin_configure_input_stream(in);
6903 if (ret)
6904 goto err_open;
6905 } else {
6906 in->config = pcm_config_audio_capture;
6907 in->config.rate = config->sample_rate;
6908 in->config.format = pcm_format_from_audio_format(config->format);
6909 in->config.channels = channel_count;
6910 in->sample_rate = config->sample_rate;
6911 in->format = config->format;
6912 frame_size = audio_stream_in_frame_size(&in->stream);
6913 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07006914 config->format,
6915 channel_count,
6916 is_low_latency);
Revathi Uddarajud2634032017-12-07 14:42:34 +05306917 in->config.period_size = buffer_size / frame_size;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006918
Revathi Uddarajud2634032017-12-07 14:42:34 +05306919 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
6920 /* optionally use VOIP usecase depending on config(s) */
6921 ret = adev_update_voice_comm_input_stream(in, config);
6922 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006923
Revathi Uddarajud2634032017-12-07 14:42:34 +05306924 if (ret) {
6925 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
6926 goto err_open;
6927 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006928 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006929 }
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306930 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6931 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08006932 devices, flags, in->format,
6933 in->sample_rate, in->bit_width,
6934 in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306935
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006936 /* This stream could be for sound trigger lab,
6937 get sound trigger pcm if present */
6938 audio_extn_sound_trigger_check_and_get_session(in);
6939
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306940 lock_input_stream(in);
6941 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6942 pthread_mutex_lock(&adev->lock);
6943 in->card_status = adev->card_status;
6944 pthread_mutex_unlock(&adev->lock);
6945 pthread_mutex_unlock(&in->lock);
6946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006947 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006948 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006949 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006950
6951err_open:
6952 free(in);
6953 *stream_in = NULL;
6954 return ret;
6955}
6956
6957static void adev_close_input_stream(struct audio_hw_device *dev,
6958 struct audio_stream_in *stream)
6959{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006960 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006961 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006962 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306963
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306964 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006965
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306966 // must deregister from sndmonitor first to prevent races
6967 // between the callback and close_stream
6968 audio_extn_snd_mon_unregister_listener(stream);
6969
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306970 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006971 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306972
Pallavid7c7a272018-01-16 11:22:55 +05306973 if (in == NULL) {
6974 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
6975 return;
6976 }
6977
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006978 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306979 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006980 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306981 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006982 if (ret != 0)
6983 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6984 __func__, ret);
6985 } else
6986 in_standby(&stream->common);
6987
Revathi Uddarajud2634032017-12-07 14:42:34 +05306988 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006989 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006990 audio_extn_ssr_deinit();
6991 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006992
Garmond Leunge2433c32017-09-28 21:51:22 -07006993 if (audio_extn_ffv_get_stream() == in) {
6994 audio_extn_ffv_stream_deinit();
6995 }
6996
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306997 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006998 audio_extn_compr_cap_format_supported(in->config.format))
6999 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05307000
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307001 if (audio_extn_cin_attached_usecase(in->usecase))
7002 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007003
Mingming Yinfd7607b2016-01-22 12:48:44 -08007004 if (in->is_st_session) {
7005 ALOGV("%s: sound trigger pcm stop lab", __func__);
7006 audio_extn_sound_trigger_stop_lab(in);
7007 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007008 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05307009 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007010 return;
7011}
7012
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307013int adev_create_audio_patch(struct audio_hw_device *dev,
7014 unsigned int num_sources,
7015 const struct audio_port_config *sources,
7016 unsigned int num_sinks,
7017 const struct audio_port_config *sinks,
7018 audio_patch_handle_t *handle)
7019{
7020
7021
7022 return audio_extn_hw_loopback_create_audio_patch(dev,
7023 num_sources,
7024 sources,
7025 num_sinks,
7026 sinks,
7027 handle);
7028
7029}
7030
7031int adev_release_audio_patch(struct audio_hw_device *dev,
7032 audio_patch_handle_t handle)
7033{
7034 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
7035}
7036
7037int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
7038{
7039 return audio_extn_hw_loopback_get_audio_port(dev, config);
7040}
7041
7042int adev_set_audio_port_config(struct audio_hw_device *dev,
7043 const struct audio_port_config *config)
7044{
7045 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
7046}
7047
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007048static int adev_dump(const audio_hw_device_t *device __unused,
7049 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050{
7051 return 0;
7052}
7053
7054static int adev_close(hw_device_t *device)
7055{
7056 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07007057
7058 if (!adev)
7059 return 0;
7060
7061 pthread_mutex_lock(&adev_init_lock);
7062
7063 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307064 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007065 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08007066 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307067 audio_extn_utils_release_streams_cfg_lists(
7068 &adev->streams_output_cfg_list,
7069 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307070 if (audio_extn_qaf_is_enabled())
7071 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007072 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007073 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07007074 free(adev->snd_dev_ref_cnt);
7075 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007076 if (adev->adm_deinit)
7077 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307078 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007079 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307080 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307081 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007082 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307083 if (adev->device_cfg_params) {
7084 free(adev->device_cfg_params);
7085 adev->device_cfg_params = NULL;
7086 }
Kiran Kandi910e1862013-10-29 13:29:42 -07007087 free(device);
7088 adev = NULL;
7089 }
7090 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092 return 0;
7093}
7094
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007095/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
7096 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
7097 * just that it _might_ work.
7098 */
7099static int period_size_is_plausible_for_low_latency(int period_size)
7100{
7101 switch (period_size) {
7102 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07007103 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007104 case 240:
7105 case 320:
7106 case 480:
7107 return 1;
7108 default:
7109 return 0;
7110 }
7111}
7112
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307113static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
7114{
7115 bool is_snd_card_status = false;
7116 bool is_ext_device_status = false;
7117 char value[32];
7118 int card = -1;
7119 card_status_t status;
7120
7121 if (cookie != adev || !parms)
7122 return;
7123
7124 if (!parse_snd_card_status(parms, &card, &status)) {
7125 is_snd_card_status = true;
7126 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
7127 is_ext_device_status = true;
7128 } else {
7129 // not a valid event
7130 return;
7131 }
7132
7133 pthread_mutex_lock(&adev->lock);
7134 if (card == adev->snd_card || is_ext_device_status) {
7135 if (is_snd_card_status && adev->card_status != status) {
7136 adev->card_status = status;
7137 platform_snd_card_update(adev->platform, status);
7138 audio_extn_fm_set_parameters(adev, parms);
7139 } else if (is_ext_device_status) {
7140 platform_set_parameters(adev->platform, parms);
7141 }
7142 }
7143 pthread_mutex_unlock(&adev->lock);
7144 return;
7145}
7146
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307147/* out and adev lock held */
7148static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
7149{
7150 struct audio_usecase *uc_info;
7151 float left_p;
7152 float right_p;
7153 audio_devices_t devices;
7154
7155 uc_info = get_usecase_from_list(adev, out->usecase);
7156 if (uc_info == NULL) {
7157 ALOGE("%s: Could not find the usecase (%d) in the list",
7158 __func__, out->usecase);
7159 return -EINVAL;
7160 }
7161
7162 ALOGD("%s: enter: usecase(%d: %s)", __func__,
7163 out->usecase, use_case_table[out->usecase]);
7164
7165 if (restore) {
7166 // restore A2DP device for active usecases and unmute if required
7167 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
7168 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
7169 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
7170 select_devices(adev, uc_info->id);
7171 pthread_mutex_lock(&out->compr_mute_lock);
7172 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7173 (out->a2dp_compress_mute)) {
7174 out->a2dp_compress_mute = false;
7175 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
7176 }
7177 pthread_mutex_unlock(&out->compr_mute_lock);
7178 }
7179 } else {
7180 // mute compress stream if suspended
7181 pthread_mutex_lock(&out->compr_mute_lock);
7182 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
7183 (!out->a2dp_compress_mute)) {
7184 if (!out->standby) {
7185 ALOGD("%s: selecting speaker and muting stream", __func__);
7186 devices = out->devices;
7187 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
7188 left_p = out->volume_l;
7189 right_p = out->volume_r;
7190 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7191 compress_pause(out->compr);
7192 out_set_compr_volume(&out->stream, (float)0, (float)0);
7193 out->a2dp_compress_mute = true;
7194 select_devices(adev, out->usecase);
7195 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7196 compress_resume(out->compr);
7197 out->devices = devices;
7198 out->volume_l = left_p;
7199 out->volume_r = right_p;
7200 }
7201 }
7202 pthread_mutex_unlock(&out->compr_mute_lock);
7203 }
7204 ALOGV("%s: exit", __func__);
7205 return 0;
7206}
7207
7208int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7209{
7210 int ret = 0;
7211
7212 lock_output_stream(out);
7213 pthread_mutex_lock(&adev->lock);
7214
7215 ret = check_a2dp_restore_l(adev, out, restore);
7216
7217 pthread_mutex_unlock(&adev->lock);
7218 pthread_mutex_unlock(&out->lock);
7219 return ret;
7220}
7221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007222static int adev_open(const hw_module_t *module, const char *name,
7223 hw_device_t **device)
7224{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307225 int ret;
7226
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007227 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007228 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7229
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007230 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007231 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007232 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007233 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007234 ALOGD("%s: returning existing instance of adev", __func__);
7235 ALOGD("%s: exit", __func__);
7236 pthread_mutex_unlock(&adev_init_lock);
7237 return 0;
7238 }
7239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007240 adev = calloc(1, sizeof(struct audio_device));
7241
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007242 if (!adev) {
7243 pthread_mutex_unlock(&adev_init_lock);
7244 return -ENOMEM;
7245 }
7246
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007247 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7248
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307249#ifdef DYNAMIC_LOG_ENABLED
7250 register_for_dynamic_logging("hal");
7251#endif
7252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007253 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7254 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7255 adev->device.common.module = (struct hw_module_t *)module;
7256 adev->device.common.close = adev_close;
7257
7258 adev->device.init_check = adev_init_check;
7259 adev->device.set_voice_volume = adev_set_voice_volume;
7260 adev->device.set_master_volume = adev_set_master_volume;
7261 adev->device.get_master_volume = adev_get_master_volume;
7262 adev->device.set_master_mute = adev_set_master_mute;
7263 adev->device.get_master_mute = adev_get_master_mute;
7264 adev->device.set_mode = adev_set_mode;
7265 adev->device.set_mic_mute = adev_set_mic_mute;
7266 adev->device.get_mic_mute = adev_get_mic_mute;
7267 adev->device.set_parameters = adev_set_parameters;
7268 adev->device.get_parameters = adev_get_parameters;
7269 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7270 adev->device.open_output_stream = adev_open_output_stream;
7271 adev->device.close_output_stream = adev_close_output_stream;
7272 adev->device.open_input_stream = adev_open_input_stream;
7273 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307274 adev->device.create_audio_patch = adev_create_audio_patch;
7275 adev->device.release_audio_patch = adev_release_audio_patch;
7276 adev->device.get_audio_port = adev_get_audio_port;
7277 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007278 adev->device.dump = adev_dump;
7279
7280 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007281 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007282 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007283 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007284 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007286 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007287 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307288 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007289 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007290 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007291 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007292 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007293 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007294 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307295 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307296 adev->perf_lock_opts[0] = 0x101;
7297 adev->perf_lock_opts[1] = 0x20E;
7298 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007299 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007301 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007302 adev->platform = platform_init(adev);
7303 if (!adev->platform) {
7304 free(adev->snd_dev_ref_cnt);
7305 free(adev);
7306 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7307 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007308 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307309 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007310 return -EINVAL;
7311 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007312
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307313 if (audio_extn_qaf_is_enabled()) {
7314 ret = audio_extn_qaf_init(adev);
7315 if (ret < 0) {
7316 free(adev);
7317 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7318 *device = NULL;
7319 pthread_mutex_unlock(&adev_init_lock);
7320 pthread_mutex_destroy(&adev->lock);
7321 return ret;
7322 }
7323
7324 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7325 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7326 }
7327
Eric Laurentc4aef752013-09-12 17:45:53 -07007328 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7329 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7330 if (adev->visualizer_lib == NULL) {
7331 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7332 } else {
7333 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7334 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007335 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007336 "visualizer_hal_start_output");
7337 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007338 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007339 "visualizer_hal_stop_output");
7340 }
7341 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307342 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007343 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007344 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307345 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007346 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007347
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007348 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7349 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7350 if (adev->offload_effects_lib == NULL) {
7351 ALOGE("%s: DLOPEN failed for %s", __func__,
7352 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7353 } else {
7354 ALOGV("%s: DLOPEN successful for %s", __func__,
7355 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7356 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307357 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007358 "offload_effects_bundle_hal_start_output");
7359 adev->offload_effects_stop_output =
7360 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7361 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007362 adev->offload_effects_set_hpx_state =
7363 (int (*)(bool))dlsym(adev->offload_effects_lib,
7364 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307365 adev->offload_effects_get_parameters =
7366 (void (*)(struct str_parms *, struct str_parms *))
7367 dlsym(adev->offload_effects_lib,
7368 "offload_effects_bundle_get_parameters");
7369 adev->offload_effects_set_parameters =
7370 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7371 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007372 }
7373 }
7374
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007375 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7376 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7377 if (adev->adm_lib == NULL) {
7378 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7379 } else {
7380 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7381 adev->adm_init = (adm_init_t)
7382 dlsym(adev->adm_lib, "adm_init");
7383 adev->adm_deinit = (adm_deinit_t)
7384 dlsym(adev->adm_lib, "adm_deinit");
7385 adev->adm_register_input_stream = (adm_register_input_stream_t)
7386 dlsym(adev->adm_lib, "adm_register_input_stream");
7387 adev->adm_register_output_stream = (adm_register_output_stream_t)
7388 dlsym(adev->adm_lib, "adm_register_output_stream");
7389 adev->adm_deregister_stream = (adm_deregister_stream_t)
7390 dlsym(adev->adm_lib, "adm_deregister_stream");
7391 adev->adm_request_focus = (adm_request_focus_t)
7392 dlsym(adev->adm_lib, "adm_request_focus");
7393 adev->adm_abandon_focus = (adm_abandon_focus_t)
7394 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007395 adev->adm_set_config = (adm_set_config_t)
7396 dlsym(adev->adm_lib, "adm_set_config");
7397 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7398 dlsym(adev->adm_lib, "adm_request_focus_v2");
7399 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7400 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7401 adev->adm_on_routing_change = (adm_on_routing_change_t)
7402 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007403 }
7404 }
7405
Mingming Yin514a8bc2014-07-29 15:22:21 -07007406 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007407 //initialize this to false for now,
7408 //this will be set to true through set param
7409 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007410
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007411 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007412 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007413 adev->dsp_bit_width_enforce_mode =
7414 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007415
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307416 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7417 &adev->streams_output_cfg_list,
7418 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007419
Kiran Kandi910e1862013-10-29 13:29:42 -07007420 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007421
7422 char value[PROPERTY_VALUE_MAX];
7423 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007424 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007425 trial = atoi(value);
7426 if (period_size_is_plausible_for_low_latency(trial)) {
7427 pcm_config_low_latency.period_size = trial;
7428 pcm_config_low_latency.start_threshold = trial / 4;
7429 pcm_config_low_latency.avail_min = trial / 4;
7430 configured_low_latency_capture_period_size = trial;
7431 }
7432 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007433 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007434 trial = atoi(value);
7435 if (period_size_is_plausible_for_low_latency(trial)) {
7436 configured_low_latency_capture_period_size = trial;
7437 }
7438 }
7439
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007440 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007441 af_period_multiplier = atoi(value);
7442 if (af_period_multiplier < 0)
7443 af_period_multiplier = 2;
7444 else if (af_period_multiplier > 4)
7445 af_period_multiplier = 4;
7446
7447 ALOGV("new period_multiplier = %d", af_period_multiplier);
7448 }
7449
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007450 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007451 pthread_mutex_unlock(&adev_init_lock);
7452
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007453 if (adev->adm_init)
7454 adev->adm_data = adev->adm_init();
7455
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307456 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307457 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007458 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307459
7460 audio_extn_snd_mon_init();
7461 pthread_mutex_lock(&adev->lock);
7462 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7463 adev->card_status = CARD_STATUS_ONLINE;
7464 pthread_mutex_unlock(&adev->lock);
7465 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307466 /* Allocate memory for Device config params */
7467 adev->device_cfg_params = (struct audio_device_config_param*)
7468 calloc(platform_get_max_codec_backend(),
7469 sizeof(struct audio_device_config_param));
7470 if (adev->device_cfg_params == NULL)
7471 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307472
Eric Laurent994a6932013-07-17 11:51:42 -07007473 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007474 return 0;
7475}
7476
7477static struct hw_module_methods_t hal_module_methods = {
7478 .open = adev_open,
7479};
7480
7481struct audio_module HAL_MODULE_INFO_SYM = {
7482 .common = {
7483 .tag = HARDWARE_MODULE_TAG,
7484 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7485 .hal_api_version = HARDWARE_HAL_API_VERSION,
7486 .id = AUDIO_HARDWARE_MODULE_ID,
7487 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007488 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007489 .methods = &hal_module_methods,
7490 },
7491};